From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: [PATCH] Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- .gitignore | 1 + adv_cmds/.upstream_base_commits | 3 + adv_cmds/adv_cmds.xcodeproj/project.pbxproj | 1806 ++++ .../contents.xcworkspacedata | 7 + adv_cmds/cap_mkdb/cap_mkdb.1 | 101 + adv_cmds/cap_mkdb/cap_mkdb.c | 228 + adv_cmds/colldef/colldef.1 | 274 + adv_cmds/colldef/common.h | 36 + adv_cmds/colldef/locale/collate.h | 121 + adv_cmds/colldef/parse.y | 1416 +++ adv_cmds/colldef/scan.l | 398 + adv_cmds/finger/extern.h | 68 + adv_cmds/finger/finger.1 | 257 + adv_cmds/finger/finger.c | 416 + adv_cmds/finger/finger.conf.5 | 91 + adv_cmds/finger/finger.h | 78 + adv_cmds/finger/lprint.c | 367 + adv_cmds/finger/net.c | 250 + adv_cmds/finger/pathnames.h | 41 + adv_cmds/finger/sprint.c | 187 + adv_cmds/finger/util.c | 419 + adv_cmds/gencat/gencat.1 | 177 + adv_cmds/gencat/gencat.c | 199 + adv_cmds/gencat/gencat.h | 87 + adv_cmds/gencat/genlib.c | 836 ++ adv_cmds/last/last.1 | 111 + adv_cmds/last/last.c | 419 + adv_cmds/locale/locale.1 | 101 + adv_cmds/locale/locale.cc | 428 + adv_cmds/localedef/charmap.p-1 | 23 + adv_cmds/localedef/charmap.p-2 | 115 + adv_cmds/localedef/charmap.test | 38 + adv_cmds/localedef/def.a55 | 6 + adv_cmds/localedef/def.p-1 | 157 + adv_cmds/localedef/def.p-2 | 280 + adv_cmds/localedef/localedef.1 | 122 + adv_cmds/localedef/localedef.pl | 1166 +++ adv_cmds/lsvfs/lsvfs.1 | 67 + adv_cmds/lsvfs/lsvfs.c | 99 + adv_cmds/mklocale/extern.h | 40 + adv_cmds/mklocale/ldef.h | 68 + adv_cmds/mklocale/lex.l | 179 + adv_cmds/mklocale/mklocale.1 | 308 + adv_cmds/mklocale/runefile.h | 87 + adv_cmds/mklocale/yacc.y | 929 ++ adv_cmds/pkill/entitlements.plist | 8 + adv_cmds/pkill/pkill.1 | 232 + adv_cmds/pkill/pkill.c | 1111 ++ adv_cmds/ps/entitlements.plist | 10 + adv_cmds/ps/extern.h | 98 + adv_cmds/ps/fmt.c | 132 + adv_cmds/ps/keyword.c | 340 + adv_cmds/ps/nlist.c | 86 + adv_cmds/ps/print.c | 1225 +++ adv_cmds/ps/ps.1 | 663 ++ adv_cmds/ps/ps.c | 1373 +++ adv_cmds/ps/ps.h | 131 + adv_cmds/ps/tasks.c | 246 + adv_cmds/stty/cchar.c | 153 + adv_cmds/stty/extern.h | 49 + adv_cmds/stty/gfmt.c | 135 + adv_cmds/stty/key.c | 297 + adv_cmds/stty/modes.c | 308 + adv_cmds/stty/print.c | 291 + adv_cmds/stty/stty.1 | 633 ++ adv_cmds/stty/stty.c | 164 + adv_cmds/stty/stty.h | 59 + adv_cmds/stty/util.c | 68 + adv_cmds/tabs/tabs.1 | 160 + adv_cmds/tabs/tabs.c | 240 + adv_cmds/tty/tty.1 | 87 + adv_cmds/tty/tty.c | 83 + adv_cmds/whois/whois.1 | 287 + adv_cmds/whois/whois.c | 629 ++ adv_cmds/xcodescripts/variant_links.sh | 11 + .../basic_cmds.xcodeproj/project.pbxproj | 546 + basic_cmds/mesg/mesg.1 | 112 + basic_cmds/mesg/mesg.c | 116 + basic_cmds/uudecode/base64.c | 317 + basic_cmds/uudecode/uudecode.1 | 1 + basic_cmds/uudecode/uudecode.c | 504 + basic_cmds/uuencode/base64.c | 317 + basic_cmds/uuencode/uuencode.1 | 192 + basic_cmds/uuencode/uuencode.5 | 100 + basic_cmds/uuencode/uuencode.c | 226 + basic_cmds/write/write.1 | 106 + basic_cmds/write/write.c | 332 + bootstrap_cmds/.gitignore | 6 + bootstrap_cmds/APPLE_LICENSE | 335 + bootstrap_cmds/mig.xcodeproj/project.pbxproj | 310 + bootstrap_cmds/migcom.tproj/alloc.h | 54 + bootstrap_cmds/migcom.tproj/error.c | 111 + bootstrap_cmds/migcom.tproj/error.h | 61 + bootstrap_cmds/migcom.tproj/global.c | 151 + bootstrap_cmds/migcom.tproj/global.h | 113 + bootstrap_cmds/migcom.tproj/handler.c | 754 ++ bootstrap_cmds/migcom.tproj/header.c | 569 + bootstrap_cmds/migcom.tproj/lexxer.h | 52 + bootstrap_cmds/migcom.tproj/lexxer.l | 314 + bootstrap_cmds/migcom.tproj/mig.1 | 88 + bootstrap_cmds/migcom.tproj/mig.c | 405 + bootstrap_cmds/migcom.tproj/mig.sh | 218 + bootstrap_cmds/migcom.tproj/mig_errors.h | 84 + bootstrap_cmds/migcom.tproj/mig_machine.h | 16 + bootstrap_cmds/migcom.tproj/migcom.1 | 73 + bootstrap_cmds/migcom.tproj/parser.y | 803 ++ bootstrap_cmds/migcom.tproj/routine.c | 1844 ++++ bootstrap_cmds/migcom.tproj/routine.h | 549 + bootstrap_cmds/migcom.tproj/server.c | 2772 +++++ bootstrap_cmds/migcom.tproj/statement.c | 68 + bootstrap_cmds/migcom.tproj/statement.h | 98 + bootstrap_cmds/migcom.tproj/strdefs.h | 93 + bootstrap_cmds/migcom.tproj/string.c | 132 + bootstrap_cmds/migcom.tproj/type.c | 899 ++ bootstrap_cmds/migcom.tproj/type.h | 270 + bootstrap_cmds/migcom.tproj/user.c | 3260 ++++++ bootstrap_cmds/migcom.tproj/utils.c | 1043 ++ bootstrap_cmds/migcom.tproj/utils.h | 140 + bootstrap_cmds/migcom.tproj/write.h | 78 + bootstrap_cmds/xcodescripts/install-mig.sh | 8 + developer_cmds/asa/asa.1 | 85 + developer_cmds/asa/asa.c | 131 + developer_cmds/ctags/C.c | 555 + developer_cmds/ctags/ctags.1 | 221 + developer_cmds/ctags/ctags.c | 282 + developer_cmds/ctags/ctags.h | 92 + developer_cmds/ctags/fortran.c | 175 + developer_cmds/ctags/lisp.c | 112 + developer_cmds/ctags/print.c | 122 + developer_cmds/ctags/test/ctags.test | 69 + developer_cmds/ctags/tree.c | 142 + developer_cmds/ctags/yacc.c | 158 + .../developer_cmds.xcodeproj/project.pbxproj | 787 ++ .../contents.xcworkspacedata | 7 + developer_cmds/indent/args.c | 327 + developer_cmds/indent/indent.1 | 559 + developer_cmds/indent/indent.c | 1234 +++ developer_cmds/indent/indent.h | 47 + developer_cmds/indent/indent_codes.h | 70 + developer_cmds/indent/indent_globs.h | 329 + developer_cmds/indent/io.c | 667 ++ developer_cmds/indent/lexi.c | 608 ++ developer_cmds/indent/parse.c | 332 + developer_cmds/indent/pr_comment.c | 429 + developer_cmds/lorder/lorder.1 | 75 + developer_cmds/lorder/lorder.sh | 104 + developer_cmds/rpcgen/rpc_clntout.c | 230 + developer_cmds/rpcgen/rpc_cout.c | 741 ++ developer_cmds/rpcgen/rpc_hout.c | 534 + developer_cmds/rpcgen/rpc_main.c | 1170 +++ developer_cmds/rpcgen/rpc_parse.c | 643 ++ developer_cmds/rpcgen/rpc_parse.h | 168 + developer_cmds/rpcgen/rpc_sample.c | 261 + developer_cmds/rpcgen/rpc_scan.c | 521 + developer_cmds/rpcgen/rpc_scan.h | 104 + developer_cmds/rpcgen/rpc_svcout.c | 980 ++ developer_cmds/rpcgen/rpc_tblout.c | 179 + developer_cmds/rpcgen/rpc_util.c | 513 + developer_cmds/rpcgen/rpc_util.h | 178 + developer_cmds/rpcgen/rpcgen.1 | 452 + developer_cmds/unifdef/unifdef.1 | 415 + developer_cmds/unifdef/unifdef.c | 1235 +++ developer_cmds/unifdef/unifdefall.sh | 79 + developer_cmds/xcodescripts/install-lorder.sh | 7 + .../xcodescripts/install-unifdefall.sh | 9 + diskdev_cmds/APPLE_LICENSE | 367 + diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 | 81 + diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c | 202 + .../diskdev_cmds.xcodeproj/project.pbxproj | 2411 +++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcschemes/All_MacOSX.xcscheme | 61 + .../xcshareddata/xcschemes/All_iOS.xcscheme | 61 + .../xcshareddata/xcschemes/Common.xcscheme | 61 + .../xcshareddata/xcschemes/dev_mkdb.xcscheme | 88 + .../xcshareddata/xcschemes/edquota.xcscheme | 88 + .../xcshareddata/xcschemes/fdisk.xcscheme | 88 + .../xcshareddata/xcschemes/fsck.xcscheme | 88 + .../xcshareddata/xcschemes/fstyp.xcscheme | 88 + .../xcschemes/fstyp_msdos.xcscheme | 88 + .../xcschemes/fstyp_ntfs.xcscheme | 88 + .../xcshareddata/xcschemes/fstyp_udf.xcscheme | 88 + .../xcshareddata/xcschemes/fuser.xcscheme | 88 + .../xcshareddata/xcschemes/libdisk.xcscheme | 61 + .../xcshareddata/xcschemes/mount.xcscheme | 88 + .../xcschemes/mount_devfs.xcscheme | 88 + .../xcschemes/mount_fdesc.xcscheme | 88 + .../xcshareddata/xcschemes/quota.xcscheme | 88 + .../xcschemes/quotacheck.xcscheme | 88 + .../xcshareddata/xcschemes/quotaon.xcscheme | 88 + .../xcshareddata/xcschemes/repquota.xcscheme | 88 + .../xcshareddata/xcschemes/setclass.xcscheme | 88 + .../xcshareddata/xcschemes/umount.xcscheme | 88 + .../xcshareddata/xcschemes/vndevice.xcscheme | 88 + .../xcshareddata/xcschemes/vsdbutil.xcscheme | 88 + diskdev_cmds/disklib/dkcksum.c | 77 + diskdev_cmds/disklib/dkdisklabel.c | 193 + diskdev_cmds/disklib/dkopen.c | 57 + diskdev_cmds/disklib/dkopen.h | 56 + diskdev_cmds/disklib/dksecsize.c | 75 + diskdev_cmds/disklib/pathnames.h | 63 + diskdev_cmds/disklib/preen.c | 392 + diskdev_cmds/disklib/vfslist.c | 112 + diskdev_cmds/edquota.tproj/edquota.8 | 184 + diskdev_cmds/edquota.tproj/edquota.c | 1228 +++ diskdev_cmds/edquota.tproj/pathnames.h | 61 + diskdev_cmds/edt_fstab/edt_fstab.c | 180 + diskdev_cmds/edt_fstab/edt_fstab.h | 47 + diskdev_cmds/fdisk.tproj/auto.c | 155 + diskdev_cmds/fdisk.tproj/auto.h | 31 + diskdev_cmds/fdisk.tproj/cmd.c | 507 + diskdev_cmds/fdisk.tproj/cmd.h | 105 + diskdev_cmds/fdisk.tproj/disk.c | 309 + diskdev_cmds/fdisk.tproj/disk.h | 83 + diskdev_cmds/fdisk.tproj/fdisk.8 | 377 + diskdev_cmds/fdisk.tproj/fdisk.c | 289 + diskdev_cmds/fdisk.tproj/getrawpartition.c | 87 + diskdev_cmds/fdisk.tproj/mbr.c | 553 + diskdev_cmds/fdisk.tproj/mbr.h | 114 + diskdev_cmds/fdisk.tproj/mbrcode.h | 119 + diskdev_cmds/fdisk.tproj/misc.c | 183 + diskdev_cmds/fdisk.tproj/misc.h | 74 + diskdev_cmds/fdisk.tproj/opendev.c | 111 + diskdev_cmds/fdisk.tproj/part.c | 425 + diskdev_cmds/fdisk.tproj/part.h | 80 + diskdev_cmds/fdisk.tproj/user.c | 275 + diskdev_cmds/fdisk.tproj/user.h | 65 + diskdev_cmds/fdisk.tproj/util.h | 137 + diskdev_cmds/fsck.tproj/fsck.8 | 176 + diskdev_cmds/fsck.tproj/fsck.c | 1339 +++ diskdev_cmds/fsck.tproj/fsck.h | 121 + diskdev_cmds/fstyp.tproj/fstyp.8 | 41 + diskdev_cmds/fstyp.tproj/fstyp.c | 167 + diskdev_cmds/fstyp.tproj/fstyp_msdos.8 | 41 + diskdev_cmds/fstyp.tproj/fstyp_msdos.c | 213 + diskdev_cmds/fstyp.tproj/fstyp_ntfs.8 | 41 + diskdev_cmds/fstyp.tproj/fstyp_ntfs.c | 206 + diskdev_cmds/fstyp.tproj/fstyp_udf.8 | 40 + diskdev_cmds/fstyp.tproj/fstyp_udf.c | 306 + diskdev_cmds/fuser.tproj/fuser.1 | 200 + diskdev_cmds/fuser.tproj/fuser.pl | 92 + diskdev_cmds/mount.tproj/fstab.5 | 222 + diskdev_cmds/mount.tproj/mount.8 | 293 + diskdev_cmds/mount.tproj/mount.c | 1696 +++ diskdev_cmds/mount.tproj/mount.entitlements | 12 + diskdev_cmds/mount.tproj/pathnames.h | 63 + diskdev_cmds/mount_devfs.tproj/mount_devfs.c | 117 + diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8 | 171 + diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c | 128 + diskdev_cmds/mount_flags_dir/mount_flags.c | 88 + diskdev_cmds/mount_flags_dir/mount_flags.h | 66 + diskdev_cmds/quota.tproj/quota.1 | 137 + diskdev_cmds/quota.tproj/quota.c | 858 ++ .../quotacheck.tproj/hfs_quotacheck.c | 169 + diskdev_cmds/quotacheck.tproj/quotacheck.8 | 156 + diskdev_cmds/quotacheck.tproj/quotacheck.c | 972 ++ diskdev_cmds/quotacheck.tproj/quotacheck.h | 87 + diskdev_cmds/quotaon.tproj/quotaon.8 | 159 + diskdev_cmds/quotaon.tproj/quotaon.c | 400 + diskdev_cmds/repquota.tproj/repquota.8 | 109 + diskdev_cmds/repquota.tproj/repquota.c | 630 ++ diskdev_cmds/setclass.tproj/setclass.8 | 46 + diskdev_cmds/setclass.tproj/setclass.c | 153 + diskdev_cmds/umount.tproj/umount.8 | 133 + diskdev_cmds/umount.tproj/umount.c | 655 ++ diskdev_cmds/vndevice.tproj/vndevice.c | 134 + .../vsdbutil.tproj/com.apple.vsdbutil.plist | 21 + diskdev_cmds/vsdbutil.tproj/vsdbutil.8 | 49 + diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c | 1213 +++ doc_cmds/checknr/checknr.1 | 163 + doc_cmds/checknr/checknr.c | 607 ++ doc_cmds/colcrt/colcrt.1 | 124 + doc_cmds/colcrt/colcrt.c | 287 + doc_cmds/doc_cmds.plist | 72 + doc_cmds/doc_cmds.txt | 134 + doc_cmds/doc_cmds.xcodeproj/project.pbxproj | 538 + doc_cmds/intro.1 | 74 + doc_cmds/makewhatis/makewhatis.8 | 133 + doc_cmds/makewhatis/makewhatis.c | 1094 ++ doc_cmds/makewhatis/makewhatis.local.8 | 69 + doc_cmds/makewhatis/makewhatis.local.sh | 64 + file_cmds/.upstream_base_commits | 2 + file_cmds/chflags/chflags.1 | 185 + file_cmds/chflags/chflags.c | 204 + file_cmds/chmod/chmod.1 | 604 ++ file_cmds/chmod/chmod.c | 458 + file_cmds/chmod/chmod_acl.c | 859 ++ file_cmds/chmod/chmod_acl.h | 90 + file_cmds/chown/chgrp.1 | 144 + file_cmds/chown/chown.8 | 177 + file_cmds/chown/chown.c | 345 + file_cmds/cksum/cksum.1 | 182 + file_cmds/cksum/cksum.c | 148 + file_cmds/cksum/crc.c | 148 + file_cmds/cksum/crc32.c | 122 + file_cmds/cksum/extern.h | 52 + file_cmds/cksum/print.c | 75 + file_cmds/cksum/sum.1 | 1 + file_cmds/cksum/sum1.c | 77 + file_cmds/cksum/sum2.c | 79 + file_cmds/compress/compress.1 | 253 + file_cmds/compress/compress.c | 467 + file_cmds/compress/doc/NOTES | 142 + file_cmds/compress/doc/README | 284 + file_cmds/compress/doc/revision.log | 118 + file_cmds/compress/uncompress.1 | 1 + file_cmds/compress/zcat.sh | 38 + file_cmds/compress/zopen.3 | 137 + file_cmds/compress/zopen.c | 738 ++ file_cmds/compress/zopen.h | 34 + file_cmds/cp/cp.1 | 311 + file_cmds/cp/cp.c | 571 + file_cmds/cp/extern.h | 61 + file_cmds/cp/utils.c | 541 + file_cmds/csh/strpct.c | 99 + file_cmds/dd/args.c | 421 + file_cmds/dd/conv.c | 273 + file_cmds/dd/conv_tab.c | 289 + file_cmds/dd/dd.1 | 382 + file_cmds/dd/dd.c | 481 + file_cmds/dd/dd.entitlements | 9 + file_cmds/dd/dd.h | 102 + file_cmds/dd/extern.h | 73 + file_cmds/dd/install_symlink.sh | 16 + file_cmds/dd/misc.c | 108 + file_cmds/dd/position.c | 169 + file_cmds/df/df.1 | 217 + file_cmds/df/df.c | 639 ++ file_cmds/df/vfslist.c | 103 + file_cmds/du/du.1 | 172 + file_cmds/du/du.c | 730 ++ file_cmds/file_cmds.xcodeproj/project.pbxproj | 3984 +++++++ file_cmds/gzip/futimens.c | 100 + file_cmds/gzip/gzexe | 179 + file_cmds/gzip/gzexe.1 | 73 + file_cmds/gzip/gzip.1 | 234 + file_cmds/gzip/gzip.c | 2256 ++++ file_cmds/gzip/gzip.plist | 29 + file_cmds/gzip/gzip.xcconfig | 49 + file_cmds/gzip/install_scripts.sh | 22 + file_cmds/gzip/unbzip2.c | 141 + file_cmds/gzip/unpack.c | 329 + file_cmds/gzip/unxz.c | 153 + file_cmds/gzip/zdiff | 142 + file_cmds/gzip/zdiff.1 | 142 + file_cmds/gzip/zforce | 55 + file_cmds/gzip/zforce.1 | 53 + file_cmds/gzip/zmore | 82 + file_cmds/gzip/zmore.1 | 110 + file_cmds/gzip/znew | 137 + file_cmds/gzip/znew.1 | 71 + file_cmds/gzip/zuncompress.c | 396 + file_cmds/install/install.1 | 253 + file_cmds/install/pathnames.h | 41 + file_cmds/install/xinstall.c | 816 ++ file_cmds/ipcrm/ipcrm.1 | 84 + file_cmds/ipcrm/ipcrm.c | 179 + file_cmds/ipcs/ipcs.1 | 132 + file_cmds/ipcs/ipcs.c | 553 + file_cmds/ln/link.1 | 1 + file_cmds/ln/ln.1 | 233 + file_cmds/ln/ln.c | 272 + file_cmds/ln/symlink.7 | 457 + file_cmds/ls/cmp.c | 226 + file_cmds/ls/extern.h | 73 + file_cmds/ls/ls.1 | 715 ++ file_cmds/ls/ls.c | 977 ++ file_cmds/ls/ls.h | 108 + file_cmds/ls/print.c | 837 ++ file_cmds/ls/util.c | 231 + file_cmds/mkdir/mkdir.1 | 108 + file_cmds/mkdir/mkdir.c | 144 + file_cmds/mkfifo/mkfifo.1 | 103 + file_cmds/mkfifo/mkfifo.c | 128 + file_cmds/mknod/mknod.8 | 137 + file_cmds/mknod/mknod.c | 405 + file_cmds/mtree/commoncrypto.c | 378 + file_cmds/mtree/commoncrypto.h | 36 + file_cmds/mtree/compare.c | 688 ++ file_cmds/mtree/create.c | 611 ++ file_cmds/mtree/excludes.c | 114 + file_cmds/mtree/extern.h | 71 + file_cmds/mtree/fix_failure_locations.py | 77 + file_cmds/mtree/metrics.c | 155 + file_cmds/mtree/metrics.h | 48 + file_cmds/mtree/misc.c | 189 + file_cmds/mtree/mtree.8 | 393 + file_cmds/mtree/mtree.c | 358 + file_cmds/mtree/mtree.h | 120 + file_cmds/mtree/spec.c | 470 + file_cmds/mtree/specspec.c | 327 + file_cmds/mtree/test/test00.sh | 67 + file_cmds/mtree/test/test01.sh | 40 + file_cmds/mtree/test/test02.sh | 36 + file_cmds/mtree/test/test03.sh | 60 + file_cmds/mtree/test/test04.sh | 51 + file_cmds/mtree/verify.c | 341 + file_cmds/mv/mv.1 | 184 + file_cmds/mv/mv.c | 505 + file_cmds/mv/pathnames.h | 45 + file_cmds/pathchk/pathchk.1 | 121 + file_cmds/pathchk/pathchk.c | 196 + file_cmds/pax/ar_io.c | 1318 +++ file_cmds/pax/ar_subs.c | 1517 +++ file_cmds/pax/buf_subs.c | 994 ++ file_cmds/pax/cache.c | 426 + file_cmds/pax/cache.h | 78 + file_cmds/pax/cpio.1 | 304 + file_cmds/pax/cpio.c | 1149 +++ file_cmds/pax/cpio.h | 155 + file_cmds/pax/extern.h | 347 + file_cmds/pax/file_subs.c | 1180 +++ file_cmds/pax/ftree.c | 585 ++ file_cmds/pax/ftree.h | 56 + file_cmds/pax/gen_subs.c | 458 + file_cmds/pax/getoldopt.c | 74 + file_cmds/pax/options.c | 1747 ++++ file_cmds/pax/options.h | 118 + file_cmds/pax/pat_rep.c | 1211 +++ file_cmds/pax/pat_rep.h | 56 + file_cmds/pax/pax.1 | 1185 +++ file_cmds/pax/pax.c | 446 + file_cmds/pax/pax.h | 255 + file_cmds/pax/pax_format.c | 1624 +++ file_cmds/pax/pax_format.h | 158 + file_cmds/pax/sel_subs.c | 614 ++ file_cmds/pax/sel_subs.h | 77 + file_cmds/pax/tables.c | 1278 +++ file_cmds/pax/tables.h | 175 + file_cmds/pax/tar.c | 1206 +++ file_cmds/pax/tar.h | 161 + file_cmds/pax/tty_subs.c | 200 + file_cmds/rm/rm.1 | 216 + file_cmds/rm/rm.c | 601 ++ file_cmds/rm/unlink.1 | 1 + file_cmds/rmdir/rmdir.1 | 100 + file_cmds/rmdir/rmdir.c | 122 + file_cmds/rmt/rmt.8 | 220 + file_cmds/rmt/rmt.c | 259 + file_cmds/shar/shar.1 | 105 + file_cmds/shar/shar.sh | 76 + file_cmds/stat/readlink.1 | 1 + file_cmds/stat/stat.1 | 534 + file_cmds/stat/stat.c | 1004 ++ file_cmds/tests/chgrp.sh | 26 + file_cmds/tests/file_cmds.plist | 33 + file_cmds/touch/touch.1 | 221 + file_cmds/touch/touch.c | 430 + file_cmds/xcodescripts/hardlink.sh | 16 + mail_cmds/Makefile | 5 + mail_cmds/biff/Makefile | 10 + mail_cmds/biff/biff.1 | 127 + mail_cmds/biff/biff.c | 117 + mail_cmds/comsat/Makefile | 11 + mail_cmds/comsat/comsat.8 | 115 + mail_cmds/comsat/comsat.c | 314 + mail_cmds/comsat/comsat.plist | 29 + mail_cmds/from/Makefile | 10 + mail_cmds/from/from.1 | 99 + mail_cmds/from/from.c | 173 + mail_cmds/mail/Makefile | 24 + mail_cmds/mail/USD.doc/Makefile | 12 + mail_cmds/mail/USD.doc/mail0.nr | 71 + mail_cmds/mail/USD.doc/mail1.nr | 92 + mail_cmds/mail/USD.doc/mail2.nr | 617 ++ mail_cmds/mail/USD.doc/mail3.nr | 133 + mail_cmds/mail/USD.doc/mail4.nr | 437 + mail_cmds/mail/USD.doc/mail5.nr | 1042 ++ mail_cmds/mail/USD.doc/mail6.nr | 125 + mail_cmds/mail/USD.doc/mail7.nr | 107 + mail_cmds/mail/USD.doc/mail8.nr | 75 + mail_cmds/mail/USD.doc/mail9.nr | 203 + mail_cmds/mail/USD.doc/maila.nr | 33 + mail_cmds/mail/aux.c | 635 ++ mail_cmds/mail/cmd1.c | 487 + mail_cmds/mail/cmd2.c | 587 ++ mail_cmds/mail/cmd3.c | 840 ++ mail_cmds/mail/cmdtab.c | 133 + mail_cmds/mail/collect.c | 998 ++ mail_cmds/mail/def.h | 283 + mail_cmds/mail/edit.c | 231 + mail_cmds/mail/extern.h | 268 + mail_cmds/mail/fio.c | 475 + mail_cmds/mail/getname.c | 77 + mail_cmds/mail/glob.h | 112 + mail_cmds/mail/head.c | 291 + mail_cmds/mail/lex.c | 736 ++ mail_cmds/mail/list.c | 843 ++ mail_cmds/mail/mail.1 | 1272 +++ mail_cmds/mail/mailx.1 | 1 + mail_cmds/mail/main.c | 395 + mail_cmds/mail/misc/mail.help | 23 + mail_cmds/mail/misc/mail.rc | 2 + mail_cmds/mail/misc/mail.tildehelp | 36 + mail_cmds/mail/names.c | 793 ++ mail_cmds/mail/pathnames.h | 47 + mail_cmds/mail/popen.c | 402 + mail_cmds/mail/quit.c | 505 + mail_cmds/mail/rcv.h | 52 + mail_cmds/mail/send.c | 629 ++ mail_cmds/mail/strings.c | 131 + mail_cmds/mail/strlcpy.c | 74 + mail_cmds/mail/temp.c | 94 + mail_cmds/mail/tty.c | 306 + mail_cmds/mail/v7.local.c | 101 + mail_cmds/mail/vars.c | 196 + mail_cmds/mail/version.c | 48 + mail_cmds/msgs/Makefile | 11 + mail_cmds/msgs/msgs.1 | 236 + mail_cmds/msgs/msgs.c | 923 ++ mail_cmds/msgs/pathnames.h | 40 + misc_cmds/calendar/calendar.1 | 265 + misc_cmds/calendar/calendar.c | 153 + misc_cmds/calendar/calendar.h | 93 + misc_cmds/calendar/calendars/calendar.all | 20 + .../calendar/calendars/calendar.australia | 58 + .../calendar/calendars/calendar.birthday | 299 + .../calendar/calendars/calendar.christian | 32 + .../calendar/calendars/calendar.computer | 76 + .../calendar/calendars/calendar.croatian | 12 + misc_cmds/calendar/calendars/calendar.dutch | 78 + misc_cmds/calendar/calendars/calendar.freebsd | 283 + misc_cmds/calendar/calendars/calendar.french | 12 + misc_cmds/calendar/calendars/calendar.german | 12 + misc_cmds/calendar/calendars/calendar.history | 476 + misc_cmds/calendar/calendars/calendar.holiday | 563 + .../calendar/calendars/calendar.hungarian | 12 + misc_cmds/calendar/calendars/calendar.judaic | 227 + misc_cmds/calendar/calendars/calendar.lotr | 48 + misc_cmds/calendar/calendars/calendar.music | 240 + .../calendar/calendars/calendar.newzealand | 25 + misc_cmds/calendar/calendars/calendar.russian | 12 + .../calendar/calendars/calendar.southafrica | 23 + .../calendar/calendars/calendar.ukrainian | 12 + .../calendar/calendars/calendar.usholiday | 42 + misc_cmds/calendar/calendars/calendar.world | 19 + .../de_AT.ISO_8859-15/calendar.feiertag | 62 + .../calendars/de_DE.ISO8859-1/calendar.all | 17 + .../de_DE.ISO8859-1/calendar.feiertag | 56 + .../de_DE.ISO8859-1/calendar.geschichte | 198 + .../calendars/de_DE.ISO8859-1/calendar.kirche | 32 + .../de_DE.ISO8859-1/calendar.literatur | 54 + .../calendars/de_DE.ISO8859-1/calendar.musik | 66 + .../de_DE.ISO8859-1/calendar.wissenschaft | 19 + .../calendars/fr_FR.ISO8859-1/calendar.all | 14 + .../calendars/fr_FR.ISO8859-1/calendar.fetes | 630 ++ .../calendars/fr_FR.ISO8859-1/calendar.french | 12 + .../fr_FR.ISO8859-1/calendar.jferies | 46 + .../fr_FR.ISO8859-1/calendar.proverbes | 354 + .../calendars/hr_HR.ISO8859-2/calendar.all | 12 + .../hr_HR.ISO8859-2/calendar.praznici | 44 + .../calendars/hu_HU.ISO8859-2/calendar.all | 13 + .../hu_HU.ISO8859-2/calendar.nevnapok | 386 + .../hu_HU.ISO8859-2/calendar.unnepek | 53 + .../calendars/ru_RU.KOI8-R/calendar.all | 17 + .../calendars/ru_RU.KOI8-R/calendar.common | 90 + .../calendars/ru_RU.KOI8-R/calendar.holiday | 25 + .../calendars/ru_RU.KOI8-R/calendar.military | 27 + .../calendars/ru_RU.KOI8-R/calendar.msk | 16 + .../calendars/ru_RU.KOI8-R/calendar.orthodox | 34 + .../calendars/ru_RU.KOI8-R/calendar.pagan | 42 + .../calendars/uk_UA.KOI8-U/calendar.all | 14 + .../calendars/uk_UA.KOI8-U/calendar.holiday | 22 + .../calendars/uk_UA.KOI8-U/calendar.misc | 18 + .../calendars/uk_UA.KOI8-U/calendar.orthodox | 35 + misc_cmds/calendar/day.c | 498 + misc_cmds/calendar/io.c | 470 + misc_cmds/calendar/ostern.c | 111 + misc_cmds/calendar/paskha.c | 93 + misc_cmds/calendar/pathnames.h | 40 + misc_cmds/leave/leave.1 | 100 + misc_cmds/leave/leave.c | 196 + misc_cmds/misc_cmds.xcodeproj/project.pbxproj | 971 ++ misc_cmds/ncal/calendar.c | 330 + misc_cmds/ncal/calendar.h | 42 + misc_cmds/ncal/easter.c | 101 + misc_cmds/ncal/ncal.1 | 198 + misc_cmds/ncal/ncal.c | 1177 +++ misc_cmds/tsort/tsort.1 | 90 + misc_cmds/tsort/tsort.c | 443 + misc_cmds/units/pathnames.h | 33 + misc_cmds/units/units.1 | 181 + misc_cmds/units/units.c | 749 ++ misc_cmds/units/units.lib | 732 ++ network_cmds/APPLE_LICENSE | 370 + network_cmds/arp.tproj/IMPORT_NOTES | 3 + network_cmds/arp.tproj/arp.8 | 251 + network_cmds/arp.tproj/arp.c | 1163 +++ network_cmds/arp.tproj/arp4.4 | 123 + network_cmds/cfilutil/cfilstat.c | 341 + network_cmds/cfilutil/cfilutil.1 | 56 + network_cmds/cfilutil/cfilutil.c | 987 ++ network_cmds/dnctl/dnctl.8 | 508 + network_cmds/dnctl/dnctl.c | 1313 +++ network_cmds/ecnprobe/base.h | 57 + network_cmds/ecnprobe/capture.c | 204 + network_cmds/ecnprobe/capture.h | 58 + network_cmds/ecnprobe/ecn.c | 1119 ++ network_cmds/ecnprobe/ecn.h | 49 + network_cmds/ecnprobe/ecn_probe.c | 469 + network_cmds/ecnprobe/ecnprobe.1 | 20 + network_cmds/ecnprobe/gmt2local.c | 66 + network_cmds/ecnprobe/gmt2local.h | 27 + network_cmds/ecnprobe/history.c | 211 + network_cmds/ecnprobe/history.h | 75 + network_cmds/ecnprobe/inet.c | 503 + network_cmds/ecnprobe/inet.h | 206 + network_cmds/ecnprobe/session.c | 785 ++ network_cmds/ecnprobe/session.h | 183 + network_cmds/ecnprobe/support.c | 246 + network_cmds/ecnprobe/support.h | 132 + network_cmds/frame_delay/frame_delay.8 | 45 + network_cmds/frame_delay/frame_delay.c | 595 ++ network_cmds/ifconfig.tproj/af_inet.c | 316 + network_cmds/ifconfig.tproj/af_inet6.c | 753 ++ network_cmds/ifconfig.tproj/af_link.c | 164 + network_cmds/ifconfig.tproj/if6lowpan.c | 178 + network_cmds/ifconfig.tproj/ifbond.c | 284 + network_cmds/ifconfig.tproj/ifbridge.c | 952 ++ network_cmds/ifconfig.tproj/ifclone.c | 170 + network_cmds/ifconfig.tproj/ifconfig.8 | 1109 ++ network_cmds/ifconfig.tproj/ifconfig.c | 2692 +++++ network_cmds/ifconfig.tproj/ifconfig.h | 186 + network_cmds/ifconfig.tproj/iffake.c | 138 + network_cmds/ifconfig.tproj/ifmedia.c | 872 ++ network_cmds/ifconfig.tproj/ifvlan.c | 207 + network_cmds/ifconfig.tproj/nexus.c | 98 + network_cmds/ip6addrctl.tproj/ip6addrctl.8 | 126 + network_cmds/ip6addrctl.tproj/ip6addrctl.c | 467 + network_cmds/ip6addrctl.tproj/ip6addrctl.conf | 12 + .../kdumpd.tproj/com.apple.kdumpd.plist | 36 + network_cmds/kdumpd.tproj/kdump.h | 114 + network_cmds/kdumpd.tproj/kdumpd.8 | 83 + network_cmds/kdumpd.tproj/kdumpd.c | 726 ++ network_cmds/kdumpd.tproj/kdumpsubs.c | 273 + network_cmds/kdumpd.tproj/kdumpsubs.h | 72 + network_cmds/mnc.tproj/LICENCE | 37 + network_cmds/mnc.tproj/README | 63 + network_cmds/mnc.tproj/mnc.1 | 101 + network_cmds/mnc.tproj/mnc.h | 92 + network_cmds/mnc.tproj/mnc_error.c | 95 + network_cmds/mnc.tproj/mnc_main.c | 131 + network_cmds/mnc.tproj/mnc_multicast.c | 404 + network_cmds/mnc.tproj/mnc_opts.c | 182 + network_cmds/mptcp_client/conn_lib.c | 233 + network_cmds/mptcp_client/conn_lib.h | 53 + network_cmds/mptcp_client/mptcp_client.1 | 21 + network_cmds/mptcp_client/mptcp_client.c | 701 ++ network_cmds/mtest.tproj/COPYING | 27 + network_cmds/mtest.tproj/mtest.8 | 175 + network_cmds/mtest.tproj/mtest.c | 825 ++ network_cmds/ndp.tproj/gnuc.h | 2 + network_cmds/ndp.tproj/ndp.8 | 236 + network_cmds/ndp.tproj/ndp.c | 1696 +++ network_cmds/netstat.tproj/DERIVED_FILES | 1 + network_cmds/netstat.tproj/data.c | 28 + network_cmds/netstat.tproj/if.c | 2259 ++++ network_cmds/netstat.tproj/inet.c | 1361 +++ network_cmds/netstat.tproj/inet6.c | 1333 +++ network_cmds/netstat.tproj/ipsec.c | 376 + network_cmds/netstat.tproj/main.c | 638 ++ network_cmds/netstat.tproj/mbuf.c | 476 + network_cmds/netstat.tproj/mcast.c | 887 ++ network_cmds/netstat.tproj/misc.c | 122 + network_cmds/netstat.tproj/mptcp.c | 170 + network_cmds/netstat.tproj/netstat.1 | 445 + network_cmds/netstat.tproj/netstat.h | 170 + network_cmds/netstat.tproj/route.c | 795 ++ network_cmds/netstat.tproj/systm.c | 503 + network_cmds/netstat.tproj/tp_astring.c | 74 + network_cmds/netstat.tproj/unix.c | 231 + network_cmds/netstat.tproj/vsock.c | 187 + .../network-client-server-entitlements.plist | 10 + network_cmds/network_cmds.plist | 26 + .../network_cmds.xcodeproj/project.pbxproj | 5098 +++++++++ network_cmds/ping.tproj/ping.8 | 616 ++ network_cmds/ping.tproj/ping.c | 2134 ++++ network_cmds/ping6.tproj/md5.c | 308 + network_cmds/ping6.tproj/md5.h | 75 + network_cmds/ping6.tproj/ping6.8 | 625 ++ network_cmds/ping6.tproj/ping6.c | 3340 ++++++ network_cmds/pktapctl/pktapctl.8 | 41 + network_cmds/pktapctl/pktapctl.c | 189 + network_cmds/pktmnglr/packet_mangler.c | 329 + network_cmds/rarpd.tproj/rarpd.8 | 92 + network_cmds/rarpd.tproj/rarpd.c | 830 ++ network_cmds/route.tproj/gen_header.pl | 15 + network_cmds/route.tproj/keywords | 49 + network_cmds/route.tproj/keywords.h | 119 + network_cmds/route.tproj/route.8 | 405 + network_cmds/route.tproj/route.c | 1571 +++ network_cmds/rtadvd.tproj/advcap.c | 483 + network_cmds/rtadvd.tproj/advcap.h | 45 + network_cmds/rtadvd.tproj/config.c | 1313 +++ network_cmds/rtadvd.tproj/config.h | 46 + network_cmds/rtadvd.tproj/dump.c | 283 + network_cmds/rtadvd.tproj/dump.h | 32 + network_cmds/rtadvd.tproj/if.c | 604 ++ network_cmds/rtadvd.tproj/if.h | 64 + network_cmds/rtadvd.tproj/pathnames.h | 4 + network_cmds/rtadvd.tproj/rrenum.c | 484 + network_cmds/rtadvd.tproj/rrenum.h | 33 + network_cmds/rtadvd.tproj/rtadvd.8 | 207 + network_cmds/rtadvd.tproj/rtadvd.c | 1650 +++ network_cmds/rtadvd.tproj/rtadvd.conf | 20 + network_cmds/rtadvd.tproj/rtadvd.conf.5 | 509 + network_cmds/rtadvd.tproj/rtadvd.h | 205 + network_cmds/rtadvd.tproj/rtadvd_logging.c | 45 + network_cmds/rtadvd.tproj/rtadvd_logging.h | 24 + network_cmds/rtadvd.tproj/timer.c | 205 + network_cmds/rtadvd.tproj/timer.h | 64 + network_cmds/rtsol.tproj/dump.c | 172 + network_cmds/rtsol.tproj/if.c | 501 + network_cmds/rtsol.tproj/probe.c | 221 + network_cmds/rtsol.tproj/rtsock.c | 179 + network_cmds/rtsol.tproj/rtsol.8 | 224 + network_cmds/rtsol.tproj/rtsol.c | 343 + network_cmds/rtsol.tproj/rtsold.c | 791 ++ network_cmds/rtsol.tproj/rtsold.h | 96 + network_cmds/spray.tproj/spray.8 | 74 + network_cmds/spray.tproj/spray.c | 247 + network_cmds/spray.tproj/spray.x | 24 + network_cmds/traceroute.tproj/README | 126 + network_cmds/traceroute.tproj/as.c | 242 + network_cmds/traceroute.tproj/as.h | 42 + .../traceroute.tproj/findsaddr-socket.c | 246 + network_cmds/traceroute.tproj/findsaddr.h | 23 + network_cmds/traceroute.tproj/gnuc.h | 43 + network_cmds/traceroute.tproj/ifaddrlist.c | 202 + network_cmds/traceroute.tproj/ifaddrlist.h | 57 + network_cmds/traceroute.tproj/mean.awk | 50 + network_cmds/traceroute.tproj/median.awk | 67 + network_cmds/traceroute.tproj/traceroute.8 | 439 + network_cmds/traceroute.tproj/traceroute.c | 1822 ++++ network_cmds/traceroute.tproj/traceroute.h | 26 + network_cmds/traceroute.tproj/version.c | 1 + network_cmds/traceroute6.tproj/traceroute6.8 | 178 + network_cmds/traceroute6.tproj/traceroute6.c | 1423 +++ patch_cmds/diffstat/CHANGES | 373 + patch_cmds/diffstat/aclocal.m4 | 1306 +++ patch_cmds/diffstat/config.guess | 1508 +++ patch_cmds/diffstat/config.h | 38 + patch_cmds/diffstat/config.sub | 1739 ++++ patch_cmds/diffstat/config_h.in | 8 + patch_cmds/diffstat/configure | 7291 +++++++++++++ patch_cmds/diffstat/configure.in | 54 + patch_cmds/diffstat/diffstat.1 | 235 + patch_cmds/diffstat/diffstat.c | 2491 +++++ patch_cmds/diffstat/install-sh | 294 + patch_cmds/diffstat/makefile.in | 144 + patch_cmds/diffstat/makefile.wnt | 35 + patch_cmds/diffstat/package/debian/changelog | 25 + patch_cmds/diffstat/package/debian/compat | 1 + patch_cmds/diffstat/package/debian/control | 15 + patch_cmds/diffstat/package/debian/copyright | 109 + patch_cmds/diffstat/package/debian/docs | 1 + patch_cmds/diffstat/package/debian/rules | 92 + .../diffstat/package/debian/source/format | 1 + patch_cmds/diffstat/package/debian/watch | 4 + patch_cmds/diffstat/package/diffstat.spec | 54 + patch_cmds/diffstat/porting/getopt.c | 79 + patch_cmds/diffstat/porting/getopt.h | 4 + patch_cmds/diffstat/porting/system.h | 85 + patch_cmds/diffstat/porting/wildcard.c | 109 + patch_cmds/diffstat/testing/case01.pat | 417 + patch_cmds/diffstat/testing/case01.ref | 28 + patch_cmds/diffstat/testing/case01R.ref | 28 + patch_cmds/diffstat/testing/case01Rp0.ref | 28 + patch_cmds/diffstat/testing/case01b.ref | 28 + patch_cmds/diffstat/testing/case01f0.ref | 28 + patch_cmds/diffstat/testing/case01k.ref | 28 + patch_cmds/diffstat/testing/case01p1.ref | 28 + patch_cmds/diffstat/testing/case01p9.ref | 28 + patch_cmds/diffstat/testing/case01r1.ref | 28 + patch_cmds/diffstat/testing/case01r2.ref | 28 + patch_cmds/diffstat/testing/case01u.ref | 28 + patch_cmds/diffstat/testing/case02.pat | 486 + patch_cmds/diffstat/testing/case02.ref | 4 + patch_cmds/diffstat/testing/case02R.ref | 4 + patch_cmds/diffstat/testing/case02Rp0.ref | 4 + patch_cmds/diffstat/testing/case02b.ref | 4 + patch_cmds/diffstat/testing/case02f0.ref | 4 + patch_cmds/diffstat/testing/case02k.ref | 4 + patch_cmds/diffstat/testing/case02p1.ref | 4 + patch_cmds/diffstat/testing/case02p9.ref | 4 + patch_cmds/diffstat/testing/case02r1.ref | 4 + patch_cmds/diffstat/testing/case02r2.ref | 4 + patch_cmds/diffstat/testing/case02u.ref | 4 + patch_cmds/diffstat/testing/case03.pat | 35 + patch_cmds/diffstat/testing/case03.ref | 6 + patch_cmds/diffstat/testing/case03R.ref | 6 + patch_cmds/diffstat/testing/case03Rp0.ref | 6 + patch_cmds/diffstat/testing/case03b.ref | 4 + patch_cmds/diffstat/testing/case03f0.ref | 6 + patch_cmds/diffstat/testing/case03k.ref | 6 + patch_cmds/diffstat/testing/case03p1.ref | 6 + patch_cmds/diffstat/testing/case03p9.ref | 6 + patch_cmds/diffstat/testing/case03r1.ref | 6 + patch_cmds/diffstat/testing/case03r2.ref | 6 + patch_cmds/diffstat/testing/case03u.ref | 6 + patch_cmds/diffstat/testing/case04.pat | 352 + patch_cmds/diffstat/testing/case04.ref | 41 + patch_cmds/diffstat/testing/case04R.ref | 41 + patch_cmds/diffstat/testing/case04Rp0.ref | 41 + patch_cmds/diffstat/testing/case04b.ref | 39 + patch_cmds/diffstat/testing/case04f0.ref | 41 + patch_cmds/diffstat/testing/case04k.ref | 81 + patch_cmds/diffstat/testing/case04p1.ref | 41 + patch_cmds/diffstat/testing/case04p9.ref | 41 + patch_cmds/diffstat/testing/case04r1.ref | 41 + patch_cmds/diffstat/testing/case04r2.ref | 41 + patch_cmds/diffstat/testing/case04u.ref | 41 + patch_cmds/diffstat/testing/case05.pat | 17 + patch_cmds/diffstat/testing/case05.ref | 2 + patch_cmds/diffstat/testing/case05R.ref | 2 + patch_cmds/diffstat/testing/case05Rp0.ref | 2 + patch_cmds/diffstat/testing/case05b.ref | 2 + patch_cmds/diffstat/testing/case05f0.ref | 2 + patch_cmds/diffstat/testing/case05k.ref | 2 + patch_cmds/diffstat/testing/case05p1.ref | 2 + patch_cmds/diffstat/testing/case05p9.ref | 2 + patch_cmds/diffstat/testing/case05r1.ref | 2 + patch_cmds/diffstat/testing/case05r2.ref | 2 + patch_cmds/diffstat/testing/case05u.ref | 2 + patch_cmds/diffstat/testing/case06.pat | 323 + patch_cmds/diffstat/testing/case06.ref | 6 + patch_cmds/diffstat/testing/case06R.ref | 6 + patch_cmds/diffstat/testing/case06Rp0.ref | 6 + patch_cmds/diffstat/testing/case06b.ref | 6 + patch_cmds/diffstat/testing/case06f0.ref | 6 + patch_cmds/diffstat/testing/case06k.ref | 6 + patch_cmds/diffstat/testing/case06p1.ref | 6 + patch_cmds/diffstat/testing/case06p9.ref | 6 + patch_cmds/diffstat/testing/case06r1.ref | 6 + patch_cmds/diffstat/testing/case06r2.ref | 6 + patch_cmds/diffstat/testing/case06u.ref | 6 + patch_cmds/diffstat/testing/case07.pat | 107 + patch_cmds/diffstat/testing/case07.ref | 3 + patch_cmds/diffstat/testing/case07R.ref | 2 + patch_cmds/diffstat/testing/case07Rp0.ref | 2 + patch_cmds/diffstat/testing/case07b.ref | 3 + patch_cmds/diffstat/testing/case07f0.ref | 3 + patch_cmds/diffstat/testing/case07k.ref | 3 + patch_cmds/diffstat/testing/case07p1.ref | 3 + patch_cmds/diffstat/testing/case07p9.ref | 3 + patch_cmds/diffstat/testing/case07r1.ref | 3 + patch_cmds/diffstat/testing/case07r2.ref | 3 + patch_cmds/diffstat/testing/case07u.ref | 3 + patch_cmds/diffstat/testing/case08.pat | 343 + patch_cmds/diffstat/testing/case08.ref | 9 + patch_cmds/diffstat/testing/case08R.ref | 9 + patch_cmds/diffstat/testing/case08Rp0.ref | 9 + patch_cmds/diffstat/testing/case08b.ref | 9 + patch_cmds/diffstat/testing/case08f0.ref | 9 + patch_cmds/diffstat/testing/case08k.ref | 9 + patch_cmds/diffstat/testing/case08p1.ref | 9 + patch_cmds/diffstat/testing/case08p9.ref | 9 + patch_cmds/diffstat/testing/case08r1.ref | 9 + patch_cmds/diffstat/testing/case08r2.ref | 9 + patch_cmds/diffstat/testing/case08u.ref | 9 + patch_cmds/diffstat/testing/case09.pat | 13 + patch_cmds/diffstat/testing/case09.ref | 1 + patch_cmds/diffstat/testing/case09R.ref | 1 + patch_cmds/diffstat/testing/case09Rp0.ref | 1 + patch_cmds/diffstat/testing/case09b.ref | 1 + patch_cmds/diffstat/testing/case09f0.ref | 1 + patch_cmds/diffstat/testing/case09k.ref | 1 + patch_cmds/diffstat/testing/case09p1.ref | 1 + patch_cmds/diffstat/testing/case09p9.ref | 1 + patch_cmds/diffstat/testing/case09r1.ref | 1 + patch_cmds/diffstat/testing/case09r2.ref | 1 + patch_cmds/diffstat/testing/case09u.ref | 1 + patch_cmds/diffstat/testing/case10.pat | 67 + patch_cmds/diffstat/testing/case10.ref | 3 + patch_cmds/diffstat/testing/case10R.ref | 3 + patch_cmds/diffstat/testing/case10Rp0.ref | 3 + patch_cmds/diffstat/testing/case10b.ref | 3 + patch_cmds/diffstat/testing/case10f0.ref | 3 + patch_cmds/diffstat/testing/case10k.ref | 4 + patch_cmds/diffstat/testing/case10p1.ref | 3 + patch_cmds/diffstat/testing/case10p9.ref | 3 + patch_cmds/diffstat/testing/case10r1.ref | 3 + patch_cmds/diffstat/testing/case10r2.ref | 3 + patch_cmds/diffstat/testing/case10u.ref | 3 + patch_cmds/diffstat/testing/case11.pat | 12 + patch_cmds/diffstat/testing/case11.ref | 2 + patch_cmds/diffstat/testing/case11R.ref | 2 + patch_cmds/diffstat/testing/case11Rp0.ref | 2 + patch_cmds/diffstat/testing/case11b.ref | 2 + patch_cmds/diffstat/testing/case11f0.ref | 2 + patch_cmds/diffstat/testing/case11k.ref | 2 + patch_cmds/diffstat/testing/case11p1.ref | 2 + patch_cmds/diffstat/testing/case11p9.ref | 2 + patch_cmds/diffstat/testing/case11r1.ref | 2 + patch_cmds/diffstat/testing/case11r2.ref | 2 + patch_cmds/diffstat/testing/case11u.ref | 2 + patch_cmds/diffstat/testing/case12.pat | 163 + patch_cmds/diffstat/testing/case12.ref | 3 + patch_cmds/diffstat/testing/case12R.ref | 3 + patch_cmds/diffstat/testing/case12Rp0.ref | 3 + patch_cmds/diffstat/testing/case12b.ref | 3 + patch_cmds/diffstat/testing/case12f0.ref | 3 + patch_cmds/diffstat/testing/case12k.ref | 3 + patch_cmds/diffstat/testing/case12p1.ref | 3 + patch_cmds/diffstat/testing/case12p9.ref | 3 + patch_cmds/diffstat/testing/case12r1.ref | 3 + patch_cmds/diffstat/testing/case12r2.ref | 3 + patch_cmds/diffstat/testing/case12u.ref | 3 + patch_cmds/diffstat/testing/case13.pat | 303 + patch_cmds/diffstat/testing/case13.ref | 3 + patch_cmds/diffstat/testing/case13R.ref | 3 + patch_cmds/diffstat/testing/case13Rp0.ref | 3 + patch_cmds/diffstat/testing/case13b.ref | 3 + patch_cmds/diffstat/testing/case13f0.ref | 3 + patch_cmds/diffstat/testing/case13k.ref | 3 + patch_cmds/diffstat/testing/case13p1.ref | 3 + patch_cmds/diffstat/testing/case13p9.ref | 3 + patch_cmds/diffstat/testing/case13r1.ref | 3 + patch_cmds/diffstat/testing/case13r2.ref | 3 + patch_cmds/diffstat/testing/case13u.ref | 3 + patch_cmds/diffstat/testing/case14.pat | 12 + patch_cmds/diffstat/testing/case14.ref | 2 + patch_cmds/diffstat/testing/case14R.ref | 2 + patch_cmds/diffstat/testing/case14Rp0.ref | 2 + patch_cmds/diffstat/testing/case14b.ref | 2 + patch_cmds/diffstat/testing/case14f0.ref | 2 + patch_cmds/diffstat/testing/case14k.ref | 2 + patch_cmds/diffstat/testing/case14p1.ref | 2 + patch_cmds/diffstat/testing/case14p9.ref | 2 + patch_cmds/diffstat/testing/case14r1.ref | 2 + patch_cmds/diffstat/testing/case14r2.ref | 2 + patch_cmds/diffstat/testing/case14u.ref | 2 + patch_cmds/diffstat/testing/case15.pat | 443 + patch_cmds/diffstat/testing/case15.ref | 13 + patch_cmds/diffstat/testing/case15R.ref | 13 + patch_cmds/diffstat/testing/case15Rp0.ref | 13 + patch_cmds/diffstat/testing/case15b.ref | 13 + patch_cmds/diffstat/testing/case15f0.ref | 13 + patch_cmds/diffstat/testing/case15k.ref | 13 + patch_cmds/diffstat/testing/case15p1.ref | 13 + patch_cmds/diffstat/testing/case15p9.ref | 13 + patch_cmds/diffstat/testing/case15r1.ref | 13 + patch_cmds/diffstat/testing/case15r2.ref | 13 + patch_cmds/diffstat/testing/case15u.ref | 13 + patch_cmds/diffstat/testing/case16.pat | 2036 ++++ patch_cmds/diffstat/testing/case16.ref | 30 + patch_cmds/diffstat/testing/case16R.ref | 30 + patch_cmds/diffstat/testing/case16Rp0.ref | 30 + patch_cmds/diffstat/testing/case16b.ref | 30 + patch_cmds/diffstat/testing/case16f0.ref | 30 + patch_cmds/diffstat/testing/case16k.ref | 30 + patch_cmds/diffstat/testing/case16p1.ref | 30 + patch_cmds/diffstat/testing/case16p9.ref | 25 + patch_cmds/diffstat/testing/case16r1.ref | 30 + patch_cmds/diffstat/testing/case16r2.ref | 30 + patch_cmds/diffstat/testing/case16u.ref | 30 + patch_cmds/diffstat/testing/case17.pat | 115 + patch_cmds/diffstat/testing/case17.ref | 4 + patch_cmds/diffstat/testing/case17R.ref | 4 + patch_cmds/diffstat/testing/case17Rp0.ref | 4 + patch_cmds/diffstat/testing/case17b.ref | 4 + patch_cmds/diffstat/testing/case17f0.ref | 4 + patch_cmds/diffstat/testing/case17k.ref | 4 + patch_cmds/diffstat/testing/case17p1.ref | 4 + patch_cmds/diffstat/testing/case17p9.ref | 4 + patch_cmds/diffstat/testing/case17r1.ref | 4 + patch_cmds/diffstat/testing/case17r2.ref | 4 + patch_cmds/diffstat/testing/case17u.ref | 4 + patch_cmds/diffstat/testing/case18.pat | 7 + patch_cmds/diffstat/testing/case18.ref | 2 + patch_cmds/diffstat/testing/case18R.ref | 2 + patch_cmds/diffstat/testing/case18Rp0.ref | 2 + patch_cmds/diffstat/testing/case18b.ref | 2 + patch_cmds/diffstat/testing/case18f0.ref | 2 + patch_cmds/diffstat/testing/case18k.ref | 2 + patch_cmds/diffstat/testing/case18p1.ref | 2 + patch_cmds/diffstat/testing/case18p9.ref | 2 + patch_cmds/diffstat/testing/case18r1.ref | 2 + patch_cmds/diffstat/testing/case18r2.ref | 2 + patch_cmds/diffstat/testing/case18u.ref | 2 + patch_cmds/diffstat/testing/case19.pat | 14 + patch_cmds/diffstat/testing/case19.ref | 2 + patch_cmds/diffstat/testing/case19R.ref | 2 + patch_cmds/diffstat/testing/case19Rp0.ref | 2 + patch_cmds/diffstat/testing/case19b.ref | 2 + patch_cmds/diffstat/testing/case19f0.ref | 2 + patch_cmds/diffstat/testing/case19k.ref | 2 + patch_cmds/diffstat/testing/case19p1.ref | 2 + patch_cmds/diffstat/testing/case19p9.ref | 2 + patch_cmds/diffstat/testing/case19r1.ref | 2 + patch_cmds/diffstat/testing/case19r2.ref | 2 + patch_cmds/diffstat/testing/case19u.ref | 2 + patch_cmds/diffstat/testing/case20.pat | 111 + patch_cmds/diffstat/testing/case20.ref | 3 + patch_cmds/diffstat/testing/case20R.ref | 3 + patch_cmds/diffstat/testing/case20Rp0.ref | 3 + patch_cmds/diffstat/testing/case20b.ref | 3 + patch_cmds/diffstat/testing/case20f0.ref | 3 + patch_cmds/diffstat/testing/case20k.ref | 3 + patch_cmds/diffstat/testing/case20p1.ref | 3 + patch_cmds/diffstat/testing/case20p9.ref | 3 + patch_cmds/diffstat/testing/case20r1.ref | 3 + patch_cmds/diffstat/testing/case20r2.ref | 3 + patch_cmds/diffstat/testing/case20u.ref | 3 + patch_cmds/diffstat/testing/case21.pat | 74 + patch_cmds/diffstat/testing/case21.ref | 2 + patch_cmds/diffstat/testing/case21R.ref | 2 + patch_cmds/diffstat/testing/case21Rp0.ref | 2 + patch_cmds/diffstat/testing/case21b.ref | 2 + patch_cmds/diffstat/testing/case21f0.ref | 2 + patch_cmds/diffstat/testing/case21k.ref | 2 + patch_cmds/diffstat/testing/case21p1.ref | 2 + patch_cmds/diffstat/testing/case21p9.ref | 2 + patch_cmds/diffstat/testing/case21r1.ref | 2 + patch_cmds/diffstat/testing/case21r2.ref | 2 + patch_cmds/diffstat/testing/case21u.ref | 2 + patch_cmds/diffstat/testing/case22.pat | 651 ++ patch_cmds/diffstat/testing/case22.ref | 37 + patch_cmds/diffstat/testing/case22R.ref | 37 + patch_cmds/diffstat/testing/case22Rp0.ref | 37 + patch_cmds/diffstat/testing/case22b.ref | 37 + patch_cmds/diffstat/testing/case22f0.ref | 37 + patch_cmds/diffstat/testing/case22k.ref | 37 + patch_cmds/diffstat/testing/case22p1.ref | 37 + patch_cmds/diffstat/testing/case22p9.ref | 37 + patch_cmds/diffstat/testing/case22r1.ref | 37 + patch_cmds/diffstat/testing/case22r2.ref | 37 + patch_cmds/diffstat/testing/case22u.ref | 37 + patch_cmds/diffstat/testing/case23.pat | 227 + patch_cmds/diffstat/testing/case23.ref | 3 + patch_cmds/diffstat/testing/case23R.ref | 3 + patch_cmds/diffstat/testing/case23Rp0.ref | 3 + patch_cmds/diffstat/testing/case23b.ref | 3 + patch_cmds/diffstat/testing/case23f0.ref | 3 + patch_cmds/diffstat/testing/case23k.ref | 3 + patch_cmds/diffstat/testing/case23p1.ref | 3 + patch_cmds/diffstat/testing/case23p9.ref | 3 + patch_cmds/diffstat/testing/case23r1.ref | 3 + patch_cmds/diffstat/testing/case23r2.ref | 3 + patch_cmds/diffstat/testing/case23u.ref | 3 + patch_cmds/diffstat/testing/case24.pat | 217 + patch_cmds/diffstat/testing/case24.ref | 6 + patch_cmds/diffstat/testing/case24R.ref | 6 + patch_cmds/diffstat/testing/case24Rp0.ref | 6 + patch_cmds/diffstat/testing/case24b.ref | 6 + patch_cmds/diffstat/testing/case24f0.ref | 6 + patch_cmds/diffstat/testing/case24k.ref | 6 + patch_cmds/diffstat/testing/case24p1.ref | 6 + patch_cmds/diffstat/testing/case24p9.ref | 6 + patch_cmds/diffstat/testing/case24r1.ref | 6 + patch_cmds/diffstat/testing/case24r2.ref | 6 + patch_cmds/diffstat/testing/case24u.ref | 6 + patch_cmds/diffstat/testing/case25.pat | 471 + patch_cmds/diffstat/testing/case25.ref | 7 + patch_cmds/diffstat/testing/case25R.ref | 7 + patch_cmds/diffstat/testing/case25Rp0.ref | 7 + patch_cmds/diffstat/testing/case25b.ref | 7 + patch_cmds/diffstat/testing/case25f0.ref | 7 + patch_cmds/diffstat/testing/case25k.ref | 7 + patch_cmds/diffstat/testing/case25p1.ref | 7 + patch_cmds/diffstat/testing/case25p9.ref | 7 + patch_cmds/diffstat/testing/case25r1.ref | 7 + patch_cmds/diffstat/testing/case25r2.ref | 7 + patch_cmds/diffstat/testing/case25u.ref | 7 + patch_cmds/diffstat/testing/case26.pat | 1901 ++++ patch_cmds/diffstat/testing/case26.ref | 35 + patch_cmds/diffstat/testing/case26R.ref | 35 + patch_cmds/diffstat/testing/case26Rp0.ref | 35 + patch_cmds/diffstat/testing/case26b.ref | 35 + patch_cmds/diffstat/testing/case26f0.ref | 35 + patch_cmds/diffstat/testing/case26k.ref | 35 + patch_cmds/diffstat/testing/case26p1.ref | 35 + patch_cmds/diffstat/testing/case26p9.ref | 27 + patch_cmds/diffstat/testing/case26r1.ref | 35 + patch_cmds/diffstat/testing/case26r2.ref | 35 + patch_cmds/diffstat/testing/case26u.ref | 35 + patch_cmds/diffstat/testing/case27.pat | 409 + patch_cmds/diffstat/testing/case27.ref | 8 + patch_cmds/diffstat/testing/case27R.ref | 8 + patch_cmds/diffstat/testing/case27Rp0.ref | 8 + patch_cmds/diffstat/testing/case27b.ref | 8 + patch_cmds/diffstat/testing/case27f0.ref | 8 + patch_cmds/diffstat/testing/case27k.ref | 8 + patch_cmds/diffstat/testing/case27p1.ref | 8 + patch_cmds/diffstat/testing/case27p9.ref | 8 + patch_cmds/diffstat/testing/case27r1.ref | 8 + patch_cmds/diffstat/testing/case27r2.ref | 8 + patch_cmds/diffstat/testing/case27u.ref | 8 + patch_cmds/diffstat/testing/case28.pat | 326 + patch_cmds/diffstat/testing/case28.ref | 2 + patch_cmds/diffstat/testing/case28R.ref | 2 + patch_cmds/diffstat/testing/case28Rp0.ref | 2 + patch_cmds/diffstat/testing/case28b.ref | 2 + patch_cmds/diffstat/testing/case28f0.ref | 2 + patch_cmds/diffstat/testing/case28k.ref | 2 + patch_cmds/diffstat/testing/case28p1.ref | 2 + patch_cmds/diffstat/testing/case28p9.ref | 2 + patch_cmds/diffstat/testing/case28r1.ref | 2 + patch_cmds/diffstat/testing/case28r2.ref | 2 + patch_cmds/diffstat/testing/case28u.ref | 2 + patch_cmds/diffstat/testing/case29.pat | 193 + patch_cmds/diffstat/testing/case29.ref | 2 + patch_cmds/diffstat/testing/case29R.ref | 2 + patch_cmds/diffstat/testing/case29Rp0.ref | 2 + patch_cmds/diffstat/testing/case29b.ref | 2 + patch_cmds/diffstat/testing/case29f0.ref | 2 + patch_cmds/diffstat/testing/case29k.ref | 2 + patch_cmds/diffstat/testing/case29p1.ref | 2 + patch_cmds/diffstat/testing/case29p9.ref | 2 + patch_cmds/diffstat/testing/case29r1.ref | 2 + patch_cmds/diffstat/testing/case29r2.ref | 2 + patch_cmds/diffstat/testing/case29u.ref | 2 + patch_cmds/diffstat/testing/case31.pat | 22 + patch_cmds/diffstat/testing/case31.ref | 2 + patch_cmds/diffstat/testing/case31R.ref | 2 + patch_cmds/diffstat/testing/case31Rp0.ref | 2 + patch_cmds/diffstat/testing/case31b.ref | 2 + patch_cmds/diffstat/testing/case31f0.ref | 2 + patch_cmds/diffstat/testing/case31k.ref | 2 + patch_cmds/diffstat/testing/case31l.pat | 8 + patch_cmds/diffstat/testing/case31l.ref | 2 + patch_cmds/diffstat/testing/case31lR.ref | 2 + patch_cmds/diffstat/testing/case31lRp0.ref | 2 + patch_cmds/diffstat/testing/case31lb.ref | 2 + patch_cmds/diffstat/testing/case31lf0.ref | 2 + patch_cmds/diffstat/testing/case31lk.ref | 2 + patch_cmds/diffstat/testing/case31lp1.ref | 2 + patch_cmds/diffstat/testing/case31lp9.ref | 2 + patch_cmds/diffstat/testing/case31lr1.ref | 2 + patch_cmds/diffstat/testing/case31lr2.ref | 2 + patch_cmds/diffstat/testing/case31lu.ref | 2 + patch_cmds/diffstat/testing/case31p1.ref | 2 + patch_cmds/diffstat/testing/case31p9.ref | 2 + patch_cmds/diffstat/testing/case31r1.ref | 2 + patch_cmds/diffstat/testing/case31r2.ref | 2 + patch_cmds/diffstat/testing/case31u.pat | 51 + patch_cmds/diffstat/testing/case31u.ref | 2 + patch_cmds/diffstat/testing/case31uR.ref | 2 + patch_cmds/diffstat/testing/case31uRp0.ref | 2 + patch_cmds/diffstat/testing/case31ub.ref | 2 + patch_cmds/diffstat/testing/case31uf0.ref | 2 + patch_cmds/diffstat/testing/case31uk.ref | 2 + patch_cmds/diffstat/testing/case31up1.ref | 2 + patch_cmds/diffstat/testing/case31up9.ref | 2 + patch_cmds/diffstat/testing/case31ur1.ref | 2 + patch_cmds/diffstat/testing/case31ur2.ref | 2 + patch_cmds/diffstat/testing/case31uu.ref | 2 + patch_cmds/diffstat/testing/case32.pat | 13 + patch_cmds/diffstat/testing/case32.ref | 2 + patch_cmds/diffstat/testing/case32R.ref | 2 + patch_cmds/diffstat/testing/case32Rp0.ref | 2 + patch_cmds/diffstat/testing/case32b.ref | 2 + patch_cmds/diffstat/testing/case32f0.ref | 2 + patch_cmds/diffstat/testing/case32k.ref | 2 + patch_cmds/diffstat/testing/case32p1.ref | 2 + patch_cmds/diffstat/testing/case32p9.ref | 2 + patch_cmds/diffstat/testing/case32r1.ref | 2 + patch_cmds/diffstat/testing/case32r2.ref | 2 + patch_cmds/diffstat/testing/case32u.ref | 2 + patch_cmds/diffstat/testing/case33.pat | 13 + patch_cmds/diffstat/testing/case33.ref | 2 + patch_cmds/diffstat/testing/case33R.ref | 2 + patch_cmds/diffstat/testing/case33Rp0.ref | 2 + patch_cmds/diffstat/testing/case33b.ref | 2 + patch_cmds/diffstat/testing/case33f0.ref | 2 + patch_cmds/diffstat/testing/case33k.ref | 2 + patch_cmds/diffstat/testing/case33p1.ref | 2 + patch_cmds/diffstat/testing/case33p9.ref | 2 + patch_cmds/diffstat/testing/case33r1.ref | 2 + patch_cmds/diffstat/testing/case33r2.ref | 2 + patch_cmds/diffstat/testing/case33u.ref | 2 + patch_cmds/diffstat/testing/run_atac.sh | 6 + patch_cmds/diffstat/testing/run_test.sh | 51 + patch_cmds/patch/Makefile | 6 + patch_cmds/patch/backupfile.c | 235 + patch_cmds/patch/backupfile.h | 38 + patch_cmds/patch/common.h | 117 + patch_cmds/patch/inp.c | 471 + patch_cmds/patch/inp.h | 31 + patch_cmds/patch/mkpath.c | 74 + patch_cmds/patch/patch.1 | 698 ++ patch_cmds/patch/patch.c | 1058 ++ patch_cmds/patch/pathnames.h | 11 + patch_cmds/patch/pch.c | 1544 +++ patch_cmds/patch/pch.h | 56 + patch_cmds/patch/util.c | 420 + patch_cmds/patch/util.h | 50 + patch_cmds/patch_cmds.plist | 54 + patch_cmds/patch_cmds.txt | 50 + .../patch_cmds.xcodeproj/project.pbxproj | 398 + remote_cmds/APPLE_LICENSE | 370 + remote_cmds/Makefile | 12 + remote_cmds/logger.tproj/Makefile | 11 + remote_cmds/logger.tproj/logger.1 | 102 + remote_cmds/logger.tproj/logger.c | 329 + remote_cmds/talk.tproj/Makefile | 14 + remote_cmds/talk.tproj/ctl.c | 128 + remote_cmds/talk.tproj/ctl_transact.c | 125 + remote_cmds/talk.tproj/display.c | 198 + remote_cmds/talk.tproj/get_addrs.c | 71 + remote_cmds/talk.tproj/get_iface.c | 103 + remote_cmds/talk.tproj/get_names.c | 126 + remote_cmds/talk.tproj/init_disp.c | 245 + remote_cmds/talk.tproj/invite.c | 202 + remote_cmds/talk.tproj/io.c | 188 + remote_cmds/talk.tproj/look_up.c | 127 + remote_cmds/talk.tproj/msgs.c | 87 + remote_cmds/talk.tproj/talk.1 | 172 + remote_cmds/talk.tproj/talk.c | 92 + remote_cmds/talk.tproj/talk.h | 97 + remote_cmds/talk.tproj/talk_ctl.h | 43 + remote_cmds/talkd.tproj/Makefile | 14 + remote_cmds/talkd.tproj/announce.c | 179 + remote_cmds/talkd.tproj/extern.h | 40 + remote_cmds/talkd.tproj/ntalk.plist | 29 + remote_cmds/talkd.tproj/ntalkd.8 | 98 + remote_cmds/talkd.tproj/print.c | 96 + remote_cmds/talkd.tproj/process.c | 279 + remote_cmds/talkd.tproj/table.c | 241 + remote_cmds/talkd.tproj/talkd.c | 145 + remote_cmds/telnet.tproj/Makefile | 18 + remote_cmds/telnet.tproj/authenc.c | 109 + remote_cmds/telnet.tproj/commands.c | 3063 ++++++ remote_cmds/telnet.tproj/defines.h | 56 + remote_cmds/telnet.tproj/externs.h | 495 + remote_cmds/telnet.tproj/fdset.h | 49 + remote_cmds/telnet.tproj/general.h | 45 + remote_cmds/telnet.tproj/krb4-proto.h | 230 + remote_cmds/telnet.tproj/main.c | 379 + remote_cmds/telnet.tproj/misc-proto.h | 80 + remote_cmds/telnet.tproj/misc.h | 42 + remote_cmds/telnet.tproj/network.c | 182 + remote_cmds/telnet.tproj/ring.c | 322 + remote_cmds/telnet.tproj/ring.h | 107 + remote_cmds/telnet.tproj/sys_bsd.c | 1145 +++ remote_cmds/telnet.tproj/telnet.1 | 1417 +++ remote_cmds/telnet.tproj/telnet.c | 2418 +++++ remote_cmds/telnet.tproj/terminal.c | 242 + remote_cmds/telnet.tproj/tn3270.c | 435 + remote_cmds/telnet.tproj/types.h | 52 + remote_cmds/telnet.tproj/utilities.c | 912 ++ remote_cmds/telnetd.tproj/Makefile | 50 + remote_cmds/telnetd.tproj/authenc.c | 87 + remote_cmds/telnetd.tproj/defs.h | 258 + remote_cmds/telnetd.tproj/entitlements.plist | 8 + remote_cmds/telnetd.tproj/ext.h | 222 + remote_cmds/telnetd.tproj/global.c | 52 + remote_cmds/telnetd.tproj/pathnames.h | 56 + remote_cmds/telnetd.tproj/slc.c | 484 + remote_cmds/telnetd.tproj/state.c | 1631 +++ remote_cmds/telnetd.tproj/strlcpy.c | 74 + remote_cmds/telnetd.tproj/sys_term.c | 1410 +++ remote_cmds/telnetd.tproj/telnet.plist | 35 + remote_cmds/telnetd.tproj/telnetd.8 | 607 ++ remote_cmds/telnetd.tproj/telnetd.c | 1330 +++ remote_cmds/telnetd.tproj/telnetd.h | 49 + remote_cmds/telnetd.tproj/termstat.c | 632 ++ remote_cmds/telnetd.tproj/utility.c | 1081 ++ remote_cmds/telnetd.tproj/vasprintf.c | 66 + remote_cmds/tftp.tproj/Makefile | 12 + remote_cmds/tftp.tproj/extern.h | 38 + remote_cmds/tftp.tproj/main.c | 920 ++ remote_cmds/tftp.tproj/tftp.1 | 243 + remote_cmds/tftp.tproj/tftp.c | 742 ++ remote_cmds/tftp.tproj/tftpsubs.c | 287 + remote_cmds/tftp.tproj/tftpsubs.h | 54 + remote_cmds/tftpd.tproj/DERIVED_FILES | 5 + remote_cmds/tftpd.tproj/Makefile | 16 + remote_cmds/tftpd.tproj/tftp.plist | 33 + remote_cmds/tftpd.tproj/tftpd.8 | 233 + remote_cmds/tftpd.tproj/tftpd.c | 1238 +++ remote_cmds/tftpd.tproj/tftpsubs.c | 285 + remote_cmds/tftpd.tproj/tftpsubs.h | 48 + remote_cmds/wall.tproj/Makefile | 16 + remote_cmds/wall.tproj/ttymsg.c | 179 + remote_cmds/wall.tproj/ttymsg.h | 3 + remote_cmds/wall.tproj/wall.1 | 83 + remote_cmds/wall.tproj/wall.c | 361 + shell_cmds/.upstream_base_commits | 4 + shell_cmds/alias/alias.1 | 1 + shell_cmds/alias/builtin.1 | 333 + shell_cmds/alias/generic.sh | 4 + shell_cmds/apply/apply.1 | 140 + shell_cmds/apply/apply.c | 267 + shell_cmds/basename/basename.1 | 114 + shell_cmds/basename/basename.c | 119 + shell_cmds/basename/dirname.1 | 1 + shell_cmds/chroot/chroot.8 | 102 + shell_cmds/chroot/chroot.c | 178 + shell_cmds/date/date.1 | 472 + shell_cmds/date/date.c | 365 + shell_cmds/date/date.plist.part | 22 + shell_cmds/date/extern.h | 35 + shell_cmds/date/netdate.c | 181 + shell_cmds/date/vary.c | 506 + shell_cmds/date/vary.h | 36 + shell_cmds/dirname/dirname.c | 84 + shell_cmds/echo/echo.1 | 101 + shell_cmds/echo/echo.c | 182 + shell_cmds/env/env.1 | 482 + shell_cmds/env/env.c | 144 + shell_cmds/env/envopts.c | 468 + shell_cmds/env/envopts.h | 37 + shell_cmds/expr/expr.1 | 235 + shell_cmds/expr/expr.y | 571 + shell_cmds/false/false.1 | 60 + shell_cmds/false/false.c | 2 + shell_cmds/false/false.sh | 2 + shell_cmds/find/extern.h | 124 + shell_cmds/find/find.1 | 1078 ++ shell_cmds/find/find.c | 323 + shell_cmds/find/find.h | 145 + shell_cmds/find/find.plist.part | 30 + shell_cmds/find/function.c | 1772 ++++ shell_cmds/find/getdate.y | 961 ++ shell_cmds/find/ls.c | 124 + shell_cmds/find/main.c | 166 + shell_cmds/find/misc.c | 106 + shell_cmds/find/operator.c | 273 + shell_cmds/find/option.c | 201 + shell_cmds/getopt/getopt.1 | 134 + shell_cmds/getopt/getopt.c | 32 + shell_cmds/hexdump/conv.c | 178 + shell_cmds/hexdump/display.c | 417 + shell_cmds/hexdump/hexdump.1 | 342 + shell_cmds/hexdump/hexdump.c | 86 + shell_cmds/hexdump/hexdump.h | 108 + shell_cmds/hexdump/hexsyntax.c | 147 + shell_cmds/hexdump/od.1 | 267 + shell_cmds/hexdump/odsyntax.c | 447 + shell_cmds/hexdump/parse.c | 523 + shell_cmds/hostname/hostname.1 | 67 + shell_cmds/hostname/hostname.c | 105 + shell_cmds/id/groups.1 | 63 + shell_cmds/id/id.1 | 167 + shell_cmds/id/id.c | 529 + shell_cmds/id/open_directory.c | 229 + shell_cmds/id/open_directory.h | 18 + shell_cmds/id/whoami.1 | 60 + shell_cmds/jot/jot.1 | 251 + shell_cmds/jot/jot.c | 490 + shell_cmds/kill/kill.1 | 152 + shell_cmds/kill/kill.c | 230 + shell_cmds/kill/kill.plist.part | 18 + shell_cmds/killall/killall.1 | 159 + shell_cmds/killall/killall.c | 549 + shell_cmds/lastcomm/lastcomm.1 | 132 + shell_cmds/lastcomm/lastcomm.c | 235 + shell_cmds/lastcomm/pathnames.h | 36 + shell_cmds/locate/bigram/locate.bigram.8 | 1 + shell_cmds/locate/bigram/locate.bigram.c | 110 + shell_cmds/locate/code/locate.code.8 | 23 + shell_cmds/locate/code/locate.code.c | 279 + .../locate/locate/com.apple.locate.plist | 35 + shell_cmds/locate/locate/concatdb.sh | 70 + shell_cmds/locate/locate/fastfind.c | 338 + shell_cmds/locate/locate/locate.1 | 276 + shell_cmds/locate/locate/locate.c | 389 + shell_cmds/locate/locate/locate.h | 76 + shell_cmds/locate/locate/locate.rc | 26 + shell_cmds/locate/locate/locate.updatedb.8 | 75 + shell_cmds/locate/locate/mklocatedb.sh | 92 + shell_cmds/locate/locate/pathnames.h | 36 + shell_cmds/locate/locate/updatedb.sh | 106 + shell_cmds/locate/locate/util.c | 278 + shell_cmds/logname/logname.1 | 78 + shell_cmds/logname/logname.c | 92 + shell_cmds/mktemp/mktemp.1 | 215 + shell_cmds/mktemp/mktemp.c | 182 + shell_cmds/mktemp/mktemp.plist.part | 21 + shell_cmds/nice/nice.1 | 120 + shell_cmds/nice/nice.c | 122 + shell_cmds/nohup/nohup.1 | 124 + shell_cmds/nohup/nohup.c | 149 + shell_cmds/path_helper/path_helper.8 | 76 + shell_cmds/path_helper/path_helper.c | 201 + shell_cmds/printenv/printenv.1 | 84 + shell_cmds/printenv/printenv.c | 99 + shell_cmds/printf/printf.1 | 418 + shell_cmds/printf/printf.c | 697 ++ shell_cmds/printf/printf.plist.part | 18 + shell_cmds/printf/tests/Makefile | 23 + shell_cmds/printf/tests/Makefile.depend | 11 + shell_cmds/printf/tests/legacy_test.sh | 6 + shell_cmds/printf/tests/regress.b.out | 1 + shell_cmds/printf/tests/regress.bwidth.out | 1 + shell_cmds/printf/tests/regress.d.out | 1 + shell_cmds/printf/tests/regress.f.out | 1 + shell_cmds/printf/tests/regress.l1.out | 1 + shell_cmds/printf/tests/regress.l2.out | 1 + shell_cmds/printf/tests/regress.m1.out | Bin 0 -> 7 bytes shell_cmds/printf/tests/regress.m2.out | 2 + shell_cmds/printf/tests/regress.m3.out | 4 + shell_cmds/printf/tests/regress.m4.out | 1 + shell_cmds/printf/tests/regress.m5.out | 1 + .../printf/tests/regress.missingpos1.out | 1 + shell_cmds/printf/tests/regress.s.out | 1 + shell_cmds/printf/tests/regress.sh | 32 + shell_cmds/printf/tests/regress.zero.out | 1 + shell_cmds/pwd/pwd.1 | 103 + shell_cmds/pwd/pwd.c | 127 + shell_cmds/renice/renice.8 | 138 + shell_cmds/renice/renice.c | 203 + shell_cmds/script/script.1 | 217 + shell_cmds/script/script.c | 546 + shell_cmds/script/script.plist.part | 20 + shell_cmds/seq/seq.1 | 187 + shell_cmds/seq/seq.c | 453 + shell_cmds/sh/Makefile | 70 + shell_cmds/sh/Makefile.depend | 19 + shell_cmds/sh/TOUR | 301 + shell_cmds/sh/alias.c | 256 + shell_cmds/sh/alias.h | 45 + shell_cmds/sh/arith.h | 37 + shell_cmds/sh/arith_yacc.c | 381 + shell_cmds/sh/arith_yacc.h | 93 + shell_cmds/sh/arith_yylex.c | 248 + shell_cmds/sh/bltin/bltin.h | 81 + shell_cmds/sh/bltin/echo.c | 109 + shell_cmds/sh/builtins.def | 96 + shell_cmds/sh/cd.c | 430 + shell_cmds/sh/cd.h | 32 + shell_cmds/sh/error.c | 199 + shell_cmds/sh/error.h | 95 + shell_cmds/sh/eval.c | 1381 +++ shell_cmds/sh/eval.h | 70 + shell_cmds/sh/exec.c | 780 ++ shell_cmds/sh/exec.h | 77 + shell_cmds/sh/expand.c | 1550 +++ shell_cmds/sh/expand.h | 62 + shell_cmds/sh/funcs/cmv | 49 + shell_cmds/sh/funcs/dirs | 73 + shell_cmds/sh/funcs/login | 38 + shell_cmds/sh/funcs/newgrp | 37 + shell_cmds/sh/funcs/popd | 73 + shell_cmds/sh/funcs/pushd | 73 + shell_cmds/sh/funcs/suspend | 39 + shell_cmds/sh/histedit.c | 502 + shell_cmds/sh/input.c | 536 + shell_cmds/sh/input.h | 65 + shell_cmds/sh/jobs.c | 1552 +++ shell_cmds/sh/jobs.h | 67 + shell_cmds/sh/mail.c | 117 + shell_cmds/sh/mail.h | 38 + shell_cmds/sh/main.c | 351 + shell_cmds/sh/main.h | 42 + shell_cmds/sh/memalloc.c | 344 + shell_cmds/sh/memalloc.h | 88 + shell_cmds/sh/miscbltin.c | 534 + shell_cmds/sh/mkbuiltins | 137 + shell_cmds/sh/mknodes.c | 467 + shell_cmds/sh/mksyntax.c | 331 + shell_cmds/sh/mktokens | 93 + shell_cmds/sh/myhistedit.h | 44 + shell_cmds/sh/mystring.c | 100 + shell_cmds/sh/mystring.h | 43 + shell_cmds/sh/nodes.c.pat | 193 + shell_cmds/sh/nodetypes | 145 + shell_cmds/sh/options.c | 594 ++ shell_cmds/sh/options.h | 115 + shell_cmds/sh/output.c | 370 + shell_cmds/sh/output.h | 85 + shell_cmds/sh/parser.c | 2120 ++++ shell_cmds/sh/parser.h | 87 + shell_cmds/sh/redir.c | 365 + shell_cmds/sh/redir.h | 47 + shell_cmds/sh/sh.1 | 2879 ++++++ shell_cmds/sh/sh.plist.part | 23 + shell_cmds/sh/shell.h | 79 + shell_cmds/sh/show.c | 410 + shell_cmds/sh/show.h | 42 + shell_cmds/sh/tests/Makefile | 14 + shell_cmds/sh/tests/Makefile.depend | 11 + shell_cmds/sh/tests/builtins/Makefile | 185 + shell_cmds/sh/tests/builtins/Makefile.depend | 11 + shell_cmds/sh/tests/builtins/alias.0 | 9 + shell_cmds/sh/tests/builtins/alias.0.stdout | 4 + shell_cmds/sh/tests/builtins/alias.1 | 3 + shell_cmds/sh/tests/builtins/alias.1.stderr | 1 + shell_cmds/sh/tests/builtins/alias3.0 | 12 + shell_cmds/sh/tests/builtins/alias3.0.stdout | 4 + shell_cmds/sh/tests/builtins/alias4.0 | 4 + shell_cmds/sh/tests/builtins/break1.0 | 16 + shell_cmds/sh/tests/builtins/break2.0 | 12 + shell_cmds/sh/tests/builtins/break2.0.stdout | 1 + shell_cmds/sh/tests/builtins/break3.0 | 15 + shell_cmds/sh/tests/builtins/break4.4 | 7 + shell_cmds/sh/tests/builtins/break5.4 | 12 + shell_cmds/sh/tests/builtins/break6.0 | 8 + shell_cmds/sh/tests/builtins/builtin1.0 | 31 + shell_cmds/sh/tests/builtins/case1.0 | 13 + shell_cmds/sh/tests/builtins/case10.0 | 16 + shell_cmds/sh/tests/builtins/case11.0 | 6 + shell_cmds/sh/tests/builtins/case12.0 | 6 + shell_cmds/sh/tests/builtins/case13.0 | 12 + shell_cmds/sh/tests/builtins/case14.0 | 5 + shell_cmds/sh/tests/builtins/case15.0 | 5 + shell_cmds/sh/tests/builtins/case16.0 | 7 + shell_cmds/sh/tests/builtins/case17.0 | 3 + shell_cmds/sh/tests/builtins/case18.0 | 7 + shell_cmds/sh/tests/builtins/case19.0 | 7 + shell_cmds/sh/tests/builtins/case2.0 | 106 + shell_cmds/sh/tests/builtins/case20.0 | 9 + shell_cmds/sh/tests/builtins/case21.0 | 10 + shell_cmds/sh/tests/builtins/case22.0 | 10 + shell_cmds/sh/tests/builtins/case3.0 | 95 + shell_cmds/sh/tests/builtins/case4.0 | 6 + shell_cmds/sh/tests/builtins/case5.0 | 57 + shell_cmds/sh/tests/builtins/case6.0 | 52 + shell_cmds/sh/tests/builtins/case7.0 | 24 + shell_cmds/sh/tests/builtins/case8.0 | 32 + shell_cmds/sh/tests/builtins/case9.0 | 39 + shell_cmds/sh/tests/builtins/cd1.0 | 30 + shell_cmds/sh/tests/builtins/cd10.0 | 6 + shell_cmds/sh/tests/builtins/cd2.0 | 16 + shell_cmds/sh/tests/builtins/cd3.0 | 21 + shell_cmds/sh/tests/builtins/cd4.0 | 38 + shell_cmds/sh/tests/builtins/cd5.0 | 23 + shell_cmds/sh/tests/builtins/cd6.0 | 10 + shell_cmds/sh/tests/builtins/cd7.0 | 15 + shell_cmds/sh/tests/builtins/cd8.0 | 26 + shell_cmds/sh/tests/builtins/cd9.0 | 8 + shell_cmds/sh/tests/builtins/cd9.0.stdout | 2 + shell_cmds/sh/tests/builtins/command1.0 | 5 + shell_cmds/sh/tests/builtins/command10.0 | 14 + shell_cmds/sh/tests/builtins/command11.0 | 14 + shell_cmds/sh/tests/builtins/command12.0 | 7 + shell_cmds/sh/tests/builtins/command2.0 | 3 + shell_cmds/sh/tests/builtins/command3.0 | 14 + .../sh/tests/builtins/command3.0.stdout | 7 + shell_cmds/sh/tests/builtins/command4.0 | 2 + shell_cmds/sh/tests/builtins/command5.0 | 15 + .../sh/tests/builtins/command5.0.stdout | 8 + shell_cmds/sh/tests/builtins/command6.0 | 22 + .../sh/tests/builtins/command6.0.stdout | 7 + shell_cmds/sh/tests/builtins/command7.0 | 34 + shell_cmds/sh/tests/builtins/command8.0 | 45 + shell_cmds/sh/tests/builtins/command9.0 | 14 + shell_cmds/sh/tests/builtins/dot1.0 | 21 + shell_cmds/sh/tests/builtins/dot2.0 | 21 + shell_cmds/sh/tests/builtins/dot3.0 | 10 + shell_cmds/sh/tests/builtins/dot4.0 | 12 + shell_cmds/sh/tests/builtins/echo1.0 | 6 + shell_cmds/sh/tests/builtins/echo2.0 | 7 + shell_cmds/sh/tests/builtins/echo3.0 | 5 + shell_cmds/sh/tests/builtins/eval1.0 | 9 + shell_cmds/sh/tests/builtins/eval2.0 | 7 + shell_cmds/sh/tests/builtins/eval3.0 | 9 + shell_cmds/sh/tests/builtins/eval4.0 | 5 + shell_cmds/sh/tests/builtins/eval5.0 | 4 + shell_cmds/sh/tests/builtins/eval6.0 | 5 + shell_cmds/sh/tests/builtins/eval7.0 | 9 + shell_cmds/sh/tests/builtins/eval8.7 | 7 + shell_cmds/sh/tests/builtins/exec1.0 | 25 + shell_cmds/sh/tests/builtins/exec2.0 | 25 + shell_cmds/sh/tests/builtins/exit1.0 | 6 + shell_cmds/sh/tests/builtins/exit2.8 | 7 + shell_cmds/sh/tests/builtins/exit3.0 | 5 + shell_cmds/sh/tests/builtins/export1.0 | 3 + shell_cmds/sh/tests/builtins/fc1.0 | 27 + shell_cmds/sh/tests/builtins/fc2.0 | 34 + shell_cmds/sh/tests/builtins/for1.0 | 4 + shell_cmds/sh/tests/builtins/for2.0 | 9 + shell_cmds/sh/tests/builtins/for3.0 | 8 + shell_cmds/sh/tests/builtins/getopts1.0 | 25 + .../sh/tests/builtins/getopts1.0.stdout | 8 + shell_cmds/sh/tests/builtins/getopts10.0 | 11 + shell_cmds/sh/tests/builtins/getopts2.0 | 6 + .../sh/tests/builtins/getopts2.0.stdout | 1 + shell_cmds/sh/tests/builtins/getopts3.0 | 6 + shell_cmds/sh/tests/builtins/getopts4.0 | 10 + shell_cmds/sh/tests/builtins/getopts5.0 | 10 + shell_cmds/sh/tests/builtins/getopts6.0 | 7 + shell_cmds/sh/tests/builtins/getopts7.0 | 6 + shell_cmds/sh/tests/builtins/getopts8.0 | 8 + .../sh/tests/builtins/getopts8.0.stdout | 5 + shell_cmds/sh/tests/builtins/getopts9.0 | 9 + .../sh/tests/builtins/getopts9.0.stdout | 3 + shell_cmds/sh/tests/builtins/hash1.0 | 5 + shell_cmds/sh/tests/builtins/hash1.0.stdout | 1 + shell_cmds/sh/tests/builtins/hash2.0 | 4 + shell_cmds/sh/tests/builtins/hash2.0.stdout | 1 + shell_cmds/sh/tests/builtins/hash3.0 | 3 + shell_cmds/sh/tests/builtins/hash3.0.stdout | 2 + shell_cmds/sh/tests/builtins/hash4.0 | 6 + shell_cmds/sh/tests/builtins/jobid1.0 | 7 + shell_cmds/sh/tests/builtins/jobid2.0 | 9 + shell_cmds/sh/tests/builtins/kill1.0 | 8 + shell_cmds/sh/tests/builtins/kill2.0 | 7 + shell_cmds/sh/tests/builtins/lineno.0 | 16 + shell_cmds/sh/tests/builtins/lineno.0.stdout | 9 + shell_cmds/sh/tests/builtins/lineno2.0 | 10 + shell_cmds/sh/tests/builtins/lineno3.0 | 6 + shell_cmds/sh/tests/builtins/lineno3.0.stdout | 2 + shell_cmds/sh/tests/builtins/local1.0 | 13 + shell_cmds/sh/tests/builtins/local2.0 | 17 + shell_cmds/sh/tests/builtins/local3.0 | 26 + shell_cmds/sh/tests/builtins/local4.0 | 12 + shell_cmds/sh/tests/builtins/local5.0 | 15 + shell_cmds/sh/tests/builtins/local6.0 | 10 + shell_cmds/sh/tests/builtins/local7.0 | 10 + shell_cmds/sh/tests/builtins/locale1.0 | 134 + shell_cmds/sh/tests/builtins/locale2.0 | 5 + shell_cmds/sh/tests/builtins/printf1.0 | 3 + shell_cmds/sh/tests/builtins/printf2.0 | 3 + shell_cmds/sh/tests/builtins/printf3.0 | 5 + shell_cmds/sh/tests/builtins/printf4.0 | 5 + shell_cmds/sh/tests/builtins/read1.0 | 26 + shell_cmds/sh/tests/builtins/read1.0.stdout | 20 + shell_cmds/sh/tests/builtins/read2.0 | 31 + shell_cmds/sh/tests/builtins/read3.0 | 11 + shell_cmds/sh/tests/builtins/read3.0.stdout | 9 + shell_cmds/sh/tests/builtins/read4.0 | 10 + shell_cmds/sh/tests/builtins/read4.0.stdout | 8 + shell_cmds/sh/tests/builtins/read5.0 | 32 + shell_cmds/sh/tests/builtins/read6.0 | 5 + shell_cmds/sh/tests/builtins/read7.0 | 5 + shell_cmds/sh/tests/builtins/read8.0 | 17 + shell_cmds/sh/tests/builtins/read9.0 | 10 + shell_cmds/sh/tests/builtins/return1.0 | 7 + shell_cmds/sh/tests/builtins/return2.1 | 7 + shell_cmds/sh/tests/builtins/return3.1 | 3 + shell_cmds/sh/tests/builtins/return4.0 | 16 + shell_cmds/sh/tests/builtins/return5.0 | 17 + shell_cmds/sh/tests/builtins/return6.4 | 3 + shell_cmds/sh/tests/builtins/return7.4 | 6 + shell_cmds/sh/tests/builtins/return8.0 | 13 + shell_cmds/sh/tests/builtins/set1.0 | 32 + shell_cmds/sh/tests/builtins/set2.0 | 3 + shell_cmds/sh/tests/builtins/set3.0 | 4 + shell_cmds/sh/tests/builtins/trap1.0 | 22 + shell_cmds/sh/tests/builtins/trap10.0 | 6 + shell_cmds/sh/tests/builtins/trap11.0 | 8 + shell_cmds/sh/tests/builtins/trap12.0 | 10 + shell_cmds/sh/tests/builtins/trap13.0 | 8 + shell_cmds/sh/tests/builtins/trap14.0 | 10 + shell_cmds/sh/tests/builtins/trap15.0 | 5 + shell_cmds/sh/tests/builtins/trap16.0 | 20 + shell_cmds/sh/tests/builtins/trap17.0 | 10 + shell_cmds/sh/tests/builtins/trap2.0 | 52 + shell_cmds/sh/tests/builtins/trap3.0 | 11 + shell_cmds/sh/tests/builtins/trap4.0 | 17 + shell_cmds/sh/tests/builtins/trap5.0 | 19 + shell_cmds/sh/tests/builtins/trap6.0 | 9 + shell_cmds/sh/tests/builtins/trap7.0 | 3 + shell_cmds/sh/tests/builtins/trap8.0 | 7 + shell_cmds/sh/tests/builtins/trap9.0 | 3 + shell_cmds/sh/tests/builtins/type1.0 | 8 + shell_cmds/sh/tests/builtins/type1.0.stderr | 4 + shell_cmds/sh/tests/builtins/type2.0 | 26 + shell_cmds/sh/tests/builtins/type3.0 | 3 + shell_cmds/sh/tests/builtins/unalias.0 | 21 + shell_cmds/sh/tests/builtins/var-assign.0 | 55 + shell_cmds/sh/tests/builtins/var-assign2.0 | 55 + shell_cmds/sh/tests/builtins/wait1.0 | 23 + shell_cmds/sh/tests/builtins/wait10.0 | 5 + shell_cmds/sh/tests/builtins/wait2.0 | 15 + shell_cmds/sh/tests/builtins/wait3.0 | 21 + shell_cmds/sh/tests/builtins/wait4.0 | 12 + shell_cmds/sh/tests/builtins/wait5.0 | 12 + shell_cmds/sh/tests/builtins/wait6.0 | 3 + shell_cmds/sh/tests/builtins/wait7.0 | 4 + shell_cmds/sh/tests/builtins/wait8.0 | 7 + shell_cmds/sh/tests/builtins/wait9.127 | 3 + shell_cmds/sh/tests/errors/Makefile | 35 + shell_cmds/sh/tests/errors/Makefile.depend | 11 + .../sh/tests/errors/assignment-error1.0 | 30 + .../sh/tests/errors/assignment-error2.0 | 8 + shell_cmds/sh/tests/errors/backquote-error1.0 | 4 + shell_cmds/sh/tests/errors/backquote-error2.0 | 7 + shell_cmds/sh/tests/errors/bad-binary1.126 | 12 + shell_cmds/sh/tests/errors/bad-keyword1.0 | 4 + shell_cmds/sh/tests/errors/bad-parm-exp1.0 | 7 + shell_cmds/sh/tests/errors/bad-parm-exp2.2 | 2 + .../sh/tests/errors/bad-parm-exp2.2.stderr | 1 + shell_cmds/sh/tests/errors/bad-parm-exp3.2 | 2 + .../sh/tests/errors/bad-parm-exp3.2.stderr | 1 + shell_cmds/sh/tests/errors/bad-parm-exp4.2 | 2 + .../sh/tests/errors/bad-parm-exp4.2.stderr | 1 + shell_cmds/sh/tests/errors/bad-parm-exp5.2 | 2 + .../sh/tests/errors/bad-parm-exp5.2.stderr | 1 + shell_cmds/sh/tests/errors/bad-parm-exp6.2 | 2 + .../sh/tests/errors/bad-parm-exp6.2.stderr | 1 + shell_cmds/sh/tests/errors/bad-parm-exp7.0 | 4 + shell_cmds/sh/tests/errors/bad-parm-exp8.0 | 4 + shell_cmds/sh/tests/errors/option-error.0 | 46 + .../sh/tests/errors/redirection-error.0 | 53 + .../sh/tests/errors/redirection-error2.2 | 4 + .../sh/tests/errors/redirection-error3.0 | 54 + .../sh/tests/errors/redirection-error4.0 | 7 + .../sh/tests/errors/redirection-error5.0 | 5 + .../sh/tests/errors/redirection-error6.0 | 12 + .../sh/tests/errors/redirection-error7.0 | 7 + .../sh/tests/errors/redirection-error8.0 | 5 + shell_cmds/sh/tests/errors/write-error1.0 | 3 + shell_cmds/sh/tests/execution/Makefile | 57 + shell_cmds/sh/tests/execution/Makefile.depend | 11 + shell_cmds/sh/tests/execution/bg1.0 | 3 + shell_cmds/sh/tests/execution/bg10.0 | 4 + shell_cmds/sh/tests/execution/bg10.0.stdout | 1 + shell_cmds/sh/tests/execution/bg2.0 | 5 + shell_cmds/sh/tests/execution/bg3.0 | 5 + shell_cmds/sh/tests/execution/bg4.0 | 6 + shell_cmds/sh/tests/execution/bg5.0 | 4 + shell_cmds/sh/tests/execution/bg6.0 | 4 + shell_cmds/sh/tests/execution/bg6.0.stdout | 1 + shell_cmds/sh/tests/execution/bg7.0 | 5 + shell_cmds/sh/tests/execution/bg8.0 | 5 + shell_cmds/sh/tests/execution/bg9.0 | 5 + shell_cmds/sh/tests/execution/fork1.0 | 10 + shell_cmds/sh/tests/execution/fork2.0 | 9 + shell_cmds/sh/tests/execution/fork3.0 | 4 + shell_cmds/sh/tests/execution/func1.0 | 4 + shell_cmds/sh/tests/execution/func2.0 | 12 + shell_cmds/sh/tests/execution/func3.0 | 7 + shell_cmds/sh/tests/execution/hash1.0 | 12 + shell_cmds/sh/tests/execution/int-cmd1.0 | 3 + shell_cmds/sh/tests/execution/killed1.0 | 8 + shell_cmds/sh/tests/execution/killed2.0 | 10 + shell_cmds/sh/tests/execution/not1.0 | 4 + shell_cmds/sh/tests/execution/not2.0 | 6 + shell_cmds/sh/tests/execution/path1.0 | 15 + shell_cmds/sh/tests/execution/redir1.0 | 27 + shell_cmds/sh/tests/execution/redir2.0 | 29 + shell_cmds/sh/tests/execution/redir3.0 | 3 + shell_cmds/sh/tests/execution/redir4.0 | 4 + shell_cmds/sh/tests/execution/redir5.0 | 3 + shell_cmds/sh/tests/execution/redir6.0 | 21 + shell_cmds/sh/tests/execution/redir7.0 | 21 + shell_cmds/sh/tests/execution/set-C1.0 | 12 + shell_cmds/sh/tests/execution/set-n1.0 | 7 + shell_cmds/sh/tests/execution/set-n2.0 | 5 + shell_cmds/sh/tests/execution/set-n3.0 | 4 + shell_cmds/sh/tests/execution/set-n4.0 | 3 + shell_cmds/sh/tests/execution/set-x1.0 | 8 + shell_cmds/sh/tests/execution/set-x2.0 | 9 + shell_cmds/sh/tests/execution/set-x3.0 | 9 + shell_cmds/sh/tests/execution/set-x4.0 | 7 + shell_cmds/sh/tests/execution/shellproc1.0 | 11 + shell_cmds/sh/tests/execution/subshell1.0 | 6 + .../sh/tests/execution/subshell1.0.stdout | 2 + shell_cmds/sh/tests/execution/subshell2.0 | 10 + shell_cmds/sh/tests/execution/subshell3.0 | 4 + shell_cmds/sh/tests/execution/subshell4.0 | 3 + shell_cmds/sh/tests/execution/unknown1.0 | 29 + shell_cmds/sh/tests/execution/var-assign1.0 | 3 + shell_cmds/sh/tests/expansion/Makefile | 105 + shell_cmds/sh/tests/expansion/Makefile.depend | 11 + shell_cmds/sh/tests/expansion/arith1.0 | 30 + shell_cmds/sh/tests/expansion/arith10.0 | 35 + shell_cmds/sh/tests/expansion/arith11.0 | 12 + shell_cmds/sh/tests/expansion/arith12.0 | 4 + shell_cmds/sh/tests/expansion/arith13.0 | 6 + shell_cmds/sh/tests/expansion/arith14.0 | 40 + shell_cmds/sh/tests/expansion/arith2.0 | 77 + shell_cmds/sh/tests/expansion/arith3.0 | 14 + shell_cmds/sh/tests/expansion/arith4.0 | 20 + shell_cmds/sh/tests/expansion/arith5.0 | 17 + shell_cmds/sh/tests/expansion/arith6.0 | 16 + shell_cmds/sh/tests/expansion/arith7.0 | 12 + shell_cmds/sh/tests/expansion/arith8.0 | 4 + shell_cmds/sh/tests/expansion/arith9.0 | 20 + shell_cmds/sh/tests/expansion/assign1.0 | 37 + shell_cmds/sh/tests/expansion/cmdsubst1.0 | 48 + shell_cmds/sh/tests/expansion/cmdsubst10.0 | 51 + shell_cmds/sh/tests/expansion/cmdsubst11.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst12.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst13.0 | 12 + shell_cmds/sh/tests/expansion/cmdsubst14.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst15.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst16.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst17.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst18.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst19.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst2.0 | 43 + shell_cmds/sh/tests/expansion/cmdsubst20.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst21.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst22.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst23.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst24.0 | 24 + shell_cmds/sh/tests/expansion/cmdsubst25.0 | 7 + shell_cmds/sh/tests/expansion/cmdsubst26.0 | 6 + shell_cmds/sh/tests/expansion/cmdsubst3.0 | 23 + shell_cmds/sh/tests/expansion/cmdsubst4.0 | 4 + shell_cmds/sh/tests/expansion/cmdsubst5.0 | 5 + shell_cmds/sh/tests/expansion/cmdsubst6.0 | 53 + shell_cmds/sh/tests/expansion/cmdsubst7.0 | 31 + shell_cmds/sh/tests/expansion/cmdsubst8.0 | 17 + shell_cmds/sh/tests/expansion/cmdsubst9.0 | 11 + shell_cmds/sh/tests/expansion/export1.0 | 13 + shell_cmds/sh/tests/expansion/export2.0 | 24 + shell_cmds/sh/tests/expansion/export3.0 | 30 + shell_cmds/sh/tests/expansion/heredoc1.0 | 25 + shell_cmds/sh/tests/expansion/heredoc2.0 | 15 + shell_cmds/sh/tests/expansion/ifs1.0 | 35 + shell_cmds/sh/tests/expansion/ifs2.0 | 24 + shell_cmds/sh/tests/expansion/ifs3.0 | 21 + shell_cmds/sh/tests/expansion/ifs4.0 | 39 + shell_cmds/sh/tests/expansion/ifs5.0 | 4 + shell_cmds/sh/tests/expansion/ifs6.0 | 6 + shell_cmds/sh/tests/expansion/ifs7.0 | 5 + shell_cmds/sh/tests/expansion/length1.0 | 12 + shell_cmds/sh/tests/expansion/length2.0 | 4 + shell_cmds/sh/tests/expansion/length3.0 | 10 + shell_cmds/sh/tests/expansion/length4.0 | 11 + shell_cmds/sh/tests/expansion/length5.0 | 27 + shell_cmds/sh/tests/expansion/length6.0 | 8 + shell_cmds/sh/tests/expansion/length7.0 | 14 + shell_cmds/sh/tests/expansion/length8.0 | 14 + shell_cmds/sh/tests/expansion/local1.0 | 28 + shell_cmds/sh/tests/expansion/local2.0 | 34 + shell_cmds/sh/tests/expansion/pathname1.0 | 65 + shell_cmds/sh/tests/expansion/pathname2.0 | 35 + shell_cmds/sh/tests/expansion/pathname3.0 | 29 + shell_cmds/sh/tests/expansion/pathname4.0 | 28 + shell_cmds/sh/tests/expansion/pathname5.0 | 3 + shell_cmds/sh/tests/expansion/pathname6.0 | 29 + shell_cmds/sh/tests/expansion/plus-minus1.0 | 76 + shell_cmds/sh/tests/expansion/plus-minus2.0 | 4 + shell_cmds/sh/tests/expansion/plus-minus3.0 | 44 + shell_cmds/sh/tests/expansion/plus-minus4.0 | 38 + shell_cmds/sh/tests/expansion/plus-minus5.0 | 31 + shell_cmds/sh/tests/expansion/plus-minus6.0 | 34 + shell_cmds/sh/tests/expansion/plus-minus7.0 | 26 + shell_cmds/sh/tests/expansion/plus-minus8.0 | 5 + shell_cmds/sh/tests/expansion/question1.0 | 22 + shell_cmds/sh/tests/expansion/readonly1.0 | 7 + shell_cmds/sh/tests/expansion/redir1.0 | 26 + shell_cmds/sh/tests/expansion/set-u1.0 | 29 + shell_cmds/sh/tests/expansion/set-u2.0 | 12 + shell_cmds/sh/tests/expansion/set-u3.0 | 6 + shell_cmds/sh/tests/expansion/tilde1.0 | 56 + shell_cmds/sh/tests/expansion/tilde2.0 | 90 + shell_cmds/sh/tests/expansion/trim1.0 | 85 + shell_cmds/sh/tests/expansion/trim2.0 | 55 + shell_cmds/sh/tests/expansion/trim3.0 | 46 + shell_cmds/sh/tests/expansion/trim4.0 | 15 + shell_cmds/sh/tests/expansion/trim5.0 | 28 + shell_cmds/sh/tests/expansion/trim6.0 | 22 + shell_cmds/sh/tests/expansion/trim7.0 | 16 + shell_cmds/sh/tests/expansion/trim8.0 | 75 + shell_cmds/sh/tests/expansion/trim9.0 | 61 + shell_cmds/sh/tests/functional_test.sh | 72 + shell_cmds/sh/tests/invocation/Makefile | 16 + .../sh/tests/invocation/Makefile.depend | 11 + shell_cmds/sh/tests/invocation/sh-ac1.0 | 7 + .../sh/tests/invocation/sh-c-missing1.0 | 3 + shell_cmds/sh/tests/invocation/sh-c1.0 | 4 + shell_cmds/sh/tests/invocation/sh-ca1.0 | 7 + shell_cmds/sh/tests/invocation/sh-fca1.0 | 7 + shell_cmds/sh/tests/parameters/Makefile | 29 + .../sh/tests/parameters/Makefile.depend | 11 + shell_cmds/sh/tests/parameters/env1.0 | 11 + shell_cmds/sh/tests/parameters/exitstatus1.0 | 9 + shell_cmds/sh/tests/parameters/ifs1.0 | 10 + shell_cmds/sh/tests/parameters/mail1.0 | 15 + shell_cmds/sh/tests/parameters/mail2.0 | 15 + shell_cmds/sh/tests/parameters/optind1.0 | 3 + shell_cmds/sh/tests/parameters/optind2.0 | 3 + shell_cmds/sh/tests/parameters/positional1.0 | 13 + shell_cmds/sh/tests/parameters/positional2.0 | 65 + shell_cmds/sh/tests/parameters/positional3.0 | 4 + shell_cmds/sh/tests/parameters/positional4.0 | 4 + shell_cmds/sh/tests/parameters/positional5.0 | 14 + shell_cmds/sh/tests/parameters/positional6.0 | 7 + shell_cmds/sh/tests/parameters/positional7.0 | 8 + shell_cmds/sh/tests/parameters/positional8.0 | 31 + shell_cmds/sh/tests/parameters/positional9.0 | 18 + shell_cmds/sh/tests/parameters/pwd1.0 | 11 + shell_cmds/sh/tests/parameters/pwd2.0 | 24 + shell_cmds/sh/tests/parser/Makefile | 88 + shell_cmds/sh/tests/parser/Makefile.depend | 11 + shell_cmds/sh/tests/parser/alias1.0 | 5 + shell_cmds/sh/tests/parser/alias10.0 | 9 + shell_cmds/sh/tests/parser/alias11.0 | 6 + shell_cmds/sh/tests/parser/alias12.0 | 6 + shell_cmds/sh/tests/parser/alias13.0 | 6 + shell_cmds/sh/tests/parser/alias14.0 | 6 + shell_cmds/sh/tests/parser/alias15.0 | 12 + shell_cmds/sh/tests/parser/alias15.0.stdout | 4 + shell_cmds/sh/tests/parser/alias16.0 | 7 + shell_cmds/sh/tests/parser/alias17.0 | 7 + shell_cmds/sh/tests/parser/alias18.0 | 8 + shell_cmds/sh/tests/parser/alias2.0 | 6 + shell_cmds/sh/tests/parser/alias3.0 | 6 + shell_cmds/sh/tests/parser/alias4.0 | 5 + shell_cmds/sh/tests/parser/alias5.0 | 5 + shell_cmds/sh/tests/parser/alias6.0 | 6 + shell_cmds/sh/tests/parser/alias7.0 | 4 + shell_cmds/sh/tests/parser/alias8.0 | 4 + shell_cmds/sh/tests/parser/alias9.0 | 6 + shell_cmds/sh/tests/parser/and-pipe-not.0 | 2 + shell_cmds/sh/tests/parser/case1.0 | 14 + shell_cmds/sh/tests/parser/case2.0 | 32 + shell_cmds/sh/tests/parser/comment1.0 | 3 + shell_cmds/sh/tests/parser/comment2.42 | 4 + shell_cmds/sh/tests/parser/dollar-quote1.0 | 12 + shell_cmds/sh/tests/parser/dollar-quote10.0 | 10 + shell_cmds/sh/tests/parser/dollar-quote11.0 | 8 + shell_cmds/sh/tests/parser/dollar-quote12.0 | 7 + shell_cmds/sh/tests/parser/dollar-quote13.0 | 8 + shell_cmds/sh/tests/parser/dollar-quote2.0 | 5 + shell_cmds/sh/tests/parser/dollar-quote3.0 | 22 + shell_cmds/sh/tests/parser/dollar-quote4.0 | 19 + shell_cmds/sh/tests/parser/dollar-quote5.0 | 12 + shell_cmds/sh/tests/parser/dollar-quote6.0 | 5 + shell_cmds/sh/tests/parser/dollar-quote7.0 | 6 + shell_cmds/sh/tests/parser/dollar-quote8.0 | 11 + shell_cmds/sh/tests/parser/dollar-quote9.0 | 8 + shell_cmds/sh/tests/parser/empty-braces1.0 | 7 + shell_cmds/sh/tests/parser/empty-cmd1.0 | 3 + shell_cmds/sh/tests/parser/for1.0 | 29 + shell_cmds/sh/tests/parser/for2.0 | 15 + shell_cmds/sh/tests/parser/func1.0 | 25 + shell_cmds/sh/tests/parser/func2.0 | 6 + shell_cmds/sh/tests/parser/func3.0 | 6 + shell_cmds/sh/tests/parser/heredoc1.0 | 85 + shell_cmds/sh/tests/parser/heredoc10.0 | 49 + shell_cmds/sh/tests/parser/heredoc11.0 | 26 + shell_cmds/sh/tests/parser/heredoc12.0 | 47 + shell_cmds/sh/tests/parser/heredoc13.0 | 21 + shell_cmds/sh/tests/parser/heredoc2.0 | 39 + shell_cmds/sh/tests/parser/heredoc3.0 | 7 + shell_cmds/sh/tests/parser/heredoc4.0 | 44 + shell_cmds/sh/tests/parser/heredoc5.0 | 56 + shell_cmds/sh/tests/parser/heredoc6.0 | 5 + shell_cmds/sh/tests/parser/heredoc7.0 | 19 + shell_cmds/sh/tests/parser/heredoc8.0 | 20 + shell_cmds/sh/tests/parser/heredoc9.0 | 58 + shell_cmds/sh/tests/parser/line-cont1.0 | 16 + shell_cmds/sh/tests/parser/line-cont10.0 | 18 + shell_cmds/sh/tests/parser/line-cont11.0 | 23 + shell_cmds/sh/tests/parser/line-cont2.0 | 4 + shell_cmds/sh/tests/parser/line-cont3.0 | 7 + shell_cmds/sh/tests/parser/line-cont4.0 | 8 + shell_cmds/sh/tests/parser/line-cont5.0 | 14 + shell_cmds/sh/tests/parser/line-cont6.0 | 23 + shell_cmds/sh/tests/parser/line-cont7.0 | 7 + shell_cmds/sh/tests/parser/line-cont8.0 | 6 + shell_cmds/sh/tests/parser/line-cont9.0 | 6 + shell_cmds/sh/tests/parser/no-space1.0 | 18 + shell_cmds/sh/tests/parser/no-space2.0 | 7 + shell_cmds/sh/tests/parser/nul1.0 | 12 + shell_cmds/sh/tests/parser/only-redir1.0 | 3 + shell_cmds/sh/tests/parser/only-redir2.0 | 2 + shell_cmds/sh/tests/parser/only-redir3.0 | 2 + shell_cmds/sh/tests/parser/only-redir4.0 | 2 + shell_cmds/sh/tests/parser/pipe-not1.0 | 3 + shell_cmds/sh/tests/parser/set-v1.0 | 8 + shell_cmds/sh/tests/parser/set-v1.0.stderr | 5 + shell_cmds/sh/tests/parser/var-assign1.0 | 19 + shell_cmds/sh/tests/set-e/Makefile | 46 + shell_cmds/sh/tests/set-e/Makefile.depend | 11 + shell_cmds/sh/tests/set-e/and1.0 | 3 + shell_cmds/sh/tests/set-e/and2.1 | 4 + shell_cmds/sh/tests/set-e/and3.0 | 4 + shell_cmds/sh/tests/set-e/and4.0 | 4 + shell_cmds/sh/tests/set-e/background1.0 | 3 + shell_cmds/sh/tests/set-e/cmd1.0 | 3 + shell_cmds/sh/tests/set-e/cmd2.1 | 4 + shell_cmds/sh/tests/set-e/elif1.0 | 7 + shell_cmds/sh/tests/set-e/elif2.0 | 7 + shell_cmds/sh/tests/set-e/eval1.0 | 3 + shell_cmds/sh/tests/set-e/eval2.1 | 4 + shell_cmds/sh/tests/set-e/for1.0 | 9 + shell_cmds/sh/tests/set-e/func1.0 | 7 + shell_cmds/sh/tests/set-e/func2.1 | 7 + shell_cmds/sh/tests/set-e/if1.0 | 5 + shell_cmds/sh/tests/set-e/if2.0 | 7 + shell_cmds/sh/tests/set-e/if3.0 | 5 + shell_cmds/sh/tests/set-e/not1.0 | 4 + shell_cmds/sh/tests/set-e/not2.0 | 4 + shell_cmds/sh/tests/set-e/or1.0 | 3 + shell_cmds/sh/tests/set-e/or2.0 | 3 + shell_cmds/sh/tests/set-e/or3.1 | 4 + shell_cmds/sh/tests/set-e/pipe1.1 | 4 + shell_cmds/sh/tests/set-e/pipe2.0 | 3 + shell_cmds/sh/tests/set-e/return1.0 | 11 + shell_cmds/sh/tests/set-e/semi1.1 | 4 + shell_cmds/sh/tests/set-e/semi2.1 | 4 + shell_cmds/sh/tests/set-e/subshell1.0 | 3 + shell_cmds/sh/tests/set-e/subshell2.1 | 4 + shell_cmds/sh/tests/set-e/until1.0 | 5 + shell_cmds/sh/tests/set-e/until2.0 | 5 + shell_cmds/sh/tests/set-e/until3.0 | 9 + shell_cmds/sh/tests/set-e/while1.0 | 5 + shell_cmds/sh/tests/set-e/while2.0 | 5 + shell_cmds/sh/tests/set-e/while3.0 | 9 + shell_cmds/sh/trap.c | 556 + shell_cmds/sh/trap.h | 50 + shell_cmds/sh/var.c | 971 ++ shell_cmds/sh/var.h | 132 + .../shell_cmds.xcodeproj/project.pbxproj | 5903 +++++++++++ .../contents.xcworkspacedata | 7 + shell_cmds/shlock/shlock.1 | 147 + shell_cmds/shlock/shlock.c | 364 + shell_cmds/sleep/sleep.1 | 124 + shell_cmds/sleep/sleep.c | 131 + shell_cmds/su/su.1 | 213 + shell_cmds/su/su.c | 737 ++ shell_cmds/su/su.pam | 7 + shell_cmds/su/su_entitlements.plist | 10 + shell_cmds/systime/systime.1 | 76 + shell_cmds/systime/systime.c | 365 + shell_cmds/tee/tee.1 | 90 + shell_cmds/tee/tee.c | 156 + shell_cmds/test/[.1 | 1 + shell_cmds/test/test.1 | 390 + shell_cmds/test/test.c | 611 ++ shell_cmds/test/test.plist.part | 19 + shell_cmds/test/tests/Makefile | 15 + shell_cmds/test/tests/legacy_test.sh | 203 + shell_cmds/tests/regress.m4 | 59 + shell_cmds/tests/shell_cmds.plist | 53 + shell_cmds/time/tests/test_time.sh | 60 + shell_cmds/time/time.1 | 116 + shell_cmds/time/time.c | 245 + shell_cmds/true/true.1 | 60 + shell_cmds/true/true.c | 2 + shell_cmds/true/true.sh | 2 + shell_cmds/uname/uname.1 | 87 + shell_cmds/uname/uname.c | 208 + shell_cmds/users/users.1 | 61 + shell_cmds/users/users.c | 123 + shell_cmds/w/extern.h | 44 + shell_cmds/w/fmt.c | 129 + shell_cmds/w/pr_time.c | 117 + shell_cmds/w/proc_compare.c | 144 + shell_cmds/w/uptime.1 | 52 + shell_cmds/w/w.1 | 127 + shell_cmds/w/w.c | 776 ++ shell_cmds/what/what.1 | 70 + shell_cmds/what/what.c | 97 + shell_cmds/whereis/whereis.1 | 70 + shell_cmds/whereis/whereis.c | 128 + shell_cmds/which/which.1 | 85 + shell_cmds/which/which.c | 146 + shell_cmds/who/utmpentry.c | 348 + shell_cmds/who/utmpentry.h | 78 + shell_cmds/who/who.1 | 130 + shell_cmds/who/who.c | 453 + shell_cmds/xargs/pathnames.h | 36 + shell_cmds/xargs/strnsubst.c | 109 + shell_cmds/xargs/xargs.1 | 389 + shell_cmds/xargs/xargs.c | 840 ++ shell_cmds/xcconfigs/base.xcconfig | 59 + shell_cmds/xcconfigs/sh.xcconfig | 33 + shell_cmds/xcodescripts/builtins-manpages.txt | 85 + shell_cmds/xcodescripts/builtins.txt | 14 + shell_cmds/xcodescripts/install-files.sh | 66 + shell_cmds/yes/yes.1 | 56 + shell_cmds/yes/yes.c | 63 + system_cmds/.upstream_base_commits | 2 + system_cmds/APPLE_LICENSE | 370 + system_cmds/ac.tproj/ac.8 | 86 + system_cmds/ac.tproj/ac.c | 540 + system_cmds/accton.tproj/accton.8 | 42 + system_cmds/accton.tproj/accton.c | 87 + system_cmds/arch.tproj/arch.1 | 245 + system_cmds/arch.tproj/arch.c | 802 ++ system_cmds/arch.tproj/machine.1 | 49 + system_cmds/at.tproj/LEGAL | 29 + system_cmds/at.tproj/at.1 | 369 + system_cmds/at.tproj/at.c | 960 ++ system_cmds/at.tproj/at.h | 31 + system_cmds/at.tproj/panic.c | 92 + system_cmds/at.tproj/panic.h | 32 + system_cmds/at.tproj/parsetime.c | 736 ++ system_cmds/at.tproj/parsetime.h | 26 + system_cmds/at.tproj/pathnames.h | 69 + system_cmds/at.tproj/perm.c | 125 + system_cmds/at.tproj/perm.h | 28 + system_cmds/at.tproj/privs.h | 110 + system_cmds/atrun.tproj/atrun.8 | 75 + system_cmds/atrun.tproj/atrun.c | 571 + system_cmds/atrun.tproj/com.apple.atrun.plist | 16 + system_cmds/atrun.tproj/gloadavg.c | 72 + system_cmds/atrun.tproj/gloadavg.h | 29 + system_cmds/base.xcconfig | 9 + system_cmds/chkpasswd.tproj/chkpasswd.8 | 59 + system_cmds/chkpasswd.tproj/chkpasswd.pam | 5 + system_cmds/chkpasswd.tproj/file_passwd.c | 276 + system_cmds/chkpasswd.tproj/nis_passwd.c | 210 + system_cmds/chkpasswd.tproj/od_passwd.c | 105 + system_cmds/chkpasswd.tproj/pam_passwd.c | 81 + system_cmds/chkpasswd.tproj/passwd.c | 174 + system_cmds/chkpasswd.tproj/passwd.h | 5 + system_cmds/chkpasswd.tproj/stringops.c | 261 + system_cmds/chkpasswd.tproj/stringops.h | 39 + system_cmds/chpass.tproj/IMPORT_NOTES | 1 + system_cmds/chpass.tproj/chpass.1 | 315 + system_cmds/chpass.tproj/chpass.c | 457 + system_cmds/chpass.tproj/chpass.h | 132 + system_cmds/chpass.tproj/edit.c | 415 + system_cmds/chpass.tproj/field.c | 345 + system_cmds/chpass.tproj/open_directory.c | 205 + system_cmds/chpass.tproj/open_directory.h | 13 + system_cmds/chpass.tproj/pw_copy.c | 127 + system_cmds/chpass.tproj/pw_copy.h | 56 + system_cmds/chpass.tproj/table.c | 117 + system_cmds/chpass.tproj/util.c | 335 + system_cmds/cpuctl.tproj/cpuctl.8 | 67 + system_cmds/cpuctl.tproj/cpuctl.c | 145 + system_cmds/dmesg.tproj/dmesg.8 | 55 + system_cmds/dmesg.tproj/dmesg.c | 101 + .../com.apple.dynamic_pager.plist | 21 + .../dynamic_pager.tproj/dynamic_pager.8 | 32 + .../dynamic_pager.tproj/dynamic_pager.c | 114 + .../dynamic_pager.tproj/entitlements.plist | 8 + .../dynamic_pager.tproj/generate_plist.sh | 16 + system_cmds/fs_usage.tproj/fs_usage.1 | 178 + system_cmds/fs_usage.tproj/fs_usage.c | 3922 +++++++ system_cmds/gcore.tproj/convert.c | 1117 ++ system_cmds/gcore.tproj/convert.h | 24 + system_cmds/gcore.tproj/corefile.c | 852 ++ system_cmds/gcore.tproj/corefile.h | 71 + system_cmds/gcore.tproj/dyld.c | 314 + system_cmds/gcore.tproj/dyld.h | 35 + system_cmds/gcore.tproj/dyld_shared_cache.c | 108 + system_cmds/gcore.tproj/dyld_shared_cache.h | 36 + .../gcore.tproj/gcore-entitlements.plist | 8 + system_cmds/gcore.tproj/gcore-internal.1 | 201 + system_cmds/gcore.tproj/gcore.1 | 105 + system_cmds/gcore.tproj/loader_additions.h | 103 + system_cmds/gcore.tproj/main.c | 863 ++ system_cmds/gcore.tproj/options.h | 62 + system_cmds/gcore.tproj/region.h | 133 + system_cmds/gcore.tproj/sparse.c | 497 + system_cmds/gcore.tproj/sparse.h | 72 + system_cmds/gcore.tproj/threads.c | 81 + system_cmds/gcore.tproj/threads.h | 14 + system_cmds/gcore.tproj/utils.c | 421 + system_cmds/gcore.tproj/utils.h | 42 + system_cmds/gcore.tproj/vanilla.c | 911 ++ system_cmds/gcore.tproj/vanilla.h | 17 + system_cmds/gcore.tproj/vm.c | 493 + system_cmds/gcore.tproj/vm.h | 47 + system_cmds/getconf.tproj/confstr.gperf | 73 + system_cmds/getconf.tproj/fake-gperf.awk | 66 + system_cmds/getconf.tproj/getconf.1 | 212 + system_cmds/getconf.tproj/getconf.c | 189 + system_cmds/getconf.tproj/getconf.h | 43 + system_cmds/getconf.tproj/limits.gperf | 142 + system_cmds/getconf.tproj/pathconf.gperf | 88 + system_cmds/getconf.tproj/progenv.gperf | 70 + system_cmds/getconf.tproj/sysconf.gperf | 187 + system_cmds/getty.tproj/chat.c | 492 + .../com.apple.getty.internal.plist | 33 + system_cmds/getty.tproj/com.apple.getty.plist | 24 + .../com.apple.serialdebugconsole.plist | 39 + system_cmds/getty.tproj/extern.h | 60 + system_cmds/getty.tproj/generate_plist.sh | 16 + system_cmds/getty.tproj/getty.8 | 128 + system_cmds/getty.tproj/gettytab.5 | 546 + system_cmds/getty.tproj/gettytab.h | 177 + system_cmds/getty.tproj/init.c | 156 + system_cmds/getty.tproj/main.c | 858 ++ system_cmds/getty.tproj/pathnames.h | 40 + system_cmds/getty.tproj/subr.c | 710 ++ system_cmds/getty.tproj/ttys.5 | 168 + system_cmds/hostinfo.tproj/hostinfo.8 | 89 + system_cmds/hostinfo.tproj/hostinfo.c | 163 + system_cmds/iosim.tproj/iosim.1 | 100 + system_cmds/iosim.tproj/iosim.c | 673 ++ system_cmds/iostat.tproj/iostat.8 | 302 + system_cmds/iostat.tproj/iostat.c | 998 ++ system_cmds/kpgo.tproj/kpgo.c | 144 + system_cmds/latency.tproj/latency.1 | 106 + system_cmds/latency.tproj/latency.c | 2793 +++++ system_cmds/login.tproj/klogin.c | 207 + system_cmds/login.tproj/login.1 | 186 + system_cmds/login.tproj/login.c | 1509 +++ system_cmds/login.tproj/login.entitlements | 8 + system_cmds/login.tproj/login.h | 37 + system_cmds/login.tproj/login_audit.c | 230 + system_cmds/login.tproj/pam.d/login | 11 + system_cmds/login.tproj/pam.d/login.term | 4 + system_cmds/login.tproj/pathnames.h | 42 + system_cmds/lskq.tproj/common.h | 167 + system_cmds/lskq.tproj/lskq.1 | 236 + system_cmds/lskq.tproj/lskq.c | 963 ++ system_cmds/lsmp.tproj/common.h | 204 + system_cmds/lsmp.tproj/entitlements.plist | 10 + system_cmds/lsmp.tproj/json.h | 119 + system_cmds/lsmp.tproj/lsmp.1 | 61 + system_cmds/lsmp.tproj/lsmp.c | 239 + system_cmds/lsmp.tproj/port_details.c | 746 ++ system_cmds/lsmp.tproj/task_details.c | 507 + system_cmds/ltop.tproj/ltop.1 | 59 + system_cmds/ltop.tproj/ltop.c | 491 + system_cmds/mean.tproj/mean.c | 128 + .../memory_pressure.tproj/memory_pressure.1 | 28 + .../memory_pressure.tproj/memory_pressure.c | 777 ++ system_cmds/mkfile.tproj/mkfile.8 | 47 + system_cmds/mkfile.tproj/mkfile.c | 204 + system_cmds/mslutil/mslutil.1 | 46 + system_cmds/mslutil/mslutil.c | 96 + system_cmds/newgrp.tproj/newgrp.1 | 95 + system_cmds/newgrp.tproj/newgrp.c | 352 + system_cmds/nologin.tproj/nologin.5 | 96 + system_cmds/nologin.tproj/nologin.8 | 57 + system_cmds/nologin.tproj/nologin.c | 51 + system_cmds/nvram.tproj/nvram.8 | 93 + system_cmds/nvram.tproj/nvram.c | 965 ++ system_cmds/pagesize.tproj/pagesize.1 | 58 + system_cmds/pagesize.tproj/pagesize.sh | 40 + system_cmds/passwd.tproj/file_passwd.c | 237 + system_cmds/passwd.tproj/nis_passwd.c | 265 + system_cmds/passwd.tproj/od_passwd.c | 253 + system_cmds/passwd.tproj/pam_passwd.c | 80 + system_cmds/passwd.tproj/passwd.1 | 134 + system_cmds/passwd.tproj/passwd.c | 302 + system_cmds/passwd.tproj/passwd.entitlements | 12 + system_cmds/passwd.tproj/passwd.h | 47 + system_cmds/passwd.tproj/passwd.pam | 5 + .../proc_uuid_policy.tproj/proc_uuid_policy.1 | 54 + .../proc_uuid_policy.tproj/proc_uuid_policy.c | 470 + system_cmds/purge.tproj/purge.8 | 14 + system_cmds/purge.tproj/purge.c | 42 + system_cmds/pwd_mkdb.tproj/pw_scan.c | 160 + system_cmds/pwd_mkdb.tproj/pw_scan.h | 59 + system_cmds/pwd_mkdb.tproj/pwd_mkdb.8 | 177 + system_cmds/pwd_mkdb.tproj/pwd_mkdb.c | 625 ++ system_cmds/reboot.tproj/kextmanager.defs | 6 + system_cmds/reboot.tproj/reboot.8 | 115 + system_cmds/reboot.tproj/reboot.c | 378 + system_cmds/sa.tproj/db.c | 211 + system_cmds/sa.tproj/extern.h | 127 + system_cmds/sa.tproj/main.c | 608 ++ system_cmds/sa.tproj/pathnames.h | 35 + system_cmds/sa.tproj/pdb.c | 469 + system_cmds/sa.tproj/sa.8 | 262 + system_cmds/sa.tproj/usrdb.c | 261 + system_cmds/sc_usage.tproj/sc_usage.1 | 133 + system_cmds/sc_usage.tproj/sc_usage.c | 1787 ++++ system_cmds/shutdown.tproj/kextmanager.defs | 6 + system_cmds/shutdown.tproj/pathnames.h | 29 + system_cmds/shutdown.tproj/shutdown.8 | 176 + system_cmds/shutdown.tproj/shutdown.c | 796 ++ system_cmds/stackshot.tproj/stackshot.c | 248 + system_cmds/sync.tproj/sync.8 | 68 + system_cmds/sync.tproj/sync.c | 52 + system_cmds/sysctl.tproj/sysctl.8 | 390 + system_cmds/sysctl.tproj/sysctl.c | 1009 ++ system_cmds/sysctl.tproj/sysctl.conf.5 | 75 + .../system_cmds.xcodeproj/project.pbxproj | 9146 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 10 + .../xcschemes/All_MacOSX.xcscheme | 71 + .../xcshareddata/xcschemes/All_iOS.xcscheme | 75 + .../taskpolicy-entitlements.plist | 8 + system_cmds/taskpolicy.tproj/taskpolicy.8 | 75 + system_cmds/taskpolicy.tproj/taskpolicy.c | 324 + system_cmds/tests/system_cmds.plist | 214 + system_cmds/trace.tproj/trace.1 | 380 + system_cmds/trace.tproj/trace.c | 2941 ++++++ system_cmds/vifs.tproj/vifs.8 | 46 + system_cmds/vifs.tproj/vifs.c | 120 + system_cmds/vipw.tproj/pw_util.c | 239 + system_cmds/vipw.tproj/pw_util.h | 65 + system_cmds/vipw.tproj/vipw.8 | 92 + system_cmds/vipw.tproj/vipw.c | 147 + .../entitlements.plist | 8 + .../vm_purgeable_stat.1 | 35 + .../vm_purgeable_stat.c | 250 + system_cmds/vm_stat.tproj/vm_stat.1 | 89 + system_cmds/vm_stat.tproj/vm_stat.c | 267 + system_cmds/wait4path/wait4path.1 | 37 + system_cmds/wait4path/wait4path.c | 64 + system_cmds/wait4path/wait4path.version | 5 + .../wordexp-helper.tproj/wordexp-helper.c | 43 + system_cmds/xcconfigs/base.xcconfig | 88 + system_cmds/xcconfigs/development.xcconfig | 29 + system_cmds/xcconfigs/executable.xcconfig | 45 + system_cmds/xcconfigs/wait4path.xcconfig | 16 + system_cmds/xscripts/darwinversion.sh | 228 + system_cmds/zdump.tproj/zdump.8 | 49 + system_cmds/zdump.tproj/zdump.c | 390 + system_cmds/zic.tproj/Arts.htm | 178 + system_cmds/zic.tproj/Makefile.zoneinfo.dist | 90 + system_cmds/zic.tproj/README | 88 + system_cmds/zic.tproj/Theory | 552 + system_cmds/zic.tproj/ZIC_HACK | 6 + system_cmds/zic.tproj/build_zichost.sh | 50 + .../zic.tproj/generate_zone_file_list.sh | 28 + system_cmds/zic.tproj/generate_zoneinfo.sh | 105 + system_cmds/zic.tproj/ialloc.c | 91 + system_cmds/zic.tproj/install_zoneinfo.sh | 47 + system_cmds/zic.tproj/private.h | 272 + system_cmds/zic.tproj/scheck.c | 68 + system_cmds/zic.tproj/tz-art.htm | 278 + system_cmds/zic.tproj/tz-link.htm | 443 + system_cmds/zic.tproj/tzfile.h | 192 + system_cmds/zic.tproj/zic.8 | 468 + system_cmds/zic.tproj/zic.c | 2770 +++++ system_cmds/zlog.tproj/SymbolicationHelper.c | 181 + system_cmds/zlog.tproj/SymbolicationHelper.h | 35 + system_cmds/zlog.tproj/entitlements.plist | 8 + system_cmds/zlog.tproj/zlog.1 | 56 + system_cmds/zlog.tproj/zlog.c | 257 + system_cmds/zprint.tproj/entitlements.plist | 8 + system_cmds/zprint.tproj/test_zprint.lua | 89 + system_cmds/zprint.tproj/zprint.1 | 90 + system_cmds/zprint.tproj/zprint.c | 1092 ++ system_cmds/zprint.tproj/zprint.lua | 281 + text_cmds/.upstream_base_commits | 10 + text_cmds/banner/banner.6 | 82 + text_cmds/banner/banner.c | 1186 +++ text_cmds/cat/cat.1 | 201 + text_cmds/cat/cat.c | 314 + text_cmds/col/README | 48 + text_cmds/col/col.1 | 156 + text_cmds/col/col.c | 552 + text_cmds/colrm/colrm.1 | 91 + text_cmds/colrm/colrm.c | 146 + text_cmds/column/column.1 | 101 + text_cmds/column/column.c | 334 + text_cmds/comm/comm.1 | 124 + text_cmds/comm/comm.c | 220 + text_cmds/csplit/csplit.1 | 157 + text_cmds/csplit/csplit.c | 467 + text_cmds/cut/cut.1 | 166 + text_cmds/cut/cut.c | 468 + text_cmds/ed/POSIX | 101 + text_cmds/ed/README | 24 + text_cmds/ed/buf.c | 284 + text_cmds/ed/cbc.c | 402 + text_cmds/ed/ed.1 | 1004 ++ text_cmds/ed/ed.h | 282 + text_cmds/ed/glbl.c | 218 + text_cmds/ed/io.c | 341 + text_cmds/ed/main.c | 1455 +++ text_cmds/ed/re.c | 132 + text_cmds/ed/red.1 | 1 + text_cmds/ed/sub.c | 256 + text_cmds/ed/test/=.err | 1 + text_cmds/ed/test/README | 32 + text_cmds/ed/test/TODO | 15 + text_cmds/ed/test/a.d | 5 + text_cmds/ed/test/a.r | 8 + text_cmds/ed/test/a.t | 9 + text_cmds/ed/test/a1.err | 3 + text_cmds/ed/test/a2.err | 3 + text_cmds/ed/test/addr.d | 9 + text_cmds/ed/test/addr.r | 2 + text_cmds/ed/test/addr.t | 5 + text_cmds/ed/test/addr1.err | 1 + text_cmds/ed/test/addr2.err | 1 + text_cmds/ed/test/ascii.d.uu | 9 + text_cmds/ed/test/ascii.r.uu | 9 + text_cmds/ed/test/ascii.t | 0 text_cmds/ed/test/bang1.d | 0 text_cmds/ed/test/bang1.err | 1 + text_cmds/ed/test/bang1.r | 1 + text_cmds/ed/test/bang1.t | 5 + text_cmds/ed/test/bang2.err | 1 + text_cmds/ed/test/c.d | 5 + text_cmds/ed/test/c.r | 4 + text_cmds/ed/test/c.t | 12 + text_cmds/ed/test/c1.err | 3 + text_cmds/ed/test/c2.err | 3 + text_cmds/ed/test/ckscripts.sh | 37 + text_cmds/ed/test/d.d | 5 + text_cmds/ed/test/d.err | 1 + text_cmds/ed/test/d.r | 1 + text_cmds/ed/test/d.t | 3 + text_cmds/ed/test/e1.d | 1 + text_cmds/ed/test/e1.err | 1 + text_cmds/ed/test/e1.r | 1 + text_cmds/ed/test/e1.t | 1 + text_cmds/ed/test/e2.d | 1 + text_cmds/ed/test/e2.err | 1 + text_cmds/ed/test/e2.r | 1 + text_cmds/ed/test/e2.t | 1 + text_cmds/ed/test/e3.d | 1 + text_cmds/ed/test/e3.err | 1 + text_cmds/ed/test/e3.r | 1 + text_cmds/ed/test/e3.t | 1 + text_cmds/ed/test/e4.d | 1 + text_cmds/ed/test/e4.r | 1 + text_cmds/ed/test/e4.t | 1 + text_cmds/ed/test/f1.err | 1 + text_cmds/ed/test/f2.err | 1 + text_cmds/ed/test/g1.d | 5 + text_cmds/ed/test/g1.err | 1 + text_cmds/ed/test/g1.r | 15 + text_cmds/ed/test/g1.t | 6 + text_cmds/ed/test/g2.d | 5 + text_cmds/ed/test/g2.err | 1 + text_cmds/ed/test/g2.r | 1 + text_cmds/ed/test/g2.t | 2 + text_cmds/ed/test/g3.d | 5 + text_cmds/ed/test/g3.err | 1 + text_cmds/ed/test/g3.r | 5 + text_cmds/ed/test/g3.t | 4 + text_cmds/ed/test/g4.d | 5 + text_cmds/ed/test/g4.r | 7 + text_cmds/ed/test/g4.t | 13 + text_cmds/ed/test/g5.d | 3 + text_cmds/ed/test/g5.r | 9 + text_cmds/ed/test/g5.t | 2 + text_cmds/ed/test/h.err | 1 + text_cmds/ed/test/i.d | 5 + text_cmds/ed/test/i.r | 8 + text_cmds/ed/test/i.t | 9 + text_cmds/ed/test/i1.err | 3 + text_cmds/ed/test/i2.err | 3 + text_cmds/ed/test/i3.err | 3 + text_cmds/ed/test/j.d | 5 + text_cmds/ed/test/j.r | 4 + text_cmds/ed/test/j.t | 2 + text_cmds/ed/test/k.d | 5 + text_cmds/ed/test/k.r | 5 + text_cmds/ed/test/k.t | 10 + text_cmds/ed/test/k1.err | 1 + text_cmds/ed/test/k2.err | 1 + text_cmds/ed/test/k3.err | 1 + text_cmds/ed/test/k4.err | 6 + text_cmds/ed/test/l.d | 0 text_cmds/ed/test/l.r | 0 text_cmds/ed/test/l.t | 0 text_cmds/ed/test/m.d | 5 + text_cmds/ed/test/m.err | 4 + text_cmds/ed/test/m.r | 5 + text_cmds/ed/test/m.t | 7 + text_cmds/ed/test/mkscripts.sh | 75 + text_cmds/ed/test/n.d | 0 text_cmds/ed/test/n.r | 0 text_cmds/ed/test/n.t | 0 text_cmds/ed/test/nl.err | 1 + text_cmds/ed/test/nl1.d | 5 + text_cmds/ed/test/nl1.r | 8 + text_cmds/ed/test/nl1.t | 8 + text_cmds/ed/test/nl2.d | 5 + text_cmds/ed/test/nl2.r | 6 + text_cmds/ed/test/nl2.t | 4 + text_cmds/ed/test/p.d | 0 text_cmds/ed/test/p.r | 0 text_cmds/ed/test/p.t | 0 text_cmds/ed/test/q.d | 0 text_cmds/ed/test/q.r | 0 text_cmds/ed/test/q.t | 5 + text_cmds/ed/test/q1.err | 1 + text_cmds/ed/test/r1.d | 5 + text_cmds/ed/test/r1.err | 1 + text_cmds/ed/test/r1.r | 7 + text_cmds/ed/test/r1.t | 3 + text_cmds/ed/test/r2.d | 5 + text_cmds/ed/test/r2.err | 1 + text_cmds/ed/test/r2.r | 10 + text_cmds/ed/test/r2.t | 1 + text_cmds/ed/test/r3.d | 1 + text_cmds/ed/test/r3.r | 2 + text_cmds/ed/test/r3.t | 1 + text_cmds/ed/test/s1.d | 5 + text_cmds/ed/test/s1.err | 1 + text_cmds/ed/test/s1.r | 5 + text_cmds/ed/test/s1.t | 6 + text_cmds/ed/test/s10.err | 4 + text_cmds/ed/test/s2.d | 5 + text_cmds/ed/test/s2.err | 4 + text_cmds/ed/test/s2.r | 5 + text_cmds/ed/test/s2.t | 4 + text_cmds/ed/test/s3.d | 0 text_cmds/ed/test/s3.err | 1 + text_cmds/ed/test/s3.r | 1 + text_cmds/ed/test/s3.t | 6 + text_cmds/ed/test/s4.err | 1 + text_cmds/ed/test/s5.err | 1 + text_cmds/ed/test/s6.err | 1 + text_cmds/ed/test/s7.err | 5 + text_cmds/ed/test/s8.err | 4 + text_cmds/ed/test/s9.err | 4 + text_cmds/ed/test/t.d | 5 + text_cmds/ed/test/t.r | 16 + text_cmds/ed/test/t1.d | 5 + text_cmds/ed/test/t1.err | 1 + text_cmds/ed/test/t1.r | 16 + text_cmds/ed/test/t1.t | 3 + text_cmds/ed/test/t2.d | 5 + text_cmds/ed/test/t2.err | 1 + text_cmds/ed/test/t2.r | 6 + text_cmds/ed/test/t2.t | 1 + text_cmds/ed/test/u.d | 5 + text_cmds/ed/test/u.err | 1 + text_cmds/ed/test/u.r | 9 + text_cmds/ed/test/u.t | 31 + text_cmds/ed/test/v.d | 5 + text_cmds/ed/test/v.r | 11 + text_cmds/ed/test/v.t | 6 + text_cmds/ed/test/w.d | 5 + text_cmds/ed/test/w.r | 10 + text_cmds/ed/test/w.t | 2 + text_cmds/ed/test/w1.err | 1 + text_cmds/ed/test/w2.err | 1 + text_cmds/ed/test/w3.err | 1 + text_cmds/ed/test/x.err | 1 + text_cmds/ed/test/z.err | 2 + text_cmds/ed/undo.c | 150 + text_cmds/ee/Changes | 40 + text_cmds/ee/Makefile | 29 + text_cmds/ee/README.ee | 119 + text_cmds/ee/create.make | 292 + text_cmds/ee/ee.1 | 543 + text_cmds/ee/ee.c | 5348 ++++++++++ text_cmds/ee/ee.i18n.guide | 158 + text_cmds/ee/ee.msg | 186 + text_cmds/ee/ee_version.h | 6 + text_cmds/ee/genstr | 32 + text_cmds/ee/make.default | 57 + text_cmds/ee/new_curse.c | 3819 +++++++ text_cmds/ee/new_curse.h | 260 + text_cmds/expand/expand.1 | 118 + text_cmds/expand/expand.c | 200 + .../expand/xcodescripts/link-man-pages.sh | 3 + text_cmds/fmt/fmt.1 | 196 + text_cmds/fmt/fmt.c | 668 ++ text_cmds/fold/fold.1 | 90 + text_cmds/fold/fold.c | 228 + text_cmds/grep/file.c | 347 + text_cmds/grep/grep.1 | 500 + text_cmds/grep/grep.c | 783 ++ text_cmds/grep/grep.h | 161 + text_cmds/grep/queue.c | 107 + text_cmds/grep/util.c | 599 ++ text_cmds/head/head.1 | 69 + text_cmds/head/head.c | 199 + text_cmds/join/join.1 | 235 + text_cmds/join/join.c | 685 ++ text_cmds/lam/lam.1 | 141 + text_cmds/lam/lam.c | 234 + text_cmds/look/look.1 | 124 + text_cmds/look/look.c | 357 + text_cmds/look/pathnames.h | 36 + text_cmds/md5/commoncrypto.c | 108 + text_cmds/md5/commoncrypto.h | 8 + text_cmds/md5/md5.1 | 95 + text_cmds/md5/md5.c | 419 + text_cmds/nl/nl.1 | 253 + text_cmds/nl/nl.c | 439 + text_cmds/paste/paste.1 | 150 + text_cmds/paste/paste.c | 280 + text_cmds/pr/egetopt.c | 218 + text_cmds/pr/extern.h | 61 + text_cmds/pr/pr.1 | 402 + text_cmds/pr/pr.c | 1856 ++++ text_cmds/pr/pr.h | 74 + text_cmds/rev/rev.1 | 49 + text_cmds/rev/rev.c | 118 + text_cmds/rs/rs.1 | 239 + text_cmds/rs/rs.c | 553 + text_cmds/sed/POSIX | 204 + text_cmds/sed/TEST/hanoi.sed | 103 + text_cmds/sed/TEST/math.sed | 439 + text_cmds/sed/TEST/sed.test | 556 + text_cmds/sed/compile.c | 987 ++ text_cmds/sed/defs.h | 151 + text_cmds/sed/extern.h | 60 + text_cmds/sed/main.c | 547 + text_cmds/sed/misc.c | 73 + text_cmds/sed/process.c | 791 ++ text_cmds/sed/sed.1 | 668 ++ text_cmds/sort/bwstring.c | 1142 ++ text_cmds/sort/bwstring.h | 142 + text_cmds/sort/coll.c | 1324 +++ text_cmds/sort/coll.h | 168 + text_cmds/sort/commoncrypto.c | 98 + text_cmds/sort/commoncrypto.h | 8 + text_cmds/sort/file.c | 1684 +++ text_cmds/sort/file.h | 126 + text_cmds/sort/mem.c | 81 + text_cmds/sort/mem.h | 45 + text_cmds/sort/nls/C.msg | 16 + text_cmds/sort/nls/hu_HU.ISO8859-2.msg | 16 + text_cmds/sort/radixsort.c | 746 ++ text_cmds/sort/radixsort.h | 38 + text_cmds/sort/sort.1.in | 639 ++ text_cmds/sort/sort.c | 1325 +++ text_cmds/sort/sort.h | 139 + text_cmds/sort/testsuite/README.txt | 19 + text_cmds/sort/testsuite/bigsample.txt.xz | Bin 0 -> 50904 bytes text_cmds/sort/testsuite/run.sh | 436 + text_cmds/sort/testsuite/sample.txt | Bin 0 -> 1672 bytes text_cmds/sort/vsort.c | 265 + text_cmds/sort/vsort.h | 37 + text_cmds/split/split.1 | 142 + text_cmds/split/split.c | 342 + text_cmds/tail/extern.h | 76 + text_cmds/tail/forward.c | 520 + text_cmds/tail/misc.c | 119 + text_cmds/tail/read.c | 214 + text_cmds/tail/reverse.c | 287 + text_cmds/tail/tail.1 | 188 + text_cmds/tail/tail.c | 349 + text_cmds/tests/Makefile | 6 + text_cmds/tests/sort_vers.c | 23 + text_cmds/text_cmds.plist | 607 ++ text_cmds/text_cmds.xcodeproj/project.pbxproj | 3890 +++++++ .../contents.xcworkspacedata | 7 + text_cmds/tr/cmap.c | 212 + text_cmds/tr/cmap.h | 83 + text_cmds/tr/cset.c | 290 + text_cmds/tr/cset.h | 74 + text_cmds/tr/extern.h | 55 + text_cmds/tr/str.c | 450 + text_cmds/tr/tr.1 | 420 + text_cmds/tr/tr.c | 378 + text_cmds/ul/ul.1 | 104 + text_cmds/ul/ul.c | 569 + text_cmds/unexpand/unexpand.c | 231 + text_cmds/uniq/uniq.1 | 151 + text_cmds/uniq/uniq.c | 367 + text_cmds/unvis/unvis.1 | 59 + text_cmds/unvis/unvis.c | 126 + text_cmds/vis/extern.h | 36 + text_cmds/vis/foldit.c | 82 + text_cmds/vis/vis.1 | 140 + text_cmds/vis/vis.c | 194 + text_cmds/wc/wc.1 | 163 + text_cmds/wc/wc.c | 294 + text_cmds/xcconfigs/base.xcconfig | 59 + text_cmds/xcconfigs/ee.xcconfig | 27 + text_cmds/xcconfigs/grep.xcconfig | 19 + text_cmds/xcconfigs/sort.xcconfig | 15 + text_cmds/xcodescripts/grep_variant_links.sh | 13 + text_cmds/xcodescripts/install-opensource.sh | 9 + text_cmds/xcodescripts/install-sort-man.sh | 3 + 2627 files changed, 497181 insertions(+) create mode 100644 .gitignore create mode 100644 adv_cmds/.upstream_base_commits create mode 100644 adv_cmds/adv_cmds.xcodeproj/project.pbxproj create mode 100644 adv_cmds/adv_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 adv_cmds/cap_mkdb/cap_mkdb.1 create mode 100644 adv_cmds/cap_mkdb/cap_mkdb.c create mode 100644 adv_cmds/colldef/colldef.1 create mode 100644 adv_cmds/colldef/common.h create mode 100644 adv_cmds/colldef/locale/collate.h create mode 100644 adv_cmds/colldef/parse.y create mode 100644 adv_cmds/colldef/scan.l create mode 100644 adv_cmds/finger/extern.h create mode 100644 adv_cmds/finger/finger.1 create mode 100644 adv_cmds/finger/finger.c create mode 100644 adv_cmds/finger/finger.conf.5 create mode 100644 adv_cmds/finger/finger.h create mode 100644 adv_cmds/finger/lprint.c create mode 100644 adv_cmds/finger/net.c create mode 100644 adv_cmds/finger/pathnames.h create mode 100644 adv_cmds/finger/sprint.c create mode 100644 adv_cmds/finger/util.c create mode 100644 adv_cmds/gencat/gencat.1 create mode 100644 adv_cmds/gencat/gencat.c create mode 100644 adv_cmds/gencat/gencat.h create mode 100644 adv_cmds/gencat/genlib.c create mode 100644 adv_cmds/last/last.1 create mode 100644 adv_cmds/last/last.c create mode 100644 adv_cmds/locale/locale.1 create mode 100644 adv_cmds/locale/locale.cc create mode 100644 adv_cmds/localedef/charmap.p-1 create mode 100644 adv_cmds/localedef/charmap.p-2 create mode 100644 adv_cmds/localedef/charmap.test create mode 100644 adv_cmds/localedef/def.a55 create mode 100644 adv_cmds/localedef/def.p-1 create mode 100644 adv_cmds/localedef/def.p-2 create mode 100644 adv_cmds/localedef/localedef.1 create mode 100644 adv_cmds/localedef/localedef.pl create mode 100644 adv_cmds/lsvfs/lsvfs.1 create mode 100644 adv_cmds/lsvfs/lsvfs.c create mode 100644 adv_cmds/mklocale/extern.h create mode 100644 adv_cmds/mklocale/ldef.h create mode 100644 adv_cmds/mklocale/lex.l create mode 100644 adv_cmds/mklocale/mklocale.1 create mode 100644 adv_cmds/mklocale/runefile.h create mode 100644 adv_cmds/mklocale/yacc.y create mode 100644 adv_cmds/pkill/entitlements.plist create mode 100644 adv_cmds/pkill/pkill.1 create mode 100644 adv_cmds/pkill/pkill.c create mode 100644 adv_cmds/ps/entitlements.plist create mode 100644 adv_cmds/ps/extern.h create mode 100644 adv_cmds/ps/fmt.c create mode 100644 adv_cmds/ps/keyword.c create mode 100644 adv_cmds/ps/nlist.c create mode 100644 adv_cmds/ps/print.c create mode 100644 adv_cmds/ps/ps.1 create mode 100644 adv_cmds/ps/ps.c create mode 100644 adv_cmds/ps/ps.h create mode 100644 adv_cmds/ps/tasks.c create mode 100644 adv_cmds/stty/cchar.c create mode 100644 adv_cmds/stty/extern.h create mode 100644 adv_cmds/stty/gfmt.c create mode 100644 adv_cmds/stty/key.c create mode 100644 adv_cmds/stty/modes.c create mode 100644 adv_cmds/stty/print.c create mode 100644 adv_cmds/stty/stty.1 create mode 100644 adv_cmds/stty/stty.c create mode 100644 adv_cmds/stty/stty.h create mode 100644 adv_cmds/stty/util.c create mode 100644 adv_cmds/tabs/tabs.1 create mode 100644 adv_cmds/tabs/tabs.c create mode 100644 adv_cmds/tty/tty.1 create mode 100644 adv_cmds/tty/tty.c create mode 100644 adv_cmds/whois/whois.1 create mode 100644 adv_cmds/whois/whois.c create mode 100644 adv_cmds/xcodescripts/variant_links.sh create mode 100644 basic_cmds/basic_cmds.xcodeproj/project.pbxproj create mode 100644 basic_cmds/mesg/mesg.1 create mode 100644 basic_cmds/mesg/mesg.c create mode 100644 basic_cmds/uudecode/base64.c create mode 100644 basic_cmds/uudecode/uudecode.1 create mode 100644 basic_cmds/uudecode/uudecode.c create mode 100644 basic_cmds/uuencode/base64.c create mode 100644 basic_cmds/uuencode/uuencode.1 create mode 100644 basic_cmds/uuencode/uuencode.5 create mode 100644 basic_cmds/uuencode/uuencode.c create mode 100644 basic_cmds/write/write.1 create mode 100644 basic_cmds/write/write.c create mode 100644 bootstrap_cmds/.gitignore create mode 100644 bootstrap_cmds/APPLE_LICENSE create mode 100644 bootstrap_cmds/mig.xcodeproj/project.pbxproj create mode 100644 bootstrap_cmds/migcom.tproj/alloc.h create mode 100644 bootstrap_cmds/migcom.tproj/error.c create mode 100644 bootstrap_cmds/migcom.tproj/error.h create mode 100644 bootstrap_cmds/migcom.tproj/global.c create mode 100644 bootstrap_cmds/migcom.tproj/global.h create mode 100644 bootstrap_cmds/migcom.tproj/handler.c create mode 100644 bootstrap_cmds/migcom.tproj/header.c create mode 100644 bootstrap_cmds/migcom.tproj/lexxer.h create mode 100644 bootstrap_cmds/migcom.tproj/lexxer.l create mode 100644 bootstrap_cmds/migcom.tproj/mig.1 create mode 100644 bootstrap_cmds/migcom.tproj/mig.c create mode 100644 bootstrap_cmds/migcom.tproj/mig.sh create mode 100644 bootstrap_cmds/migcom.tproj/mig_errors.h create mode 100644 bootstrap_cmds/migcom.tproj/mig_machine.h create mode 100644 bootstrap_cmds/migcom.tproj/migcom.1 create mode 100644 bootstrap_cmds/migcom.tproj/parser.y create mode 100644 bootstrap_cmds/migcom.tproj/routine.c create mode 100644 bootstrap_cmds/migcom.tproj/routine.h create mode 100644 bootstrap_cmds/migcom.tproj/server.c create mode 100644 bootstrap_cmds/migcom.tproj/statement.c create mode 100644 bootstrap_cmds/migcom.tproj/statement.h create mode 100644 bootstrap_cmds/migcom.tproj/strdefs.h create mode 100644 bootstrap_cmds/migcom.tproj/string.c create mode 100644 bootstrap_cmds/migcom.tproj/type.c create mode 100644 bootstrap_cmds/migcom.tproj/type.h create mode 100644 bootstrap_cmds/migcom.tproj/user.c create mode 100644 bootstrap_cmds/migcom.tproj/utils.c create mode 100644 bootstrap_cmds/migcom.tproj/utils.h create mode 100644 bootstrap_cmds/migcom.tproj/write.h create mode 100644 bootstrap_cmds/xcodescripts/install-mig.sh create mode 100644 developer_cmds/asa/asa.1 create mode 100644 developer_cmds/asa/asa.c create mode 100644 developer_cmds/ctags/C.c create mode 100644 developer_cmds/ctags/ctags.1 create mode 100644 developer_cmds/ctags/ctags.c create mode 100644 developer_cmds/ctags/ctags.h create mode 100644 developer_cmds/ctags/fortran.c create mode 100644 developer_cmds/ctags/lisp.c create mode 100644 developer_cmds/ctags/print.c create mode 100644 developer_cmds/ctags/test/ctags.test create mode 100644 developer_cmds/ctags/tree.c create mode 100644 developer_cmds/ctags/yacc.c create mode 100644 developer_cmds/developer_cmds.xcodeproj/project.pbxproj create mode 100644 developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 developer_cmds/indent/args.c create mode 100644 developer_cmds/indent/indent.1 create mode 100644 developer_cmds/indent/indent.c create mode 100644 developer_cmds/indent/indent.h create mode 100644 developer_cmds/indent/indent_codes.h create mode 100644 developer_cmds/indent/indent_globs.h create mode 100644 developer_cmds/indent/io.c create mode 100644 developer_cmds/indent/lexi.c create mode 100644 developer_cmds/indent/parse.c create mode 100644 developer_cmds/indent/pr_comment.c create mode 100644 developer_cmds/lorder/lorder.1 create mode 100644 developer_cmds/lorder/lorder.sh create mode 100644 developer_cmds/rpcgen/rpc_clntout.c create mode 100644 developer_cmds/rpcgen/rpc_cout.c create mode 100644 developer_cmds/rpcgen/rpc_hout.c create mode 100644 developer_cmds/rpcgen/rpc_main.c create mode 100644 developer_cmds/rpcgen/rpc_parse.c create mode 100644 developer_cmds/rpcgen/rpc_parse.h create mode 100644 developer_cmds/rpcgen/rpc_sample.c create mode 100644 developer_cmds/rpcgen/rpc_scan.c create mode 100644 developer_cmds/rpcgen/rpc_scan.h create mode 100644 developer_cmds/rpcgen/rpc_svcout.c create mode 100644 developer_cmds/rpcgen/rpc_tblout.c create mode 100644 developer_cmds/rpcgen/rpc_util.c create mode 100644 developer_cmds/rpcgen/rpc_util.h create mode 100644 developer_cmds/rpcgen/rpcgen.1 create mode 100644 developer_cmds/unifdef/unifdef.1 create mode 100644 developer_cmds/unifdef/unifdef.c create mode 100644 developer_cmds/unifdef/unifdefall.sh create mode 100644 developer_cmds/xcodescripts/install-lorder.sh create mode 100644 developer_cmds/xcodescripts/install-unifdefall.sh create mode 100644 diskdev_cmds/APPLE_LICENSE create mode 100644 diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 create mode 100644 diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme create mode 100644 diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme create mode 100644 diskdev_cmds/disklib/dkcksum.c create mode 100644 diskdev_cmds/disklib/dkdisklabel.c create mode 100644 diskdev_cmds/disklib/dkopen.c create mode 100644 diskdev_cmds/disklib/dkopen.h create mode 100644 diskdev_cmds/disklib/dksecsize.c create mode 100644 diskdev_cmds/disklib/pathnames.h create mode 100644 diskdev_cmds/disklib/preen.c create mode 100644 diskdev_cmds/disklib/vfslist.c create mode 100644 diskdev_cmds/edquota.tproj/edquota.8 create mode 100644 diskdev_cmds/edquota.tproj/edquota.c create mode 100644 diskdev_cmds/edquota.tproj/pathnames.h create mode 100644 diskdev_cmds/edt_fstab/edt_fstab.c create mode 100644 diskdev_cmds/edt_fstab/edt_fstab.h create mode 100644 diskdev_cmds/fdisk.tproj/auto.c create mode 100644 diskdev_cmds/fdisk.tproj/auto.h create mode 100644 diskdev_cmds/fdisk.tproj/cmd.c create mode 100644 diskdev_cmds/fdisk.tproj/cmd.h create mode 100644 diskdev_cmds/fdisk.tproj/disk.c create mode 100644 diskdev_cmds/fdisk.tproj/disk.h create mode 100644 diskdev_cmds/fdisk.tproj/fdisk.8 create mode 100644 diskdev_cmds/fdisk.tproj/fdisk.c create mode 100644 diskdev_cmds/fdisk.tproj/getrawpartition.c create mode 100644 diskdev_cmds/fdisk.tproj/mbr.c create mode 100644 diskdev_cmds/fdisk.tproj/mbr.h create mode 100644 diskdev_cmds/fdisk.tproj/mbrcode.h create mode 100644 diskdev_cmds/fdisk.tproj/misc.c create mode 100644 diskdev_cmds/fdisk.tproj/misc.h create mode 100644 diskdev_cmds/fdisk.tproj/opendev.c create mode 100644 diskdev_cmds/fdisk.tproj/part.c create mode 100644 diskdev_cmds/fdisk.tproj/part.h create mode 100644 diskdev_cmds/fdisk.tproj/user.c create mode 100644 diskdev_cmds/fdisk.tproj/user.h create mode 100644 diskdev_cmds/fdisk.tproj/util.h create mode 100644 diskdev_cmds/fsck.tproj/fsck.8 create mode 100644 diskdev_cmds/fsck.tproj/fsck.c create mode 100644 diskdev_cmds/fsck.tproj/fsck.h create mode 100644 diskdev_cmds/fstyp.tproj/fstyp.8 create mode 100644 diskdev_cmds/fstyp.tproj/fstyp.c create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_msdos.8 create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_msdos.c create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_ntfs.8 create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_ntfs.c create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_udf.8 create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_udf.c create mode 100644 diskdev_cmds/fuser.tproj/fuser.1 create mode 100755 diskdev_cmds/fuser.tproj/fuser.pl create mode 100644 diskdev_cmds/mount.tproj/fstab.5 create mode 100644 diskdev_cmds/mount.tproj/mount.8 create mode 100644 diskdev_cmds/mount.tproj/mount.c create mode 100644 diskdev_cmds/mount.tproj/mount.entitlements create mode 100644 diskdev_cmds/mount.tproj/pathnames.h create mode 100644 diskdev_cmds/mount_devfs.tproj/mount_devfs.c create mode 100644 diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8 create mode 100644 diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c create mode 100644 diskdev_cmds/mount_flags_dir/mount_flags.c create mode 100644 diskdev_cmds/mount_flags_dir/mount_flags.h create mode 100644 diskdev_cmds/quota.tproj/quota.1 create mode 100644 diskdev_cmds/quota.tproj/quota.c create mode 100644 diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c create mode 100644 diskdev_cmds/quotacheck.tproj/quotacheck.8 create mode 100644 diskdev_cmds/quotacheck.tproj/quotacheck.c create mode 100644 diskdev_cmds/quotacheck.tproj/quotacheck.h create mode 100644 diskdev_cmds/quotaon.tproj/quotaon.8 create mode 100644 diskdev_cmds/quotaon.tproj/quotaon.c create mode 100644 diskdev_cmds/repquota.tproj/repquota.8 create mode 100644 diskdev_cmds/repquota.tproj/repquota.c create mode 100644 diskdev_cmds/setclass.tproj/setclass.8 create mode 100644 diskdev_cmds/setclass.tproj/setclass.c create mode 100644 diskdev_cmds/umount.tproj/umount.8 create mode 100644 diskdev_cmds/umount.tproj/umount.c create mode 100644 diskdev_cmds/vndevice.tproj/vndevice.c create mode 100644 diskdev_cmds/vsdbutil.tproj/com.apple.vsdbutil.plist create mode 100644 diskdev_cmds/vsdbutil.tproj/vsdbutil.8 create mode 100644 diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c create mode 100644 doc_cmds/checknr/checknr.1 create mode 100644 doc_cmds/checknr/checknr.c create mode 100644 doc_cmds/colcrt/colcrt.1 create mode 100644 doc_cmds/colcrt/colcrt.c create mode 100644 doc_cmds/doc_cmds.plist create mode 100644 doc_cmds/doc_cmds.txt create mode 100644 doc_cmds/doc_cmds.xcodeproj/project.pbxproj create mode 100644 doc_cmds/intro.1 create mode 100644 doc_cmds/makewhatis/makewhatis.8 create mode 100644 doc_cmds/makewhatis/makewhatis.c create mode 100644 doc_cmds/makewhatis/makewhatis.local.8 create mode 100644 doc_cmds/makewhatis/makewhatis.local.sh create mode 100644 file_cmds/.upstream_base_commits create mode 100644 file_cmds/chflags/chflags.1 create mode 100644 file_cmds/chflags/chflags.c create mode 100644 file_cmds/chmod/chmod.1 create mode 100644 file_cmds/chmod/chmod.c create mode 100644 file_cmds/chmod/chmod_acl.c create mode 100644 file_cmds/chmod/chmod_acl.h create mode 100644 file_cmds/chown/chgrp.1 create mode 100644 file_cmds/chown/chown.8 create mode 100644 file_cmds/chown/chown.c create mode 100644 file_cmds/cksum/cksum.1 create mode 100644 file_cmds/cksum/cksum.c create mode 100644 file_cmds/cksum/crc.c create mode 100644 file_cmds/cksum/crc32.c create mode 100644 file_cmds/cksum/extern.h create mode 100644 file_cmds/cksum/print.c create mode 100644 file_cmds/cksum/sum.1 create mode 100644 file_cmds/cksum/sum1.c create mode 100644 file_cmds/cksum/sum2.c create mode 100644 file_cmds/compress/compress.1 create mode 100644 file_cmds/compress/compress.c create mode 100644 file_cmds/compress/doc/NOTES create mode 100644 file_cmds/compress/doc/README create mode 100644 file_cmds/compress/doc/revision.log create mode 100644 file_cmds/compress/uncompress.1 create mode 100644 file_cmds/compress/zcat.sh create mode 100644 file_cmds/compress/zopen.3 create mode 100644 file_cmds/compress/zopen.c create mode 100644 file_cmds/compress/zopen.h create mode 100644 file_cmds/cp/cp.1 create mode 100644 file_cmds/cp/cp.c create mode 100644 file_cmds/cp/extern.h create mode 100644 file_cmds/cp/utils.c create mode 100644 file_cmds/csh/strpct.c create mode 100644 file_cmds/dd/args.c create mode 100644 file_cmds/dd/conv.c create mode 100644 file_cmds/dd/conv_tab.c create mode 100644 file_cmds/dd/dd.1 create mode 100644 file_cmds/dd/dd.c create mode 100644 file_cmds/dd/dd.entitlements create mode 100644 file_cmds/dd/dd.h create mode 100644 file_cmds/dd/extern.h create mode 100644 file_cmds/dd/install_symlink.sh create mode 100644 file_cmds/dd/misc.c create mode 100644 file_cmds/dd/position.c create mode 100644 file_cmds/df/df.1 create mode 100644 file_cmds/df/df.c create mode 100644 file_cmds/df/vfslist.c create mode 100644 file_cmds/du/du.1 create mode 100644 file_cmds/du/du.c create mode 100644 file_cmds/file_cmds.xcodeproj/project.pbxproj create mode 100644 file_cmds/gzip/futimens.c create mode 100644 file_cmds/gzip/gzexe create mode 100644 file_cmds/gzip/gzexe.1 create mode 100644 file_cmds/gzip/gzip.1 create mode 100644 file_cmds/gzip/gzip.c create mode 100644 file_cmds/gzip/gzip.plist create mode 100644 file_cmds/gzip/gzip.xcconfig create mode 100644 file_cmds/gzip/install_scripts.sh create mode 100644 file_cmds/gzip/unbzip2.c create mode 100644 file_cmds/gzip/unpack.c create mode 100644 file_cmds/gzip/unxz.c create mode 100644 file_cmds/gzip/zdiff create mode 100644 file_cmds/gzip/zdiff.1 create mode 100644 file_cmds/gzip/zforce create mode 100644 file_cmds/gzip/zforce.1 create mode 100644 file_cmds/gzip/zmore create mode 100644 file_cmds/gzip/zmore.1 create mode 100644 file_cmds/gzip/znew create mode 100644 file_cmds/gzip/znew.1 create mode 100644 file_cmds/gzip/zuncompress.c create mode 100644 file_cmds/install/install.1 create mode 100644 file_cmds/install/pathnames.h create mode 100644 file_cmds/install/xinstall.c create mode 100644 file_cmds/ipcrm/ipcrm.1 create mode 100644 file_cmds/ipcrm/ipcrm.c create mode 100644 file_cmds/ipcs/ipcs.1 create mode 100644 file_cmds/ipcs/ipcs.c create mode 100644 file_cmds/ln/link.1 create mode 100644 file_cmds/ln/ln.1 create mode 100644 file_cmds/ln/ln.c create mode 100644 file_cmds/ln/symlink.7 create mode 100644 file_cmds/ls/cmp.c create mode 100644 file_cmds/ls/extern.h create mode 100644 file_cmds/ls/ls.1 create mode 100644 file_cmds/ls/ls.c create mode 100644 file_cmds/ls/ls.h create mode 100644 file_cmds/ls/print.c create mode 100644 file_cmds/ls/util.c create mode 100644 file_cmds/mkdir/mkdir.1 create mode 100644 file_cmds/mkdir/mkdir.c create mode 100644 file_cmds/mkfifo/mkfifo.1 create mode 100644 file_cmds/mkfifo/mkfifo.c create mode 100644 file_cmds/mknod/mknod.8 create mode 100644 file_cmds/mknod/mknod.c create mode 100644 file_cmds/mtree/commoncrypto.c create mode 100644 file_cmds/mtree/commoncrypto.h create mode 100644 file_cmds/mtree/compare.c create mode 100644 file_cmds/mtree/create.c create mode 100644 file_cmds/mtree/excludes.c create mode 100644 file_cmds/mtree/extern.h create mode 100755 file_cmds/mtree/fix_failure_locations.py create mode 100644 file_cmds/mtree/metrics.c create mode 100644 file_cmds/mtree/metrics.h create mode 100644 file_cmds/mtree/misc.c create mode 100644 file_cmds/mtree/mtree.8 create mode 100644 file_cmds/mtree/mtree.c create mode 100644 file_cmds/mtree/mtree.h create mode 100644 file_cmds/mtree/spec.c create mode 100644 file_cmds/mtree/specspec.c create mode 100644 file_cmds/mtree/test/test00.sh create mode 100644 file_cmds/mtree/test/test01.sh create mode 100644 file_cmds/mtree/test/test02.sh create mode 100644 file_cmds/mtree/test/test03.sh create mode 100644 file_cmds/mtree/test/test04.sh create mode 100644 file_cmds/mtree/verify.c create mode 100644 file_cmds/mv/mv.1 create mode 100644 file_cmds/mv/mv.c create mode 100644 file_cmds/mv/pathnames.h create mode 100644 file_cmds/pathchk/pathchk.1 create mode 100644 file_cmds/pathchk/pathchk.c create mode 100644 file_cmds/pax/ar_io.c create mode 100644 file_cmds/pax/ar_subs.c create mode 100644 file_cmds/pax/buf_subs.c create mode 100644 file_cmds/pax/cache.c create mode 100644 file_cmds/pax/cache.h create mode 100644 file_cmds/pax/cpio.1 create mode 100644 file_cmds/pax/cpio.c create mode 100644 file_cmds/pax/cpio.h create mode 100644 file_cmds/pax/extern.h create mode 100644 file_cmds/pax/file_subs.c create mode 100644 file_cmds/pax/ftree.c create mode 100644 file_cmds/pax/ftree.h create mode 100644 file_cmds/pax/gen_subs.c create mode 100644 file_cmds/pax/getoldopt.c create mode 100644 file_cmds/pax/options.c create mode 100644 file_cmds/pax/options.h create mode 100644 file_cmds/pax/pat_rep.c create mode 100644 file_cmds/pax/pat_rep.h create mode 100644 file_cmds/pax/pax.1 create mode 100644 file_cmds/pax/pax.c create mode 100644 file_cmds/pax/pax.h create mode 100644 file_cmds/pax/pax_format.c create mode 100644 file_cmds/pax/pax_format.h create mode 100644 file_cmds/pax/sel_subs.c create mode 100644 file_cmds/pax/sel_subs.h create mode 100644 file_cmds/pax/tables.c create mode 100644 file_cmds/pax/tables.h create mode 100644 file_cmds/pax/tar.c create mode 100644 file_cmds/pax/tar.h create mode 100644 file_cmds/pax/tty_subs.c create mode 100644 file_cmds/rm/rm.1 create mode 100644 file_cmds/rm/rm.c create mode 100644 file_cmds/rm/unlink.1 create mode 100644 file_cmds/rmdir/rmdir.1 create mode 100644 file_cmds/rmdir/rmdir.c create mode 100644 file_cmds/rmt/rmt.8 create mode 100644 file_cmds/rmt/rmt.c create mode 100644 file_cmds/shar/shar.1 create mode 100644 file_cmds/shar/shar.sh create mode 100644 file_cmds/stat/readlink.1 create mode 100644 file_cmds/stat/stat.1 create mode 100644 file_cmds/stat/stat.c create mode 100644 file_cmds/tests/chgrp.sh create mode 100644 file_cmds/tests/file_cmds.plist create mode 100644 file_cmds/touch/touch.1 create mode 100644 file_cmds/touch/touch.c create mode 100644 file_cmds/xcodescripts/hardlink.sh create mode 100644 mail_cmds/Makefile create mode 100644 mail_cmds/biff/Makefile create mode 100644 mail_cmds/biff/biff.1 create mode 100644 mail_cmds/biff/biff.c create mode 100644 mail_cmds/comsat/Makefile create mode 100644 mail_cmds/comsat/comsat.8 create mode 100644 mail_cmds/comsat/comsat.c create mode 100644 mail_cmds/comsat/comsat.plist create mode 100644 mail_cmds/from/Makefile create mode 100644 mail_cmds/from/from.1 create mode 100644 mail_cmds/from/from.c create mode 100644 mail_cmds/mail/Makefile create mode 100644 mail_cmds/mail/USD.doc/Makefile create mode 100644 mail_cmds/mail/USD.doc/mail0.nr create mode 100644 mail_cmds/mail/USD.doc/mail1.nr create mode 100644 mail_cmds/mail/USD.doc/mail2.nr create mode 100644 mail_cmds/mail/USD.doc/mail3.nr create mode 100644 mail_cmds/mail/USD.doc/mail4.nr create mode 100644 mail_cmds/mail/USD.doc/mail5.nr create mode 100644 mail_cmds/mail/USD.doc/mail6.nr create mode 100644 mail_cmds/mail/USD.doc/mail7.nr create mode 100644 mail_cmds/mail/USD.doc/mail8.nr create mode 100644 mail_cmds/mail/USD.doc/mail9.nr create mode 100644 mail_cmds/mail/USD.doc/maila.nr create mode 100644 mail_cmds/mail/aux.c create mode 100644 mail_cmds/mail/cmd1.c create mode 100644 mail_cmds/mail/cmd2.c create mode 100644 mail_cmds/mail/cmd3.c create mode 100644 mail_cmds/mail/cmdtab.c create mode 100644 mail_cmds/mail/collect.c create mode 100644 mail_cmds/mail/def.h create mode 100644 mail_cmds/mail/edit.c create mode 100644 mail_cmds/mail/extern.h create mode 100644 mail_cmds/mail/fio.c create mode 100644 mail_cmds/mail/getname.c create mode 100644 mail_cmds/mail/glob.h create mode 100644 mail_cmds/mail/head.c create mode 100644 mail_cmds/mail/lex.c create mode 100644 mail_cmds/mail/list.c create mode 100644 mail_cmds/mail/mail.1 create mode 100644 mail_cmds/mail/mailx.1 create mode 100644 mail_cmds/mail/main.c create mode 100644 mail_cmds/mail/misc/mail.help create mode 100644 mail_cmds/mail/misc/mail.rc create mode 100644 mail_cmds/mail/misc/mail.tildehelp create mode 100644 mail_cmds/mail/names.c create mode 100644 mail_cmds/mail/pathnames.h create mode 100644 mail_cmds/mail/popen.c create mode 100644 mail_cmds/mail/quit.c create mode 100644 mail_cmds/mail/rcv.h create mode 100644 mail_cmds/mail/send.c create mode 100644 mail_cmds/mail/strings.c create mode 100644 mail_cmds/mail/strlcpy.c create mode 100644 mail_cmds/mail/temp.c create mode 100644 mail_cmds/mail/tty.c create mode 100644 mail_cmds/mail/v7.local.c create mode 100644 mail_cmds/mail/vars.c create mode 100644 mail_cmds/mail/version.c create mode 100644 mail_cmds/msgs/Makefile create mode 100644 mail_cmds/msgs/msgs.1 create mode 100644 mail_cmds/msgs/msgs.c create mode 100644 mail_cmds/msgs/pathnames.h create mode 100644 misc_cmds/calendar/calendar.1 create mode 100644 misc_cmds/calendar/calendar.c create mode 100644 misc_cmds/calendar/calendar.h create mode 100644 misc_cmds/calendar/calendars/calendar.all create mode 100644 misc_cmds/calendar/calendars/calendar.australia create mode 100644 misc_cmds/calendar/calendars/calendar.birthday create mode 100644 misc_cmds/calendar/calendars/calendar.christian create mode 100644 misc_cmds/calendar/calendars/calendar.computer create mode 100644 misc_cmds/calendar/calendars/calendar.croatian create mode 100644 misc_cmds/calendar/calendars/calendar.dutch create mode 100644 misc_cmds/calendar/calendars/calendar.freebsd create mode 100644 misc_cmds/calendar/calendars/calendar.french create mode 100644 misc_cmds/calendar/calendars/calendar.german create mode 100644 misc_cmds/calendar/calendars/calendar.history create mode 100644 misc_cmds/calendar/calendars/calendar.holiday create mode 100644 misc_cmds/calendar/calendars/calendar.hungarian create mode 100644 misc_cmds/calendar/calendars/calendar.judaic create mode 100644 misc_cmds/calendar/calendars/calendar.lotr create mode 100644 misc_cmds/calendar/calendars/calendar.music create mode 100644 misc_cmds/calendar/calendars/calendar.newzealand create mode 100644 misc_cmds/calendar/calendars/calendar.russian create mode 100644 misc_cmds/calendar/calendars/calendar.southafrica create mode 100644 misc_cmds/calendar/calendars/calendar.ukrainian create mode 100644 misc_cmds/calendar/calendars/calendar.usholiday create mode 100644 misc_cmds/calendar/calendars/calendar.world create mode 100644 misc_cmds/calendar/calendars/de_AT.ISO_8859-15/calendar.feiertag create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.all create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.feiertag create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.geschichte create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.kirche create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.literatur create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.musik create mode 100644 misc_cmds/calendar/calendars/de_DE.ISO8859-1/calendar.wissenschaft create mode 100644 misc_cmds/calendar/calendars/fr_FR.ISO8859-1/calendar.all create mode 100644 misc_cmds/calendar/calendars/fr_FR.ISO8859-1/calendar.fetes create mode 100644 misc_cmds/calendar/calendars/fr_FR.ISO8859-1/calendar.french create mode 100644 misc_cmds/calendar/calendars/fr_FR.ISO8859-1/calendar.jferies create mode 100644 misc_cmds/calendar/calendars/fr_FR.ISO8859-1/calendar.proverbes create mode 100644 misc_cmds/calendar/calendars/hr_HR.ISO8859-2/calendar.all create mode 100644 misc_cmds/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici create mode 100644 misc_cmds/calendar/calendars/hu_HU.ISO8859-2/calendar.all create mode 100644 misc_cmds/calendar/calendars/hu_HU.ISO8859-2/calendar.nevnapok create mode 100644 misc_cmds/calendar/calendars/hu_HU.ISO8859-2/calendar.unnepek create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.all create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.common create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.holiday create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.military create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.msk create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.orthodox create mode 100644 misc_cmds/calendar/calendars/ru_RU.KOI8-R/calendar.pagan create mode 100644 misc_cmds/calendar/calendars/uk_UA.KOI8-U/calendar.all create mode 100644 misc_cmds/calendar/calendars/uk_UA.KOI8-U/calendar.holiday create mode 100644 misc_cmds/calendar/calendars/uk_UA.KOI8-U/calendar.misc create mode 100644 misc_cmds/calendar/calendars/uk_UA.KOI8-U/calendar.orthodox create mode 100644 misc_cmds/calendar/day.c create mode 100644 misc_cmds/calendar/io.c create mode 100644 misc_cmds/calendar/ostern.c create mode 100644 misc_cmds/calendar/paskha.c create mode 100644 misc_cmds/calendar/pathnames.h create mode 100644 misc_cmds/leave/leave.1 create mode 100644 misc_cmds/leave/leave.c create mode 100644 misc_cmds/misc_cmds.xcodeproj/project.pbxproj create mode 100644 misc_cmds/ncal/calendar.c create mode 100644 misc_cmds/ncal/calendar.h create mode 100644 misc_cmds/ncal/easter.c create mode 100644 misc_cmds/ncal/ncal.1 create mode 100644 misc_cmds/ncal/ncal.c create mode 100644 misc_cmds/tsort/tsort.1 create mode 100644 misc_cmds/tsort/tsort.c create mode 100644 misc_cmds/units/pathnames.h create mode 100644 misc_cmds/units/units.1 create mode 100644 misc_cmds/units/units.c create mode 100644 misc_cmds/units/units.lib create mode 100644 network_cmds/APPLE_LICENSE create mode 100644 network_cmds/arp.tproj/IMPORT_NOTES create mode 100644 network_cmds/arp.tproj/arp.8 create mode 100644 network_cmds/arp.tproj/arp.c create mode 100644 network_cmds/arp.tproj/arp4.4 create mode 100644 network_cmds/cfilutil/cfilstat.c create mode 100644 network_cmds/cfilutil/cfilutil.1 create mode 100644 network_cmds/cfilutil/cfilutil.c create mode 100644 network_cmds/dnctl/dnctl.8 create mode 100644 network_cmds/dnctl/dnctl.c create mode 100644 network_cmds/ecnprobe/base.h create mode 100644 network_cmds/ecnprobe/capture.c create mode 100644 network_cmds/ecnprobe/capture.h create mode 100644 network_cmds/ecnprobe/ecn.c create mode 100644 network_cmds/ecnprobe/ecn.h create mode 100644 network_cmds/ecnprobe/ecn_probe.c create mode 100644 network_cmds/ecnprobe/ecnprobe.1 create mode 100644 network_cmds/ecnprobe/gmt2local.c create mode 100644 network_cmds/ecnprobe/gmt2local.h create mode 100644 network_cmds/ecnprobe/history.c create mode 100644 network_cmds/ecnprobe/history.h create mode 100644 network_cmds/ecnprobe/inet.c create mode 100644 network_cmds/ecnprobe/inet.h create mode 100644 network_cmds/ecnprobe/session.c create mode 100644 network_cmds/ecnprobe/session.h create mode 100644 network_cmds/ecnprobe/support.c create mode 100644 network_cmds/ecnprobe/support.h create mode 100644 network_cmds/frame_delay/frame_delay.8 create mode 100644 network_cmds/frame_delay/frame_delay.c create mode 100644 network_cmds/ifconfig.tproj/af_inet.c create mode 100644 network_cmds/ifconfig.tproj/af_inet6.c create mode 100644 network_cmds/ifconfig.tproj/af_link.c create mode 100644 network_cmds/ifconfig.tproj/if6lowpan.c create mode 100644 network_cmds/ifconfig.tproj/ifbond.c create mode 100644 network_cmds/ifconfig.tproj/ifbridge.c create mode 100644 network_cmds/ifconfig.tproj/ifclone.c create mode 100644 network_cmds/ifconfig.tproj/ifconfig.8 create mode 100644 network_cmds/ifconfig.tproj/ifconfig.c create mode 100644 network_cmds/ifconfig.tproj/ifconfig.h create mode 100644 network_cmds/ifconfig.tproj/iffake.c create mode 100644 network_cmds/ifconfig.tproj/ifmedia.c create mode 100644 network_cmds/ifconfig.tproj/ifvlan.c create mode 100644 network_cmds/ifconfig.tproj/nexus.c create mode 100644 network_cmds/ip6addrctl.tproj/ip6addrctl.8 create mode 100644 network_cmds/ip6addrctl.tproj/ip6addrctl.c create mode 100644 network_cmds/ip6addrctl.tproj/ip6addrctl.conf create mode 100644 network_cmds/kdumpd.tproj/com.apple.kdumpd.plist create mode 100644 network_cmds/kdumpd.tproj/kdump.h create mode 100755 network_cmds/kdumpd.tproj/kdumpd.8 create mode 100644 network_cmds/kdumpd.tproj/kdumpd.c create mode 100644 network_cmds/kdumpd.tproj/kdumpsubs.c create mode 100644 network_cmds/kdumpd.tproj/kdumpsubs.h create mode 100644 network_cmds/mnc.tproj/LICENCE create mode 100644 network_cmds/mnc.tproj/README create mode 100644 network_cmds/mnc.tproj/mnc.1 create mode 100644 network_cmds/mnc.tproj/mnc.h create mode 100644 network_cmds/mnc.tproj/mnc_error.c create mode 100644 network_cmds/mnc.tproj/mnc_main.c create mode 100644 network_cmds/mnc.tproj/mnc_multicast.c create mode 100644 network_cmds/mnc.tproj/mnc_opts.c create mode 100644 network_cmds/mptcp_client/conn_lib.c create mode 100644 network_cmds/mptcp_client/conn_lib.h create mode 100644 network_cmds/mptcp_client/mptcp_client.1 create mode 100644 network_cmds/mptcp_client/mptcp_client.c create mode 100644 network_cmds/mtest.tproj/COPYING create mode 100644 network_cmds/mtest.tproj/mtest.8 create mode 100644 network_cmds/mtest.tproj/mtest.c create mode 100644 network_cmds/ndp.tproj/gnuc.h create mode 100644 network_cmds/ndp.tproj/ndp.8 create mode 100644 network_cmds/ndp.tproj/ndp.c create mode 100644 network_cmds/netstat.tproj/DERIVED_FILES create mode 100644 network_cmds/netstat.tproj/data.c create mode 100644 network_cmds/netstat.tproj/if.c create mode 100644 network_cmds/netstat.tproj/inet.c create mode 100644 network_cmds/netstat.tproj/inet6.c create mode 100644 network_cmds/netstat.tproj/ipsec.c create mode 100644 network_cmds/netstat.tproj/main.c create mode 100644 network_cmds/netstat.tproj/mbuf.c create mode 100644 network_cmds/netstat.tproj/mcast.c create mode 100644 network_cmds/netstat.tproj/misc.c create mode 100644 network_cmds/netstat.tproj/mptcp.c create mode 100644 network_cmds/netstat.tproj/netstat.1 create mode 100644 network_cmds/netstat.tproj/netstat.h create mode 100644 network_cmds/netstat.tproj/route.c create mode 100644 network_cmds/netstat.tproj/systm.c create mode 100644 network_cmds/netstat.tproj/tp_astring.c create mode 100644 network_cmds/netstat.tproj/unix.c create mode 100644 network_cmds/netstat.tproj/vsock.c create mode 100644 network_cmds/network-client-server-entitlements.plist create mode 100644 network_cmds/network_cmds.plist create mode 100755 network_cmds/network_cmds.xcodeproj/project.pbxproj create mode 100644 network_cmds/ping.tproj/ping.8 create mode 100644 network_cmds/ping.tproj/ping.c create mode 100644 network_cmds/ping6.tproj/md5.c create mode 100644 network_cmds/ping6.tproj/md5.h create mode 100644 network_cmds/ping6.tproj/ping6.8 create mode 100644 network_cmds/ping6.tproj/ping6.c create mode 100644 network_cmds/pktapctl/pktapctl.8 create mode 100644 network_cmds/pktapctl/pktapctl.c create mode 100644 network_cmds/pktmnglr/packet_mangler.c create mode 100644 network_cmds/rarpd.tproj/rarpd.8 create mode 100644 network_cmds/rarpd.tproj/rarpd.c create mode 100755 network_cmds/route.tproj/gen_header.pl create mode 100644 network_cmds/route.tproj/keywords create mode 100644 network_cmds/route.tproj/keywords.h create mode 100644 network_cmds/route.tproj/route.8 create mode 100644 network_cmds/route.tproj/route.c create mode 100644 network_cmds/rtadvd.tproj/advcap.c create mode 100644 network_cmds/rtadvd.tproj/advcap.h create mode 100644 network_cmds/rtadvd.tproj/config.c create mode 100644 network_cmds/rtadvd.tproj/config.h create mode 100644 network_cmds/rtadvd.tproj/dump.c create mode 100644 network_cmds/rtadvd.tproj/dump.h create mode 100644 network_cmds/rtadvd.tproj/if.c create mode 100644 network_cmds/rtadvd.tproj/if.h create mode 100644 network_cmds/rtadvd.tproj/pathnames.h create mode 100644 network_cmds/rtadvd.tproj/rrenum.c create mode 100644 network_cmds/rtadvd.tproj/rrenum.h create mode 100644 network_cmds/rtadvd.tproj/rtadvd.8 create mode 100644 network_cmds/rtadvd.tproj/rtadvd.c create mode 100644 network_cmds/rtadvd.tproj/rtadvd.conf create mode 100644 network_cmds/rtadvd.tproj/rtadvd.conf.5 create mode 100644 network_cmds/rtadvd.tproj/rtadvd.h create mode 100644 network_cmds/rtadvd.tproj/rtadvd_logging.c create mode 100644 network_cmds/rtadvd.tproj/rtadvd_logging.h create mode 100644 network_cmds/rtadvd.tproj/timer.c create mode 100644 network_cmds/rtadvd.tproj/timer.h create mode 100644 network_cmds/rtsol.tproj/dump.c create mode 100644 network_cmds/rtsol.tproj/if.c create mode 100644 network_cmds/rtsol.tproj/probe.c create mode 100644 network_cmds/rtsol.tproj/rtsock.c create mode 100644 network_cmds/rtsol.tproj/rtsol.8 create mode 100644 network_cmds/rtsol.tproj/rtsol.c create mode 100644 network_cmds/rtsol.tproj/rtsold.c create mode 100644 network_cmds/rtsol.tproj/rtsold.h create mode 100644 network_cmds/spray.tproj/spray.8 create mode 100644 network_cmds/spray.tproj/spray.c create mode 100644 network_cmds/spray.tproj/spray.x create mode 100644 network_cmds/traceroute.tproj/README create mode 100644 network_cmds/traceroute.tproj/as.c create mode 100644 network_cmds/traceroute.tproj/as.h create mode 100644 network_cmds/traceroute.tproj/findsaddr-socket.c create mode 100644 network_cmds/traceroute.tproj/findsaddr.h create mode 100644 network_cmds/traceroute.tproj/gnuc.h create mode 100644 network_cmds/traceroute.tproj/ifaddrlist.c create mode 100644 network_cmds/traceroute.tproj/ifaddrlist.h create mode 100644 network_cmds/traceroute.tproj/mean.awk create mode 100644 network_cmds/traceroute.tproj/median.awk create mode 100644 network_cmds/traceroute.tproj/traceroute.8 create mode 100644 network_cmds/traceroute.tproj/traceroute.c create mode 100644 network_cmds/traceroute.tproj/traceroute.h create mode 100644 network_cmds/traceroute.tproj/version.c create mode 100644 network_cmds/traceroute6.tproj/traceroute6.8 create mode 100644 network_cmds/traceroute6.tproj/traceroute6.c create mode 100644 patch_cmds/diffstat/CHANGES create mode 100644 patch_cmds/diffstat/aclocal.m4 create mode 100644 patch_cmds/diffstat/config.guess create mode 100644 patch_cmds/diffstat/config.h create mode 100644 patch_cmds/diffstat/config.sub create mode 100644 patch_cmds/diffstat/config_h.in create mode 100644 patch_cmds/diffstat/configure create mode 100644 patch_cmds/diffstat/configure.in create mode 100644 patch_cmds/diffstat/diffstat.1 create mode 100644 patch_cmds/diffstat/diffstat.c create mode 100644 patch_cmds/diffstat/install-sh create mode 100644 patch_cmds/diffstat/makefile.in create mode 100644 patch_cmds/diffstat/makefile.wnt create mode 100644 patch_cmds/diffstat/package/debian/changelog create mode 100644 patch_cmds/diffstat/package/debian/compat create mode 100644 patch_cmds/diffstat/package/debian/control create mode 100644 patch_cmds/diffstat/package/debian/copyright create mode 100644 patch_cmds/diffstat/package/debian/docs create mode 100644 patch_cmds/diffstat/package/debian/rules create mode 100644 patch_cmds/diffstat/package/debian/source/format create mode 100644 patch_cmds/diffstat/package/debian/watch create mode 100644 patch_cmds/diffstat/package/diffstat.spec create mode 100644 patch_cmds/diffstat/porting/getopt.c create mode 100644 patch_cmds/diffstat/porting/getopt.h create mode 100644 patch_cmds/diffstat/porting/system.h create mode 100644 patch_cmds/diffstat/porting/wildcard.c create mode 100644 patch_cmds/diffstat/testing/case01.pat create mode 100644 patch_cmds/diffstat/testing/case01.ref create mode 100644 patch_cmds/diffstat/testing/case01R.ref create mode 100644 patch_cmds/diffstat/testing/case01Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case01b.ref create mode 100644 patch_cmds/diffstat/testing/case01f0.ref create mode 100644 patch_cmds/diffstat/testing/case01k.ref create mode 100644 patch_cmds/diffstat/testing/case01p1.ref create mode 100644 patch_cmds/diffstat/testing/case01p9.ref create mode 100644 patch_cmds/diffstat/testing/case01r1.ref create mode 100644 patch_cmds/diffstat/testing/case01r2.ref create mode 100644 patch_cmds/diffstat/testing/case01u.ref create mode 100644 patch_cmds/diffstat/testing/case02.pat create mode 100644 patch_cmds/diffstat/testing/case02.ref create mode 100644 patch_cmds/diffstat/testing/case02R.ref create mode 100644 patch_cmds/diffstat/testing/case02Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case02b.ref create mode 100644 patch_cmds/diffstat/testing/case02f0.ref create mode 100644 patch_cmds/diffstat/testing/case02k.ref create mode 100644 patch_cmds/diffstat/testing/case02p1.ref create mode 100644 patch_cmds/diffstat/testing/case02p9.ref create mode 100644 patch_cmds/diffstat/testing/case02r1.ref create mode 100644 patch_cmds/diffstat/testing/case02r2.ref create mode 100644 patch_cmds/diffstat/testing/case02u.ref create mode 100644 patch_cmds/diffstat/testing/case03.pat create mode 100644 patch_cmds/diffstat/testing/case03.ref create mode 100644 patch_cmds/diffstat/testing/case03R.ref create mode 100644 patch_cmds/diffstat/testing/case03Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case03b.ref create mode 100644 patch_cmds/diffstat/testing/case03f0.ref create mode 100644 patch_cmds/diffstat/testing/case03k.ref create mode 100644 patch_cmds/diffstat/testing/case03p1.ref create mode 100644 patch_cmds/diffstat/testing/case03p9.ref create mode 100644 patch_cmds/diffstat/testing/case03r1.ref create mode 100644 patch_cmds/diffstat/testing/case03r2.ref create mode 100644 patch_cmds/diffstat/testing/case03u.ref create mode 100644 patch_cmds/diffstat/testing/case04.pat create mode 100644 patch_cmds/diffstat/testing/case04.ref create mode 100644 patch_cmds/diffstat/testing/case04R.ref create mode 100644 patch_cmds/diffstat/testing/case04Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case04b.ref create mode 100644 patch_cmds/diffstat/testing/case04f0.ref create mode 100644 patch_cmds/diffstat/testing/case04k.ref create mode 100644 patch_cmds/diffstat/testing/case04p1.ref create mode 100644 patch_cmds/diffstat/testing/case04p9.ref create mode 100644 patch_cmds/diffstat/testing/case04r1.ref create mode 100644 patch_cmds/diffstat/testing/case04r2.ref create mode 100644 patch_cmds/diffstat/testing/case04u.ref create mode 100644 patch_cmds/diffstat/testing/case05.pat create mode 100644 patch_cmds/diffstat/testing/case05.ref create mode 100644 patch_cmds/diffstat/testing/case05R.ref create mode 100644 patch_cmds/diffstat/testing/case05Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case05b.ref create mode 100644 patch_cmds/diffstat/testing/case05f0.ref create mode 100644 patch_cmds/diffstat/testing/case05k.ref create mode 100644 patch_cmds/diffstat/testing/case05p1.ref create mode 100644 patch_cmds/diffstat/testing/case05p9.ref create mode 100644 patch_cmds/diffstat/testing/case05r1.ref create mode 100644 patch_cmds/diffstat/testing/case05r2.ref create mode 100644 patch_cmds/diffstat/testing/case05u.ref create mode 100644 patch_cmds/diffstat/testing/case06.pat create mode 100644 patch_cmds/diffstat/testing/case06.ref create mode 100644 patch_cmds/diffstat/testing/case06R.ref create mode 100644 patch_cmds/diffstat/testing/case06Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case06b.ref create mode 100644 patch_cmds/diffstat/testing/case06f0.ref create mode 100644 patch_cmds/diffstat/testing/case06k.ref create mode 100644 patch_cmds/diffstat/testing/case06p1.ref create mode 100644 patch_cmds/diffstat/testing/case06p9.ref create mode 100644 patch_cmds/diffstat/testing/case06r1.ref create mode 100644 patch_cmds/diffstat/testing/case06r2.ref create mode 100644 patch_cmds/diffstat/testing/case06u.ref create mode 100644 patch_cmds/diffstat/testing/case07.pat create mode 100644 patch_cmds/diffstat/testing/case07.ref create mode 100644 patch_cmds/diffstat/testing/case07R.ref create mode 100644 patch_cmds/diffstat/testing/case07Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case07b.ref create mode 100644 patch_cmds/diffstat/testing/case07f0.ref create mode 100644 patch_cmds/diffstat/testing/case07k.ref create mode 100644 patch_cmds/diffstat/testing/case07p1.ref create mode 100644 patch_cmds/diffstat/testing/case07p9.ref create mode 100644 patch_cmds/diffstat/testing/case07r1.ref create mode 100644 patch_cmds/diffstat/testing/case07r2.ref create mode 100644 patch_cmds/diffstat/testing/case07u.ref create mode 100644 patch_cmds/diffstat/testing/case08.pat create mode 100644 patch_cmds/diffstat/testing/case08.ref create mode 100644 patch_cmds/diffstat/testing/case08R.ref create mode 100644 patch_cmds/diffstat/testing/case08Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case08b.ref create mode 100644 patch_cmds/diffstat/testing/case08f0.ref create mode 100644 patch_cmds/diffstat/testing/case08k.ref create mode 100644 patch_cmds/diffstat/testing/case08p1.ref create mode 100644 patch_cmds/diffstat/testing/case08p9.ref create mode 100644 patch_cmds/diffstat/testing/case08r1.ref create mode 100644 patch_cmds/diffstat/testing/case08r2.ref create mode 100644 patch_cmds/diffstat/testing/case08u.ref create mode 100644 patch_cmds/diffstat/testing/case09.pat create mode 100644 patch_cmds/diffstat/testing/case09.ref create mode 100644 patch_cmds/diffstat/testing/case09R.ref create mode 100644 patch_cmds/diffstat/testing/case09Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case09b.ref create mode 100644 patch_cmds/diffstat/testing/case09f0.ref create mode 100644 patch_cmds/diffstat/testing/case09k.ref create mode 100644 patch_cmds/diffstat/testing/case09p1.ref create mode 100644 patch_cmds/diffstat/testing/case09p9.ref create mode 100644 patch_cmds/diffstat/testing/case09r1.ref create mode 100644 patch_cmds/diffstat/testing/case09r2.ref create mode 100644 patch_cmds/diffstat/testing/case09u.ref create mode 100644 patch_cmds/diffstat/testing/case10.pat create mode 100644 patch_cmds/diffstat/testing/case10.ref create mode 100644 patch_cmds/diffstat/testing/case10R.ref create mode 100644 patch_cmds/diffstat/testing/case10Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case10b.ref create mode 100644 patch_cmds/diffstat/testing/case10f0.ref create mode 100644 patch_cmds/diffstat/testing/case10k.ref create mode 100644 patch_cmds/diffstat/testing/case10p1.ref create mode 100644 patch_cmds/diffstat/testing/case10p9.ref create mode 100644 patch_cmds/diffstat/testing/case10r1.ref create mode 100644 patch_cmds/diffstat/testing/case10r2.ref create mode 100644 patch_cmds/diffstat/testing/case10u.ref create mode 100644 patch_cmds/diffstat/testing/case11.pat create mode 100644 patch_cmds/diffstat/testing/case11.ref create mode 100644 patch_cmds/diffstat/testing/case11R.ref create mode 100644 patch_cmds/diffstat/testing/case11Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case11b.ref create mode 100644 patch_cmds/diffstat/testing/case11f0.ref create mode 100644 patch_cmds/diffstat/testing/case11k.ref create mode 100644 patch_cmds/diffstat/testing/case11p1.ref create mode 100644 patch_cmds/diffstat/testing/case11p9.ref create mode 100644 patch_cmds/diffstat/testing/case11r1.ref create mode 100644 patch_cmds/diffstat/testing/case11r2.ref create mode 100644 patch_cmds/diffstat/testing/case11u.ref create mode 100644 patch_cmds/diffstat/testing/case12.pat create mode 100644 patch_cmds/diffstat/testing/case12.ref create mode 100644 patch_cmds/diffstat/testing/case12R.ref create mode 100644 patch_cmds/diffstat/testing/case12Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case12b.ref create mode 100644 patch_cmds/diffstat/testing/case12f0.ref create mode 100644 patch_cmds/diffstat/testing/case12k.ref create mode 100644 patch_cmds/diffstat/testing/case12p1.ref create mode 100644 patch_cmds/diffstat/testing/case12p9.ref create mode 100644 patch_cmds/diffstat/testing/case12r1.ref create mode 100644 patch_cmds/diffstat/testing/case12r2.ref create mode 100644 patch_cmds/diffstat/testing/case12u.ref create mode 100644 patch_cmds/diffstat/testing/case13.pat create mode 100644 patch_cmds/diffstat/testing/case13.ref create mode 100644 patch_cmds/diffstat/testing/case13R.ref create mode 100644 patch_cmds/diffstat/testing/case13Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case13b.ref create mode 100644 patch_cmds/diffstat/testing/case13f0.ref create mode 100644 patch_cmds/diffstat/testing/case13k.ref create mode 100644 patch_cmds/diffstat/testing/case13p1.ref create mode 100644 patch_cmds/diffstat/testing/case13p9.ref create mode 100644 patch_cmds/diffstat/testing/case13r1.ref create mode 100644 patch_cmds/diffstat/testing/case13r2.ref create mode 100644 patch_cmds/diffstat/testing/case13u.ref create mode 100644 patch_cmds/diffstat/testing/case14.pat create mode 100644 patch_cmds/diffstat/testing/case14.ref create mode 100644 patch_cmds/diffstat/testing/case14R.ref create mode 100644 patch_cmds/diffstat/testing/case14Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case14b.ref create mode 100644 patch_cmds/diffstat/testing/case14f0.ref create mode 100644 patch_cmds/diffstat/testing/case14k.ref create mode 100644 patch_cmds/diffstat/testing/case14p1.ref create mode 100644 patch_cmds/diffstat/testing/case14p9.ref create mode 100644 patch_cmds/diffstat/testing/case14r1.ref create mode 100644 patch_cmds/diffstat/testing/case14r2.ref create mode 100644 patch_cmds/diffstat/testing/case14u.ref create mode 100644 patch_cmds/diffstat/testing/case15.pat create mode 100644 patch_cmds/diffstat/testing/case15.ref create mode 100644 patch_cmds/diffstat/testing/case15R.ref create mode 100644 patch_cmds/diffstat/testing/case15Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case15b.ref create mode 100644 patch_cmds/diffstat/testing/case15f0.ref create mode 100644 patch_cmds/diffstat/testing/case15k.ref create mode 100644 patch_cmds/diffstat/testing/case15p1.ref create mode 100644 patch_cmds/diffstat/testing/case15p9.ref create mode 100644 patch_cmds/diffstat/testing/case15r1.ref create mode 100644 patch_cmds/diffstat/testing/case15r2.ref create mode 100644 patch_cmds/diffstat/testing/case15u.ref create mode 100644 patch_cmds/diffstat/testing/case16.pat create mode 100644 patch_cmds/diffstat/testing/case16.ref create mode 100644 patch_cmds/diffstat/testing/case16R.ref create mode 100644 patch_cmds/diffstat/testing/case16Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case16b.ref create mode 100644 patch_cmds/diffstat/testing/case16f0.ref create mode 100644 patch_cmds/diffstat/testing/case16k.ref create mode 100644 patch_cmds/diffstat/testing/case16p1.ref create mode 100644 patch_cmds/diffstat/testing/case16p9.ref create mode 100644 patch_cmds/diffstat/testing/case16r1.ref create mode 100644 patch_cmds/diffstat/testing/case16r2.ref create mode 100644 patch_cmds/diffstat/testing/case16u.ref create mode 100644 patch_cmds/diffstat/testing/case17.pat create mode 100644 patch_cmds/diffstat/testing/case17.ref create mode 100644 patch_cmds/diffstat/testing/case17R.ref create mode 100644 patch_cmds/diffstat/testing/case17Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case17b.ref create mode 100644 patch_cmds/diffstat/testing/case17f0.ref create mode 100644 patch_cmds/diffstat/testing/case17k.ref create mode 100644 patch_cmds/diffstat/testing/case17p1.ref create mode 100644 patch_cmds/diffstat/testing/case17p9.ref create mode 100644 patch_cmds/diffstat/testing/case17r1.ref create mode 100644 patch_cmds/diffstat/testing/case17r2.ref create mode 100644 patch_cmds/diffstat/testing/case17u.ref create mode 100644 patch_cmds/diffstat/testing/case18.pat create mode 100644 patch_cmds/diffstat/testing/case18.ref create mode 100644 patch_cmds/diffstat/testing/case18R.ref create mode 100644 patch_cmds/diffstat/testing/case18Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case18b.ref create mode 100644 patch_cmds/diffstat/testing/case18f0.ref create mode 100644 patch_cmds/diffstat/testing/case18k.ref create mode 100644 patch_cmds/diffstat/testing/case18p1.ref create mode 100644 patch_cmds/diffstat/testing/case18p9.ref create mode 100644 patch_cmds/diffstat/testing/case18r1.ref create mode 100644 patch_cmds/diffstat/testing/case18r2.ref create mode 100644 patch_cmds/diffstat/testing/case18u.ref create mode 100644 patch_cmds/diffstat/testing/case19.pat create mode 100644 patch_cmds/diffstat/testing/case19.ref create mode 100644 patch_cmds/diffstat/testing/case19R.ref create mode 100644 patch_cmds/diffstat/testing/case19Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case19b.ref create mode 100644 patch_cmds/diffstat/testing/case19f0.ref create mode 100644 patch_cmds/diffstat/testing/case19k.ref create mode 100644 patch_cmds/diffstat/testing/case19p1.ref create mode 100644 patch_cmds/diffstat/testing/case19p9.ref create mode 100644 patch_cmds/diffstat/testing/case19r1.ref create mode 100644 patch_cmds/diffstat/testing/case19r2.ref create mode 100644 patch_cmds/diffstat/testing/case19u.ref create mode 100644 patch_cmds/diffstat/testing/case20.pat create mode 100644 patch_cmds/diffstat/testing/case20.ref create mode 100644 patch_cmds/diffstat/testing/case20R.ref create mode 100644 patch_cmds/diffstat/testing/case20Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case20b.ref create mode 100644 patch_cmds/diffstat/testing/case20f0.ref create mode 100644 patch_cmds/diffstat/testing/case20k.ref create mode 100644 patch_cmds/diffstat/testing/case20p1.ref create mode 100644 patch_cmds/diffstat/testing/case20p9.ref create mode 100644 patch_cmds/diffstat/testing/case20r1.ref create mode 100644 patch_cmds/diffstat/testing/case20r2.ref create mode 100644 patch_cmds/diffstat/testing/case20u.ref create mode 100644 patch_cmds/diffstat/testing/case21.pat create mode 100644 patch_cmds/diffstat/testing/case21.ref create mode 100644 patch_cmds/diffstat/testing/case21R.ref create mode 100644 patch_cmds/diffstat/testing/case21Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case21b.ref create mode 100644 patch_cmds/diffstat/testing/case21f0.ref create mode 100644 patch_cmds/diffstat/testing/case21k.ref create mode 100644 patch_cmds/diffstat/testing/case21p1.ref create mode 100644 patch_cmds/diffstat/testing/case21p9.ref create mode 100644 patch_cmds/diffstat/testing/case21r1.ref create mode 100644 patch_cmds/diffstat/testing/case21r2.ref create mode 100644 patch_cmds/diffstat/testing/case21u.ref create mode 100644 patch_cmds/diffstat/testing/case22.pat create mode 100644 patch_cmds/diffstat/testing/case22.ref create mode 100644 patch_cmds/diffstat/testing/case22R.ref create mode 100644 patch_cmds/diffstat/testing/case22Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case22b.ref create mode 100644 patch_cmds/diffstat/testing/case22f0.ref create mode 100644 patch_cmds/diffstat/testing/case22k.ref create mode 100644 patch_cmds/diffstat/testing/case22p1.ref create mode 100644 patch_cmds/diffstat/testing/case22p9.ref create mode 100644 patch_cmds/diffstat/testing/case22r1.ref create mode 100644 patch_cmds/diffstat/testing/case22r2.ref create mode 100644 patch_cmds/diffstat/testing/case22u.ref create mode 100644 patch_cmds/diffstat/testing/case23.pat create mode 100644 patch_cmds/diffstat/testing/case23.ref create mode 100644 patch_cmds/diffstat/testing/case23R.ref create mode 100644 patch_cmds/diffstat/testing/case23Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case23b.ref create mode 100644 patch_cmds/diffstat/testing/case23f0.ref create mode 100644 patch_cmds/diffstat/testing/case23k.ref create mode 100644 patch_cmds/diffstat/testing/case23p1.ref create mode 100644 patch_cmds/diffstat/testing/case23p9.ref create mode 100644 patch_cmds/diffstat/testing/case23r1.ref create mode 100644 patch_cmds/diffstat/testing/case23r2.ref create mode 100644 patch_cmds/diffstat/testing/case23u.ref create mode 100644 patch_cmds/diffstat/testing/case24.pat create mode 100644 patch_cmds/diffstat/testing/case24.ref create mode 100644 patch_cmds/diffstat/testing/case24R.ref create mode 100644 patch_cmds/diffstat/testing/case24Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case24b.ref create mode 100644 patch_cmds/diffstat/testing/case24f0.ref create mode 100644 patch_cmds/diffstat/testing/case24k.ref create mode 100644 patch_cmds/diffstat/testing/case24p1.ref create mode 100644 patch_cmds/diffstat/testing/case24p9.ref create mode 100644 patch_cmds/diffstat/testing/case24r1.ref create mode 100644 patch_cmds/diffstat/testing/case24r2.ref create mode 100644 patch_cmds/diffstat/testing/case24u.ref create mode 100644 patch_cmds/diffstat/testing/case25.pat create mode 100644 patch_cmds/diffstat/testing/case25.ref create mode 100644 patch_cmds/diffstat/testing/case25R.ref create mode 100644 patch_cmds/diffstat/testing/case25Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case25b.ref create mode 100644 patch_cmds/diffstat/testing/case25f0.ref create mode 100644 patch_cmds/diffstat/testing/case25k.ref create mode 100644 patch_cmds/diffstat/testing/case25p1.ref create mode 100644 patch_cmds/diffstat/testing/case25p9.ref create mode 100644 patch_cmds/diffstat/testing/case25r1.ref create mode 100644 patch_cmds/diffstat/testing/case25r2.ref create mode 100644 patch_cmds/diffstat/testing/case25u.ref create mode 100644 patch_cmds/diffstat/testing/case26.pat create mode 100644 patch_cmds/diffstat/testing/case26.ref create mode 100644 patch_cmds/diffstat/testing/case26R.ref create mode 100644 patch_cmds/diffstat/testing/case26Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case26b.ref create mode 100644 patch_cmds/diffstat/testing/case26f0.ref create mode 100644 patch_cmds/diffstat/testing/case26k.ref create mode 100644 patch_cmds/diffstat/testing/case26p1.ref create mode 100644 patch_cmds/diffstat/testing/case26p9.ref create mode 100644 patch_cmds/diffstat/testing/case26r1.ref create mode 100644 patch_cmds/diffstat/testing/case26r2.ref create mode 100644 patch_cmds/diffstat/testing/case26u.ref create mode 100644 patch_cmds/diffstat/testing/case27.pat create mode 100644 patch_cmds/diffstat/testing/case27.ref create mode 100644 patch_cmds/diffstat/testing/case27R.ref create mode 100644 patch_cmds/diffstat/testing/case27Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case27b.ref create mode 100644 patch_cmds/diffstat/testing/case27f0.ref create mode 100644 patch_cmds/diffstat/testing/case27k.ref create mode 100644 patch_cmds/diffstat/testing/case27p1.ref create mode 100644 patch_cmds/diffstat/testing/case27p9.ref create mode 100644 patch_cmds/diffstat/testing/case27r1.ref create mode 100644 patch_cmds/diffstat/testing/case27r2.ref create mode 100644 patch_cmds/diffstat/testing/case27u.ref create mode 100644 patch_cmds/diffstat/testing/case28.pat create mode 100644 patch_cmds/diffstat/testing/case28.ref create mode 100644 patch_cmds/diffstat/testing/case28R.ref create mode 100644 patch_cmds/diffstat/testing/case28Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case28b.ref create mode 100644 patch_cmds/diffstat/testing/case28f0.ref create mode 100644 patch_cmds/diffstat/testing/case28k.ref create mode 100644 patch_cmds/diffstat/testing/case28p1.ref create mode 100644 patch_cmds/diffstat/testing/case28p9.ref create mode 100644 patch_cmds/diffstat/testing/case28r1.ref create mode 100644 patch_cmds/diffstat/testing/case28r2.ref create mode 100644 patch_cmds/diffstat/testing/case28u.ref create mode 100644 patch_cmds/diffstat/testing/case29.pat create mode 100644 patch_cmds/diffstat/testing/case29.ref create mode 100644 patch_cmds/diffstat/testing/case29R.ref create mode 100644 patch_cmds/diffstat/testing/case29Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case29b.ref create mode 100644 patch_cmds/diffstat/testing/case29f0.ref create mode 100644 patch_cmds/diffstat/testing/case29k.ref create mode 100644 patch_cmds/diffstat/testing/case29p1.ref create mode 100644 patch_cmds/diffstat/testing/case29p9.ref create mode 100644 patch_cmds/diffstat/testing/case29r1.ref create mode 100644 patch_cmds/diffstat/testing/case29r2.ref create mode 100644 patch_cmds/diffstat/testing/case29u.ref create mode 100644 patch_cmds/diffstat/testing/case31.pat create mode 100644 patch_cmds/diffstat/testing/case31.ref create mode 100644 patch_cmds/diffstat/testing/case31R.ref create mode 100644 patch_cmds/diffstat/testing/case31Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case31b.ref create mode 100644 patch_cmds/diffstat/testing/case31f0.ref create mode 100644 patch_cmds/diffstat/testing/case31k.ref create mode 100644 patch_cmds/diffstat/testing/case31l.pat create mode 100644 patch_cmds/diffstat/testing/case31l.ref create mode 100644 patch_cmds/diffstat/testing/case31lR.ref create mode 100644 patch_cmds/diffstat/testing/case31lRp0.ref create mode 100644 patch_cmds/diffstat/testing/case31lb.ref create mode 100644 patch_cmds/diffstat/testing/case31lf0.ref create mode 100644 patch_cmds/diffstat/testing/case31lk.ref create mode 100644 patch_cmds/diffstat/testing/case31lp1.ref create mode 100644 patch_cmds/diffstat/testing/case31lp9.ref create mode 100644 patch_cmds/diffstat/testing/case31lr1.ref create mode 100644 patch_cmds/diffstat/testing/case31lr2.ref create mode 100644 patch_cmds/diffstat/testing/case31lu.ref create mode 100644 patch_cmds/diffstat/testing/case31p1.ref create mode 100644 patch_cmds/diffstat/testing/case31p9.ref create mode 100644 patch_cmds/diffstat/testing/case31r1.ref create mode 100644 patch_cmds/diffstat/testing/case31r2.ref create mode 100644 patch_cmds/diffstat/testing/case31u.pat create mode 100644 patch_cmds/diffstat/testing/case31u.ref create mode 100644 patch_cmds/diffstat/testing/case31uR.ref create mode 100644 patch_cmds/diffstat/testing/case31uRp0.ref create mode 100644 patch_cmds/diffstat/testing/case31ub.ref create mode 100644 patch_cmds/diffstat/testing/case31uf0.ref create mode 100644 patch_cmds/diffstat/testing/case31uk.ref create mode 100644 patch_cmds/diffstat/testing/case31up1.ref create mode 100644 patch_cmds/diffstat/testing/case31up9.ref create mode 100644 patch_cmds/diffstat/testing/case31ur1.ref create mode 100644 patch_cmds/diffstat/testing/case31ur2.ref create mode 100644 patch_cmds/diffstat/testing/case31uu.ref create mode 100644 patch_cmds/diffstat/testing/case32.pat create mode 100644 patch_cmds/diffstat/testing/case32.ref create mode 100644 patch_cmds/diffstat/testing/case32R.ref create mode 100644 patch_cmds/diffstat/testing/case32Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case32b.ref create mode 100644 patch_cmds/diffstat/testing/case32f0.ref create mode 100644 patch_cmds/diffstat/testing/case32k.ref create mode 100644 patch_cmds/diffstat/testing/case32p1.ref create mode 100644 patch_cmds/diffstat/testing/case32p9.ref create mode 100644 patch_cmds/diffstat/testing/case32r1.ref create mode 100644 patch_cmds/diffstat/testing/case32r2.ref create mode 100644 patch_cmds/diffstat/testing/case32u.ref create mode 100644 patch_cmds/diffstat/testing/case33.pat create mode 100644 patch_cmds/diffstat/testing/case33.ref create mode 100644 patch_cmds/diffstat/testing/case33R.ref create mode 100644 patch_cmds/diffstat/testing/case33Rp0.ref create mode 100644 patch_cmds/diffstat/testing/case33b.ref create mode 100644 patch_cmds/diffstat/testing/case33f0.ref create mode 100644 patch_cmds/diffstat/testing/case33k.ref create mode 100644 patch_cmds/diffstat/testing/case33p1.ref create mode 100644 patch_cmds/diffstat/testing/case33p9.ref create mode 100644 patch_cmds/diffstat/testing/case33r1.ref create mode 100644 patch_cmds/diffstat/testing/case33r2.ref create mode 100644 patch_cmds/diffstat/testing/case33u.ref create mode 100644 patch_cmds/diffstat/testing/run_atac.sh create mode 100644 patch_cmds/diffstat/testing/run_test.sh create mode 100644 patch_cmds/patch/Makefile create mode 100644 patch_cmds/patch/backupfile.c create mode 100644 patch_cmds/patch/backupfile.h create mode 100644 patch_cmds/patch/common.h create mode 100644 patch_cmds/patch/inp.c create mode 100644 patch_cmds/patch/inp.h create mode 100644 patch_cmds/patch/mkpath.c create mode 100644 patch_cmds/patch/patch.1 create mode 100644 patch_cmds/patch/patch.c create mode 100644 patch_cmds/patch/pathnames.h create mode 100644 patch_cmds/patch/pch.c create mode 100644 patch_cmds/patch/pch.h create mode 100644 patch_cmds/patch/util.c create mode 100644 patch_cmds/patch/util.h create mode 100644 patch_cmds/patch_cmds.plist create mode 100644 patch_cmds/patch_cmds.txt create mode 100644 patch_cmds/patch_cmds.xcodeproj/project.pbxproj create mode 100644 remote_cmds/APPLE_LICENSE create mode 100644 remote_cmds/Makefile create mode 100644 remote_cmds/logger.tproj/Makefile create mode 100644 remote_cmds/logger.tproj/logger.1 create mode 100644 remote_cmds/logger.tproj/logger.c create mode 100644 remote_cmds/talk.tproj/Makefile create mode 100644 remote_cmds/talk.tproj/ctl.c create mode 100644 remote_cmds/talk.tproj/ctl_transact.c create mode 100644 remote_cmds/talk.tproj/display.c create mode 100644 remote_cmds/talk.tproj/get_addrs.c create mode 100644 remote_cmds/talk.tproj/get_iface.c create mode 100644 remote_cmds/talk.tproj/get_names.c create mode 100644 remote_cmds/talk.tproj/init_disp.c create mode 100644 remote_cmds/talk.tproj/invite.c create mode 100644 remote_cmds/talk.tproj/io.c create mode 100644 remote_cmds/talk.tproj/look_up.c create mode 100644 remote_cmds/talk.tproj/msgs.c create mode 100644 remote_cmds/talk.tproj/talk.1 create mode 100644 remote_cmds/talk.tproj/talk.c create mode 100644 remote_cmds/talk.tproj/talk.h create mode 100644 remote_cmds/talk.tproj/talk_ctl.h create mode 100644 remote_cmds/talkd.tproj/Makefile create mode 100644 remote_cmds/talkd.tproj/announce.c create mode 100644 remote_cmds/talkd.tproj/extern.h create mode 100644 remote_cmds/talkd.tproj/ntalk.plist create mode 100644 remote_cmds/talkd.tproj/ntalkd.8 create mode 100644 remote_cmds/talkd.tproj/print.c create mode 100644 remote_cmds/talkd.tproj/process.c create mode 100644 remote_cmds/talkd.tproj/table.c create mode 100644 remote_cmds/talkd.tproj/talkd.c create mode 100644 remote_cmds/telnet.tproj/Makefile create mode 100644 remote_cmds/telnet.tproj/authenc.c create mode 100644 remote_cmds/telnet.tproj/commands.c create mode 100644 remote_cmds/telnet.tproj/defines.h create mode 100644 remote_cmds/telnet.tproj/externs.h create mode 100644 remote_cmds/telnet.tproj/fdset.h create mode 100644 remote_cmds/telnet.tproj/general.h create mode 100644 remote_cmds/telnet.tproj/krb4-proto.h create mode 100644 remote_cmds/telnet.tproj/main.c create mode 100644 remote_cmds/telnet.tproj/misc-proto.h create mode 100644 remote_cmds/telnet.tproj/misc.h create mode 100644 remote_cmds/telnet.tproj/network.c create mode 100644 remote_cmds/telnet.tproj/ring.c create mode 100644 remote_cmds/telnet.tproj/ring.h create mode 100644 remote_cmds/telnet.tproj/sys_bsd.c create mode 100644 remote_cmds/telnet.tproj/telnet.1 create mode 100644 remote_cmds/telnet.tproj/telnet.c create mode 100644 remote_cmds/telnet.tproj/terminal.c create mode 100644 remote_cmds/telnet.tproj/tn3270.c create mode 100644 remote_cmds/telnet.tproj/types.h create mode 100644 remote_cmds/telnet.tproj/utilities.c create mode 100644 remote_cmds/telnetd.tproj/Makefile create mode 100644 remote_cmds/telnetd.tproj/authenc.c create mode 100644 remote_cmds/telnetd.tproj/defs.h create mode 100644 remote_cmds/telnetd.tproj/entitlements.plist create mode 100644 remote_cmds/telnetd.tproj/ext.h create mode 100644 remote_cmds/telnetd.tproj/global.c create mode 100644 remote_cmds/telnetd.tproj/pathnames.h create mode 100644 remote_cmds/telnetd.tproj/slc.c create mode 100644 remote_cmds/telnetd.tproj/state.c create mode 100644 remote_cmds/telnetd.tproj/strlcpy.c create mode 100644 remote_cmds/telnetd.tproj/sys_term.c create mode 100644 remote_cmds/telnetd.tproj/telnet.plist create mode 100644 remote_cmds/telnetd.tproj/telnetd.8 create mode 100644 remote_cmds/telnetd.tproj/telnetd.c create mode 100644 remote_cmds/telnetd.tproj/telnetd.h create mode 100644 remote_cmds/telnetd.tproj/termstat.c create mode 100644 remote_cmds/telnetd.tproj/utility.c create mode 100644 remote_cmds/telnetd.tproj/vasprintf.c create mode 100644 remote_cmds/tftp.tproj/Makefile create mode 100644 remote_cmds/tftp.tproj/extern.h create mode 100644 remote_cmds/tftp.tproj/main.c create mode 100644 remote_cmds/tftp.tproj/tftp.1 create mode 100644 remote_cmds/tftp.tproj/tftp.c create mode 100644 remote_cmds/tftp.tproj/tftpsubs.c create mode 100644 remote_cmds/tftp.tproj/tftpsubs.h create mode 100644 remote_cmds/tftpd.tproj/DERIVED_FILES create mode 100644 remote_cmds/tftpd.tproj/Makefile create mode 100644 remote_cmds/tftpd.tproj/tftp.plist create mode 100644 remote_cmds/tftpd.tproj/tftpd.8 create mode 100644 remote_cmds/tftpd.tproj/tftpd.c create mode 100644 remote_cmds/tftpd.tproj/tftpsubs.c create mode 100644 remote_cmds/tftpd.tproj/tftpsubs.h create mode 100644 remote_cmds/wall.tproj/Makefile create mode 100644 remote_cmds/wall.tproj/ttymsg.c create mode 100644 remote_cmds/wall.tproj/ttymsg.h create mode 100644 remote_cmds/wall.tproj/wall.1 create mode 100644 remote_cmds/wall.tproj/wall.c create mode 100644 shell_cmds/.upstream_base_commits create mode 100644 shell_cmds/alias/alias.1 create mode 100644 shell_cmds/alias/builtin.1 create mode 100644 shell_cmds/alias/generic.sh create mode 100644 shell_cmds/apply/apply.1 create mode 100644 shell_cmds/apply/apply.c create mode 100644 shell_cmds/basename/basename.1 create mode 100644 shell_cmds/basename/basename.c create mode 100644 shell_cmds/basename/dirname.1 create mode 100644 shell_cmds/chroot/chroot.8 create mode 100644 shell_cmds/chroot/chroot.c create mode 100644 shell_cmds/date/date.1 create mode 100644 shell_cmds/date/date.c create mode 100644 shell_cmds/date/date.plist.part create mode 100644 shell_cmds/date/extern.h create mode 100644 shell_cmds/date/netdate.c create mode 100644 shell_cmds/date/vary.c create mode 100644 shell_cmds/date/vary.h create mode 100644 shell_cmds/dirname/dirname.c create mode 100644 shell_cmds/echo/echo.1 create mode 100644 shell_cmds/echo/echo.c create mode 100644 shell_cmds/env/env.1 create mode 100644 shell_cmds/env/env.c create mode 100644 shell_cmds/env/envopts.c create mode 100644 shell_cmds/env/envopts.h create mode 100644 shell_cmds/expr/expr.1 create mode 100644 shell_cmds/expr/expr.y create mode 100644 shell_cmds/false/false.1 create mode 100644 shell_cmds/false/false.c create mode 100644 shell_cmds/false/false.sh create mode 100644 shell_cmds/find/extern.h create mode 100644 shell_cmds/find/find.1 create mode 100644 shell_cmds/find/find.c create mode 100644 shell_cmds/find/find.h create mode 100644 shell_cmds/find/find.plist.part create mode 100644 shell_cmds/find/function.c create mode 100644 shell_cmds/find/getdate.y create mode 100644 shell_cmds/find/ls.c create mode 100644 shell_cmds/find/main.c create mode 100644 shell_cmds/find/misc.c create mode 100644 shell_cmds/find/operator.c create mode 100644 shell_cmds/find/option.c create mode 100644 shell_cmds/getopt/getopt.1 create mode 100644 shell_cmds/getopt/getopt.c create mode 100644 shell_cmds/hexdump/conv.c create mode 100644 shell_cmds/hexdump/display.c create mode 100644 shell_cmds/hexdump/hexdump.1 create mode 100644 shell_cmds/hexdump/hexdump.c create mode 100644 shell_cmds/hexdump/hexdump.h create mode 100644 shell_cmds/hexdump/hexsyntax.c create mode 100644 shell_cmds/hexdump/od.1 create mode 100644 shell_cmds/hexdump/odsyntax.c create mode 100644 shell_cmds/hexdump/parse.c create mode 100644 shell_cmds/hostname/hostname.1 create mode 100644 shell_cmds/hostname/hostname.c create mode 100644 shell_cmds/id/groups.1 create mode 100644 shell_cmds/id/id.1 create mode 100644 shell_cmds/id/id.c create mode 100644 shell_cmds/id/open_directory.c create mode 100644 shell_cmds/id/open_directory.h create mode 100644 shell_cmds/id/whoami.1 create mode 100644 shell_cmds/jot/jot.1 create mode 100644 shell_cmds/jot/jot.c create mode 100644 shell_cmds/kill/kill.1 create mode 100644 shell_cmds/kill/kill.c create mode 100644 shell_cmds/kill/kill.plist.part create mode 100644 shell_cmds/killall/killall.1 create mode 100644 shell_cmds/killall/killall.c create mode 100644 shell_cmds/lastcomm/lastcomm.1 create mode 100644 shell_cmds/lastcomm/lastcomm.c create mode 100644 shell_cmds/lastcomm/pathnames.h create mode 100644 shell_cmds/locate/bigram/locate.bigram.8 create mode 100644 shell_cmds/locate/bigram/locate.bigram.c create mode 100644 shell_cmds/locate/code/locate.code.8 create mode 100644 shell_cmds/locate/code/locate.code.c create mode 100644 shell_cmds/locate/locate/com.apple.locate.plist create mode 100644 shell_cmds/locate/locate/concatdb.sh create mode 100644 shell_cmds/locate/locate/fastfind.c create mode 100644 shell_cmds/locate/locate/locate.1 create mode 100644 shell_cmds/locate/locate/locate.c create mode 100644 shell_cmds/locate/locate/locate.h create mode 100644 shell_cmds/locate/locate/locate.rc create mode 100755 shell_cmds/locate/locate/locate.updatedb.8 create mode 100644 shell_cmds/locate/locate/mklocatedb.sh create mode 100644 shell_cmds/locate/locate/pathnames.h create mode 100644 shell_cmds/locate/locate/updatedb.sh create mode 100644 shell_cmds/locate/locate/util.c create mode 100644 shell_cmds/logname/logname.1 create mode 100644 shell_cmds/logname/logname.c create mode 100644 shell_cmds/mktemp/mktemp.1 create mode 100644 shell_cmds/mktemp/mktemp.c create mode 100644 shell_cmds/mktemp/mktemp.plist.part create mode 100644 shell_cmds/nice/nice.1 create mode 100644 shell_cmds/nice/nice.c create mode 100644 shell_cmds/nohup/nohup.1 create mode 100644 shell_cmds/nohup/nohup.c create mode 100644 shell_cmds/path_helper/path_helper.8 create mode 100644 shell_cmds/path_helper/path_helper.c create mode 100644 shell_cmds/printenv/printenv.1 create mode 100644 shell_cmds/printenv/printenv.c create mode 100644 shell_cmds/printf/printf.1 create mode 100644 shell_cmds/printf/printf.c create mode 100644 shell_cmds/printf/printf.plist.part create mode 100644 shell_cmds/printf/tests/Makefile create mode 100644 shell_cmds/printf/tests/Makefile.depend create mode 100644 shell_cmds/printf/tests/legacy_test.sh create mode 100644 shell_cmds/printf/tests/regress.b.out create mode 100644 shell_cmds/printf/tests/regress.bwidth.out create mode 100644 shell_cmds/printf/tests/regress.d.out create mode 100644 shell_cmds/printf/tests/regress.f.out create mode 100644 shell_cmds/printf/tests/regress.l1.out create mode 100644 shell_cmds/printf/tests/regress.l2.out create mode 100644 shell_cmds/printf/tests/regress.m1.out create mode 100644 shell_cmds/printf/tests/regress.m2.out create mode 100644 shell_cmds/printf/tests/regress.m3.out create mode 100644 shell_cmds/printf/tests/regress.m4.out create mode 100644 shell_cmds/printf/tests/regress.m5.out create mode 100644 shell_cmds/printf/tests/regress.missingpos1.out create mode 100644 shell_cmds/printf/tests/regress.s.out create mode 100644 shell_cmds/printf/tests/regress.sh create mode 100644 shell_cmds/printf/tests/regress.zero.out create mode 100644 shell_cmds/pwd/pwd.1 create mode 100644 shell_cmds/pwd/pwd.c create mode 100644 shell_cmds/renice/renice.8 create mode 100644 shell_cmds/renice/renice.c create mode 100644 shell_cmds/script/script.1 create mode 100644 shell_cmds/script/script.c create mode 100644 shell_cmds/script/script.plist.part create mode 100644 shell_cmds/seq/seq.1 create mode 100644 shell_cmds/seq/seq.c create mode 100644 shell_cmds/sh/Makefile create mode 100644 shell_cmds/sh/Makefile.depend create mode 100644 shell_cmds/sh/TOUR create mode 100644 shell_cmds/sh/alias.c create mode 100644 shell_cmds/sh/alias.h create mode 100644 shell_cmds/sh/arith.h create mode 100644 shell_cmds/sh/arith_yacc.c create mode 100644 shell_cmds/sh/arith_yacc.h create mode 100644 shell_cmds/sh/arith_yylex.c create mode 100644 shell_cmds/sh/bltin/bltin.h create mode 100644 shell_cmds/sh/bltin/echo.c create mode 100644 shell_cmds/sh/builtins.def create mode 100644 shell_cmds/sh/cd.c create mode 100644 shell_cmds/sh/cd.h create mode 100644 shell_cmds/sh/error.c create mode 100644 shell_cmds/sh/error.h create mode 100644 shell_cmds/sh/eval.c create mode 100644 shell_cmds/sh/eval.h create mode 100644 shell_cmds/sh/exec.c create mode 100644 shell_cmds/sh/exec.h create mode 100644 shell_cmds/sh/expand.c create mode 100644 shell_cmds/sh/expand.h create mode 100644 shell_cmds/sh/funcs/cmv create mode 100644 shell_cmds/sh/funcs/dirs create mode 100644 shell_cmds/sh/funcs/login create mode 100644 shell_cmds/sh/funcs/newgrp create mode 100644 shell_cmds/sh/funcs/popd create mode 100644 shell_cmds/sh/funcs/pushd create mode 100644 shell_cmds/sh/funcs/suspend create mode 100644 shell_cmds/sh/histedit.c create mode 100644 shell_cmds/sh/input.c create mode 100644 shell_cmds/sh/input.h create mode 100644 shell_cmds/sh/jobs.c create mode 100644 shell_cmds/sh/jobs.h create mode 100644 shell_cmds/sh/mail.c create mode 100644 shell_cmds/sh/mail.h create mode 100644 shell_cmds/sh/main.c create mode 100644 shell_cmds/sh/main.h create mode 100644 shell_cmds/sh/memalloc.c create mode 100644 shell_cmds/sh/memalloc.h create mode 100644 shell_cmds/sh/miscbltin.c create mode 100755 shell_cmds/sh/mkbuiltins create mode 100644 shell_cmds/sh/mknodes.c create mode 100644 shell_cmds/sh/mksyntax.c create mode 100644 shell_cmds/sh/mktokens create mode 100644 shell_cmds/sh/myhistedit.h create mode 100644 shell_cmds/sh/mystring.c create mode 100644 shell_cmds/sh/mystring.h create mode 100644 shell_cmds/sh/nodes.c.pat create mode 100644 shell_cmds/sh/nodetypes create mode 100644 shell_cmds/sh/options.c create mode 100644 shell_cmds/sh/options.h create mode 100644 shell_cmds/sh/output.c create mode 100644 shell_cmds/sh/output.h create mode 100644 shell_cmds/sh/parser.c create mode 100644 shell_cmds/sh/parser.h create mode 100644 shell_cmds/sh/redir.c create mode 100644 shell_cmds/sh/redir.h create mode 100644 shell_cmds/sh/sh.1 create mode 100644 shell_cmds/sh/sh.plist.part create mode 100644 shell_cmds/sh/shell.h create mode 100644 shell_cmds/sh/show.c create mode 100644 shell_cmds/sh/show.h create mode 100644 shell_cmds/sh/tests/Makefile create mode 100644 shell_cmds/sh/tests/Makefile.depend create mode 100644 shell_cmds/sh/tests/builtins/Makefile create mode 100644 shell_cmds/sh/tests/builtins/Makefile.depend create mode 100644 shell_cmds/sh/tests/builtins/alias.0 create mode 100644 shell_cmds/sh/tests/builtins/alias.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/alias.1 create mode 100644 shell_cmds/sh/tests/builtins/alias.1.stderr create mode 100644 shell_cmds/sh/tests/builtins/alias3.0 create mode 100644 shell_cmds/sh/tests/builtins/alias3.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/alias4.0 create mode 100644 shell_cmds/sh/tests/builtins/break1.0 create mode 100644 shell_cmds/sh/tests/builtins/break2.0 create mode 100644 shell_cmds/sh/tests/builtins/break2.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/break3.0 create mode 100644 shell_cmds/sh/tests/builtins/break4.4 create mode 100644 shell_cmds/sh/tests/builtins/break5.4 create mode 100644 shell_cmds/sh/tests/builtins/break6.0 create mode 100644 shell_cmds/sh/tests/builtins/builtin1.0 create mode 100644 shell_cmds/sh/tests/builtins/case1.0 create mode 100644 shell_cmds/sh/tests/builtins/case10.0 create mode 100644 shell_cmds/sh/tests/builtins/case11.0 create mode 100644 shell_cmds/sh/tests/builtins/case12.0 create mode 100644 shell_cmds/sh/tests/builtins/case13.0 create mode 100644 shell_cmds/sh/tests/builtins/case14.0 create mode 100644 shell_cmds/sh/tests/builtins/case15.0 create mode 100644 shell_cmds/sh/tests/builtins/case16.0 create mode 100644 shell_cmds/sh/tests/builtins/case17.0 create mode 100644 shell_cmds/sh/tests/builtins/case18.0 create mode 100644 shell_cmds/sh/tests/builtins/case19.0 create mode 100644 shell_cmds/sh/tests/builtins/case2.0 create mode 100644 shell_cmds/sh/tests/builtins/case20.0 create mode 100644 shell_cmds/sh/tests/builtins/case21.0 create mode 100644 shell_cmds/sh/tests/builtins/case22.0 create mode 100644 shell_cmds/sh/tests/builtins/case3.0 create mode 100644 shell_cmds/sh/tests/builtins/case4.0 create mode 100644 shell_cmds/sh/tests/builtins/case5.0 create mode 100644 shell_cmds/sh/tests/builtins/case6.0 create mode 100644 shell_cmds/sh/tests/builtins/case7.0 create mode 100644 shell_cmds/sh/tests/builtins/case8.0 create mode 100644 shell_cmds/sh/tests/builtins/case9.0 create mode 100644 shell_cmds/sh/tests/builtins/cd1.0 create mode 100644 shell_cmds/sh/tests/builtins/cd10.0 create mode 100644 shell_cmds/sh/tests/builtins/cd2.0 create mode 100644 shell_cmds/sh/tests/builtins/cd3.0 create mode 100644 shell_cmds/sh/tests/builtins/cd4.0 create mode 100644 shell_cmds/sh/tests/builtins/cd5.0 create mode 100644 shell_cmds/sh/tests/builtins/cd6.0 create mode 100644 shell_cmds/sh/tests/builtins/cd7.0 create mode 100644 shell_cmds/sh/tests/builtins/cd8.0 create mode 100644 shell_cmds/sh/tests/builtins/cd9.0 create mode 100644 shell_cmds/sh/tests/builtins/cd9.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/command1.0 create mode 100644 shell_cmds/sh/tests/builtins/command10.0 create mode 100644 shell_cmds/sh/tests/builtins/command11.0 create mode 100644 shell_cmds/sh/tests/builtins/command12.0 create mode 100644 shell_cmds/sh/tests/builtins/command2.0 create mode 100644 shell_cmds/sh/tests/builtins/command3.0 create mode 100644 shell_cmds/sh/tests/builtins/command3.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/command4.0 create mode 100644 shell_cmds/sh/tests/builtins/command5.0 create mode 100644 shell_cmds/sh/tests/builtins/command5.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/command6.0 create mode 100644 shell_cmds/sh/tests/builtins/command6.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/command7.0 create mode 100644 shell_cmds/sh/tests/builtins/command8.0 create mode 100644 shell_cmds/sh/tests/builtins/command9.0 create mode 100644 shell_cmds/sh/tests/builtins/dot1.0 create mode 100644 shell_cmds/sh/tests/builtins/dot2.0 create mode 100644 shell_cmds/sh/tests/builtins/dot3.0 create mode 100644 shell_cmds/sh/tests/builtins/dot4.0 create mode 100644 shell_cmds/sh/tests/builtins/echo1.0 create mode 100644 shell_cmds/sh/tests/builtins/echo2.0 create mode 100644 shell_cmds/sh/tests/builtins/echo3.0 create mode 100644 shell_cmds/sh/tests/builtins/eval1.0 create mode 100644 shell_cmds/sh/tests/builtins/eval2.0 create mode 100644 shell_cmds/sh/tests/builtins/eval3.0 create mode 100644 shell_cmds/sh/tests/builtins/eval4.0 create mode 100644 shell_cmds/sh/tests/builtins/eval5.0 create mode 100644 shell_cmds/sh/tests/builtins/eval6.0 create mode 100644 shell_cmds/sh/tests/builtins/eval7.0 create mode 100644 shell_cmds/sh/tests/builtins/eval8.7 create mode 100644 shell_cmds/sh/tests/builtins/exec1.0 create mode 100644 shell_cmds/sh/tests/builtins/exec2.0 create mode 100644 shell_cmds/sh/tests/builtins/exit1.0 create mode 100644 shell_cmds/sh/tests/builtins/exit2.8 create mode 100644 shell_cmds/sh/tests/builtins/exit3.0 create mode 100644 shell_cmds/sh/tests/builtins/export1.0 create mode 100644 shell_cmds/sh/tests/builtins/fc1.0 create mode 100644 shell_cmds/sh/tests/builtins/fc2.0 create mode 100644 shell_cmds/sh/tests/builtins/for1.0 create mode 100644 shell_cmds/sh/tests/builtins/for2.0 create mode 100644 shell_cmds/sh/tests/builtins/for3.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts1.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts1.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/getopts10.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts2.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts2.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/getopts3.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts4.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts5.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts6.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts7.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts8.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts8.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/getopts9.0 create mode 100644 shell_cmds/sh/tests/builtins/getopts9.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/hash1.0 create mode 100644 shell_cmds/sh/tests/builtins/hash1.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/hash2.0 create mode 100644 shell_cmds/sh/tests/builtins/hash2.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/hash3.0 create mode 100644 shell_cmds/sh/tests/builtins/hash3.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/hash4.0 create mode 100644 shell_cmds/sh/tests/builtins/jobid1.0 create mode 100644 shell_cmds/sh/tests/builtins/jobid2.0 create mode 100644 shell_cmds/sh/tests/builtins/kill1.0 create mode 100644 shell_cmds/sh/tests/builtins/kill2.0 create mode 100644 shell_cmds/sh/tests/builtins/lineno.0 create mode 100644 shell_cmds/sh/tests/builtins/lineno.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/lineno2.0 create mode 100644 shell_cmds/sh/tests/builtins/lineno3.0 create mode 100644 shell_cmds/sh/tests/builtins/lineno3.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/local1.0 create mode 100644 shell_cmds/sh/tests/builtins/local2.0 create mode 100644 shell_cmds/sh/tests/builtins/local3.0 create mode 100644 shell_cmds/sh/tests/builtins/local4.0 create mode 100644 shell_cmds/sh/tests/builtins/local5.0 create mode 100644 shell_cmds/sh/tests/builtins/local6.0 create mode 100644 shell_cmds/sh/tests/builtins/local7.0 create mode 100644 shell_cmds/sh/tests/builtins/locale1.0 create mode 100644 shell_cmds/sh/tests/builtins/locale2.0 create mode 100644 shell_cmds/sh/tests/builtins/printf1.0 create mode 100644 shell_cmds/sh/tests/builtins/printf2.0 create mode 100644 shell_cmds/sh/tests/builtins/printf3.0 create mode 100644 shell_cmds/sh/tests/builtins/printf4.0 create mode 100644 shell_cmds/sh/tests/builtins/read1.0 create mode 100644 shell_cmds/sh/tests/builtins/read1.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/read2.0 create mode 100644 shell_cmds/sh/tests/builtins/read3.0 create mode 100644 shell_cmds/sh/tests/builtins/read3.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/read4.0 create mode 100644 shell_cmds/sh/tests/builtins/read4.0.stdout create mode 100644 shell_cmds/sh/tests/builtins/read5.0 create mode 100644 shell_cmds/sh/tests/builtins/read6.0 create mode 100644 shell_cmds/sh/tests/builtins/read7.0 create mode 100644 shell_cmds/sh/tests/builtins/read8.0 create mode 100644 shell_cmds/sh/tests/builtins/read9.0 create mode 100644 shell_cmds/sh/tests/builtins/return1.0 create mode 100644 shell_cmds/sh/tests/builtins/return2.1 create mode 100644 shell_cmds/sh/tests/builtins/return3.1 create mode 100644 shell_cmds/sh/tests/builtins/return4.0 create mode 100644 shell_cmds/sh/tests/builtins/return5.0 create mode 100644 shell_cmds/sh/tests/builtins/return6.4 create mode 100644 shell_cmds/sh/tests/builtins/return7.4 create mode 100644 shell_cmds/sh/tests/builtins/return8.0 create mode 100644 shell_cmds/sh/tests/builtins/set1.0 create mode 100644 shell_cmds/sh/tests/builtins/set2.0 create mode 100644 shell_cmds/sh/tests/builtins/set3.0 create mode 100644 shell_cmds/sh/tests/builtins/trap1.0 create mode 100644 shell_cmds/sh/tests/builtins/trap10.0 create mode 100644 shell_cmds/sh/tests/builtins/trap11.0 create mode 100644 shell_cmds/sh/tests/builtins/trap12.0 create mode 100644 shell_cmds/sh/tests/builtins/trap13.0 create mode 100644 shell_cmds/sh/tests/builtins/trap14.0 create mode 100644 shell_cmds/sh/tests/builtins/trap15.0 create mode 100644 shell_cmds/sh/tests/builtins/trap16.0 create mode 100644 shell_cmds/sh/tests/builtins/trap17.0 create mode 100644 shell_cmds/sh/tests/builtins/trap2.0 create mode 100644 shell_cmds/sh/tests/builtins/trap3.0 create mode 100644 shell_cmds/sh/tests/builtins/trap4.0 create mode 100644 shell_cmds/sh/tests/builtins/trap5.0 create mode 100644 shell_cmds/sh/tests/builtins/trap6.0 create mode 100644 shell_cmds/sh/tests/builtins/trap7.0 create mode 100644 shell_cmds/sh/tests/builtins/trap8.0 create mode 100644 shell_cmds/sh/tests/builtins/trap9.0 create mode 100644 shell_cmds/sh/tests/builtins/type1.0 create mode 100644 shell_cmds/sh/tests/builtins/type1.0.stderr create mode 100644 shell_cmds/sh/tests/builtins/type2.0 create mode 100644 shell_cmds/sh/tests/builtins/type3.0 create mode 100644 shell_cmds/sh/tests/builtins/unalias.0 create mode 100644 shell_cmds/sh/tests/builtins/var-assign.0 create mode 100644 shell_cmds/sh/tests/builtins/var-assign2.0 create mode 100644 shell_cmds/sh/tests/builtins/wait1.0 create mode 100644 shell_cmds/sh/tests/builtins/wait10.0 create mode 100644 shell_cmds/sh/tests/builtins/wait2.0 create mode 100644 shell_cmds/sh/tests/builtins/wait3.0 create mode 100644 shell_cmds/sh/tests/builtins/wait4.0 create mode 100644 shell_cmds/sh/tests/builtins/wait5.0 create mode 100644 shell_cmds/sh/tests/builtins/wait6.0 create mode 100644 shell_cmds/sh/tests/builtins/wait7.0 create mode 100644 shell_cmds/sh/tests/builtins/wait8.0 create mode 100644 shell_cmds/sh/tests/builtins/wait9.127 create mode 100644 shell_cmds/sh/tests/errors/Makefile create mode 100644 shell_cmds/sh/tests/errors/Makefile.depend create mode 100644 shell_cmds/sh/tests/errors/assignment-error1.0 create mode 100644 shell_cmds/sh/tests/errors/assignment-error2.0 create mode 100644 shell_cmds/sh/tests/errors/backquote-error1.0 create mode 100644 shell_cmds/sh/tests/errors/backquote-error2.0 create mode 100644 shell_cmds/sh/tests/errors/bad-binary1.126 create mode 100644 shell_cmds/sh/tests/errors/bad-keyword1.0 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp1.0 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp2.2 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp2.2.stderr create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp3.2 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp3.2.stderr create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp4.2 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp4.2.stderr create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp5.2 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp5.2.stderr create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp6.2 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp6.2.stderr create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp7.0 create mode 100644 shell_cmds/sh/tests/errors/bad-parm-exp8.0 create mode 100644 shell_cmds/sh/tests/errors/option-error.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error2.2 create mode 100644 shell_cmds/sh/tests/errors/redirection-error3.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error4.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error5.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error6.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error7.0 create mode 100644 shell_cmds/sh/tests/errors/redirection-error8.0 create mode 100644 shell_cmds/sh/tests/errors/write-error1.0 create mode 100644 shell_cmds/sh/tests/execution/Makefile create mode 100644 shell_cmds/sh/tests/execution/Makefile.depend create mode 100644 shell_cmds/sh/tests/execution/bg1.0 create mode 100644 shell_cmds/sh/tests/execution/bg10.0 create mode 100644 shell_cmds/sh/tests/execution/bg10.0.stdout create mode 100644 shell_cmds/sh/tests/execution/bg2.0 create mode 100644 shell_cmds/sh/tests/execution/bg3.0 create mode 100644 shell_cmds/sh/tests/execution/bg4.0 create mode 100644 shell_cmds/sh/tests/execution/bg5.0 create mode 100644 shell_cmds/sh/tests/execution/bg6.0 create mode 100644 shell_cmds/sh/tests/execution/bg6.0.stdout create mode 100644 shell_cmds/sh/tests/execution/bg7.0 create mode 100644 shell_cmds/sh/tests/execution/bg8.0 create mode 100644 shell_cmds/sh/tests/execution/bg9.0 create mode 100644 shell_cmds/sh/tests/execution/fork1.0 create mode 100644 shell_cmds/sh/tests/execution/fork2.0 create mode 100644 shell_cmds/sh/tests/execution/fork3.0 create mode 100644 shell_cmds/sh/tests/execution/func1.0 create mode 100644 shell_cmds/sh/tests/execution/func2.0 create mode 100644 shell_cmds/sh/tests/execution/func3.0 create mode 100644 shell_cmds/sh/tests/execution/hash1.0 create mode 100644 shell_cmds/sh/tests/execution/int-cmd1.0 create mode 100644 shell_cmds/sh/tests/execution/killed1.0 create mode 100644 shell_cmds/sh/tests/execution/killed2.0 create mode 100644 shell_cmds/sh/tests/execution/not1.0 create mode 100644 shell_cmds/sh/tests/execution/not2.0 create mode 100644 shell_cmds/sh/tests/execution/path1.0 create mode 100644 shell_cmds/sh/tests/execution/redir1.0 create mode 100644 shell_cmds/sh/tests/execution/redir2.0 create mode 100644 shell_cmds/sh/tests/execution/redir3.0 create mode 100644 shell_cmds/sh/tests/execution/redir4.0 create mode 100644 shell_cmds/sh/tests/execution/redir5.0 create mode 100644 shell_cmds/sh/tests/execution/redir6.0 create mode 100644 shell_cmds/sh/tests/execution/redir7.0 create mode 100644 shell_cmds/sh/tests/execution/set-C1.0 create mode 100644 shell_cmds/sh/tests/execution/set-n1.0 create mode 100644 shell_cmds/sh/tests/execution/set-n2.0 create mode 100644 shell_cmds/sh/tests/execution/set-n3.0 create mode 100644 shell_cmds/sh/tests/execution/set-n4.0 create mode 100644 shell_cmds/sh/tests/execution/set-x1.0 create mode 100644 shell_cmds/sh/tests/execution/set-x2.0 create mode 100644 shell_cmds/sh/tests/execution/set-x3.0 create mode 100644 shell_cmds/sh/tests/execution/set-x4.0 create mode 100644 shell_cmds/sh/tests/execution/shellproc1.0 create mode 100644 shell_cmds/sh/tests/execution/subshell1.0 create mode 100644 shell_cmds/sh/tests/execution/subshell1.0.stdout create mode 100644 shell_cmds/sh/tests/execution/subshell2.0 create mode 100644 shell_cmds/sh/tests/execution/subshell3.0 create mode 100644 shell_cmds/sh/tests/execution/subshell4.0 create mode 100644 shell_cmds/sh/tests/execution/unknown1.0 create mode 100644 shell_cmds/sh/tests/execution/var-assign1.0 create mode 100644 shell_cmds/sh/tests/expansion/Makefile create mode 100644 shell_cmds/sh/tests/expansion/Makefile.depend create mode 100644 shell_cmds/sh/tests/expansion/arith1.0 create mode 100644 shell_cmds/sh/tests/expansion/arith10.0 create mode 100644 shell_cmds/sh/tests/expansion/arith11.0 create mode 100644 shell_cmds/sh/tests/expansion/arith12.0 create mode 100644 shell_cmds/sh/tests/expansion/arith13.0 create mode 100644 shell_cmds/sh/tests/expansion/arith14.0 create mode 100644 shell_cmds/sh/tests/expansion/arith2.0 create mode 100644 shell_cmds/sh/tests/expansion/arith3.0 create mode 100644 shell_cmds/sh/tests/expansion/arith4.0 create mode 100644 shell_cmds/sh/tests/expansion/arith5.0 create mode 100644 shell_cmds/sh/tests/expansion/arith6.0 create mode 100644 shell_cmds/sh/tests/expansion/arith7.0 create mode 100644 shell_cmds/sh/tests/expansion/arith8.0 create mode 100644 shell_cmds/sh/tests/expansion/arith9.0 create mode 100644 shell_cmds/sh/tests/expansion/assign1.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst1.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst10.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst11.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst12.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst13.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst14.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst15.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst16.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst17.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst18.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst19.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst2.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst20.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst21.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst22.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst23.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst24.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst25.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst26.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst3.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst4.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst5.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst6.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst7.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst8.0 create mode 100644 shell_cmds/sh/tests/expansion/cmdsubst9.0 create mode 100644 shell_cmds/sh/tests/expansion/export1.0 create mode 100644 shell_cmds/sh/tests/expansion/export2.0 create mode 100644 shell_cmds/sh/tests/expansion/export3.0 create mode 100644 shell_cmds/sh/tests/expansion/heredoc1.0 create mode 100644 shell_cmds/sh/tests/expansion/heredoc2.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs1.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs2.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs3.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs4.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs5.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs6.0 create mode 100644 shell_cmds/sh/tests/expansion/ifs7.0 create mode 100644 shell_cmds/sh/tests/expansion/length1.0 create mode 100644 shell_cmds/sh/tests/expansion/length2.0 create mode 100644 shell_cmds/sh/tests/expansion/length3.0 create mode 100644 shell_cmds/sh/tests/expansion/length4.0 create mode 100644 shell_cmds/sh/tests/expansion/length5.0 create mode 100644 shell_cmds/sh/tests/expansion/length6.0 create mode 100644 shell_cmds/sh/tests/expansion/length7.0 create mode 100644 shell_cmds/sh/tests/expansion/length8.0 create mode 100644 shell_cmds/sh/tests/expansion/local1.0 create mode 100644 shell_cmds/sh/tests/expansion/local2.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname1.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname2.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname3.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname4.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname5.0 create mode 100644 shell_cmds/sh/tests/expansion/pathname6.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus1.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus2.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus3.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus4.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus5.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus6.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus7.0 create mode 100644 shell_cmds/sh/tests/expansion/plus-minus8.0 create mode 100644 shell_cmds/sh/tests/expansion/question1.0 create mode 100644 shell_cmds/sh/tests/expansion/readonly1.0 create mode 100644 shell_cmds/sh/tests/expansion/redir1.0 create mode 100644 shell_cmds/sh/tests/expansion/set-u1.0 create mode 100644 shell_cmds/sh/tests/expansion/set-u2.0 create mode 100644 shell_cmds/sh/tests/expansion/set-u3.0 create mode 100644 shell_cmds/sh/tests/expansion/tilde1.0 create mode 100644 shell_cmds/sh/tests/expansion/tilde2.0 create mode 100644 shell_cmds/sh/tests/expansion/trim1.0 create mode 100644 shell_cmds/sh/tests/expansion/trim2.0 create mode 100644 shell_cmds/sh/tests/expansion/trim3.0 create mode 100644 shell_cmds/sh/tests/expansion/trim4.0 create mode 100644 shell_cmds/sh/tests/expansion/trim5.0 create mode 100644 shell_cmds/sh/tests/expansion/trim6.0 create mode 100644 shell_cmds/sh/tests/expansion/trim7.0 create mode 100644 shell_cmds/sh/tests/expansion/trim8.0 create mode 100644 shell_cmds/sh/tests/expansion/trim9.0 create mode 100755 shell_cmds/sh/tests/functional_test.sh create mode 100644 shell_cmds/sh/tests/invocation/Makefile create mode 100644 shell_cmds/sh/tests/invocation/Makefile.depend create mode 100644 shell_cmds/sh/tests/invocation/sh-ac1.0 create mode 100644 shell_cmds/sh/tests/invocation/sh-c-missing1.0 create mode 100644 shell_cmds/sh/tests/invocation/sh-c1.0 create mode 100644 shell_cmds/sh/tests/invocation/sh-ca1.0 create mode 100644 shell_cmds/sh/tests/invocation/sh-fca1.0 create mode 100644 shell_cmds/sh/tests/parameters/Makefile create mode 100644 shell_cmds/sh/tests/parameters/Makefile.depend create mode 100644 shell_cmds/sh/tests/parameters/env1.0 create mode 100644 shell_cmds/sh/tests/parameters/exitstatus1.0 create mode 100644 shell_cmds/sh/tests/parameters/ifs1.0 create mode 100644 shell_cmds/sh/tests/parameters/mail1.0 create mode 100644 shell_cmds/sh/tests/parameters/mail2.0 create mode 100644 shell_cmds/sh/tests/parameters/optind1.0 create mode 100644 shell_cmds/sh/tests/parameters/optind2.0 create mode 100644 shell_cmds/sh/tests/parameters/positional1.0 create mode 100644 shell_cmds/sh/tests/parameters/positional2.0 create mode 100644 shell_cmds/sh/tests/parameters/positional3.0 create mode 100644 shell_cmds/sh/tests/parameters/positional4.0 create mode 100644 shell_cmds/sh/tests/parameters/positional5.0 create mode 100644 shell_cmds/sh/tests/parameters/positional6.0 create mode 100644 shell_cmds/sh/tests/parameters/positional7.0 create mode 100644 shell_cmds/sh/tests/parameters/positional8.0 create mode 100644 shell_cmds/sh/tests/parameters/positional9.0 create mode 100644 shell_cmds/sh/tests/parameters/pwd1.0 create mode 100644 shell_cmds/sh/tests/parameters/pwd2.0 create mode 100644 shell_cmds/sh/tests/parser/Makefile create mode 100644 shell_cmds/sh/tests/parser/Makefile.depend create mode 100644 shell_cmds/sh/tests/parser/alias1.0 create mode 100644 shell_cmds/sh/tests/parser/alias10.0 create mode 100644 shell_cmds/sh/tests/parser/alias11.0 create mode 100644 shell_cmds/sh/tests/parser/alias12.0 create mode 100644 shell_cmds/sh/tests/parser/alias13.0 create mode 100644 shell_cmds/sh/tests/parser/alias14.0 create mode 100644 shell_cmds/sh/tests/parser/alias15.0 create mode 100644 shell_cmds/sh/tests/parser/alias15.0.stdout create mode 100644 shell_cmds/sh/tests/parser/alias16.0 create mode 100644 shell_cmds/sh/tests/parser/alias17.0 create mode 100644 shell_cmds/sh/tests/parser/alias18.0 create mode 100644 shell_cmds/sh/tests/parser/alias2.0 create mode 100644 shell_cmds/sh/tests/parser/alias3.0 create mode 100644 shell_cmds/sh/tests/parser/alias4.0 create mode 100644 shell_cmds/sh/tests/parser/alias5.0 create mode 100644 shell_cmds/sh/tests/parser/alias6.0 create mode 100644 shell_cmds/sh/tests/parser/alias7.0 create mode 100644 shell_cmds/sh/tests/parser/alias8.0 create mode 100644 shell_cmds/sh/tests/parser/alias9.0 create mode 100644 shell_cmds/sh/tests/parser/and-pipe-not.0 create mode 100644 shell_cmds/sh/tests/parser/case1.0 create mode 100644 shell_cmds/sh/tests/parser/case2.0 create mode 100644 shell_cmds/sh/tests/parser/comment1.0 create mode 100644 shell_cmds/sh/tests/parser/comment2.42 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote1.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote10.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote11.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote12.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote13.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote2.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote3.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote4.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote5.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote6.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote7.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote8.0 create mode 100644 shell_cmds/sh/tests/parser/dollar-quote9.0 create mode 100644 shell_cmds/sh/tests/parser/empty-braces1.0 create mode 100644 shell_cmds/sh/tests/parser/empty-cmd1.0 create mode 100644 shell_cmds/sh/tests/parser/for1.0 create mode 100644 shell_cmds/sh/tests/parser/for2.0 create mode 100644 shell_cmds/sh/tests/parser/func1.0 create mode 100644 shell_cmds/sh/tests/parser/func2.0 create mode 100644 shell_cmds/sh/tests/parser/func3.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc1.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc10.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc11.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc12.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc13.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc2.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc3.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc4.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc5.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc6.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc7.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc8.0 create mode 100644 shell_cmds/sh/tests/parser/heredoc9.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont1.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont10.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont11.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont2.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont3.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont4.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont5.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont6.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont7.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont8.0 create mode 100644 shell_cmds/sh/tests/parser/line-cont9.0 create mode 100644 shell_cmds/sh/tests/parser/no-space1.0 create mode 100644 shell_cmds/sh/tests/parser/no-space2.0 create mode 100644 shell_cmds/sh/tests/parser/nul1.0 create mode 100644 shell_cmds/sh/tests/parser/only-redir1.0 create mode 100644 shell_cmds/sh/tests/parser/only-redir2.0 create mode 100644 shell_cmds/sh/tests/parser/only-redir3.0 create mode 100644 shell_cmds/sh/tests/parser/only-redir4.0 create mode 100644 shell_cmds/sh/tests/parser/pipe-not1.0 create mode 100644 shell_cmds/sh/tests/parser/set-v1.0 create mode 100644 shell_cmds/sh/tests/parser/set-v1.0.stderr create mode 100644 shell_cmds/sh/tests/parser/var-assign1.0 create mode 100644 shell_cmds/sh/tests/set-e/Makefile create mode 100644 shell_cmds/sh/tests/set-e/Makefile.depend create mode 100644 shell_cmds/sh/tests/set-e/and1.0 create mode 100644 shell_cmds/sh/tests/set-e/and2.1 create mode 100644 shell_cmds/sh/tests/set-e/and3.0 create mode 100644 shell_cmds/sh/tests/set-e/and4.0 create mode 100644 shell_cmds/sh/tests/set-e/background1.0 create mode 100644 shell_cmds/sh/tests/set-e/cmd1.0 create mode 100644 shell_cmds/sh/tests/set-e/cmd2.1 create mode 100644 shell_cmds/sh/tests/set-e/elif1.0 create mode 100644 shell_cmds/sh/tests/set-e/elif2.0 create mode 100644 shell_cmds/sh/tests/set-e/eval1.0 create mode 100644 shell_cmds/sh/tests/set-e/eval2.1 create mode 100644 shell_cmds/sh/tests/set-e/for1.0 create mode 100644 shell_cmds/sh/tests/set-e/func1.0 create mode 100644 shell_cmds/sh/tests/set-e/func2.1 create mode 100644 shell_cmds/sh/tests/set-e/if1.0 create mode 100644 shell_cmds/sh/tests/set-e/if2.0 create mode 100644 shell_cmds/sh/tests/set-e/if3.0 create mode 100644 shell_cmds/sh/tests/set-e/not1.0 create mode 100644 shell_cmds/sh/tests/set-e/not2.0 create mode 100644 shell_cmds/sh/tests/set-e/or1.0 create mode 100644 shell_cmds/sh/tests/set-e/or2.0 create mode 100644 shell_cmds/sh/tests/set-e/or3.1 create mode 100644 shell_cmds/sh/tests/set-e/pipe1.1 create mode 100644 shell_cmds/sh/tests/set-e/pipe2.0 create mode 100644 shell_cmds/sh/tests/set-e/return1.0 create mode 100644 shell_cmds/sh/tests/set-e/semi1.1 create mode 100644 shell_cmds/sh/tests/set-e/semi2.1 create mode 100644 shell_cmds/sh/tests/set-e/subshell1.0 create mode 100644 shell_cmds/sh/tests/set-e/subshell2.1 create mode 100644 shell_cmds/sh/tests/set-e/until1.0 create mode 100644 shell_cmds/sh/tests/set-e/until2.0 create mode 100644 shell_cmds/sh/tests/set-e/until3.0 create mode 100644 shell_cmds/sh/tests/set-e/while1.0 create mode 100644 shell_cmds/sh/tests/set-e/while2.0 create mode 100644 shell_cmds/sh/tests/set-e/while3.0 create mode 100644 shell_cmds/sh/trap.c create mode 100644 shell_cmds/sh/trap.h create mode 100644 shell_cmds/sh/var.c create mode 100644 shell_cmds/sh/var.h create mode 100644 shell_cmds/shell_cmds.xcodeproj/project.pbxproj create mode 100644 shell_cmds/shell_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 shell_cmds/shlock/shlock.1 create mode 100644 shell_cmds/shlock/shlock.c create mode 100644 shell_cmds/sleep/sleep.1 create mode 100644 shell_cmds/sleep/sleep.c create mode 100644 shell_cmds/su/su.1 create mode 100644 shell_cmds/su/su.c create mode 100644 shell_cmds/su/su.pam create mode 100644 shell_cmds/su/su_entitlements.plist create mode 100644 shell_cmds/systime/systime.1 create mode 100644 shell_cmds/systime/systime.c create mode 100644 shell_cmds/tee/tee.1 create mode 100644 shell_cmds/tee/tee.c create mode 100644 shell_cmds/test/[.1 create mode 100644 shell_cmds/test/test.1 create mode 100644 shell_cmds/test/test.c create mode 100644 shell_cmds/test/test.plist.part create mode 100644 shell_cmds/test/tests/Makefile create mode 100644 shell_cmds/test/tests/legacy_test.sh create mode 100644 shell_cmds/tests/regress.m4 create mode 100644 shell_cmds/tests/shell_cmds.plist create mode 100755 shell_cmds/time/tests/test_time.sh create mode 100644 shell_cmds/time/time.1 create mode 100644 shell_cmds/time/time.c create mode 100644 shell_cmds/true/true.1 create mode 100644 shell_cmds/true/true.c create mode 100644 shell_cmds/true/true.sh create mode 100644 shell_cmds/uname/uname.1 create mode 100644 shell_cmds/uname/uname.c create mode 100644 shell_cmds/users/users.1 create mode 100644 shell_cmds/users/users.c create mode 100644 shell_cmds/w/extern.h create mode 100644 shell_cmds/w/fmt.c create mode 100644 shell_cmds/w/pr_time.c create mode 100644 shell_cmds/w/proc_compare.c create mode 100644 shell_cmds/w/uptime.1 create mode 100644 shell_cmds/w/w.1 create mode 100644 shell_cmds/w/w.c create mode 100644 shell_cmds/what/what.1 create mode 100644 shell_cmds/what/what.c create mode 100644 shell_cmds/whereis/whereis.1 create mode 100644 shell_cmds/whereis/whereis.c create mode 100644 shell_cmds/which/which.1 create mode 100644 shell_cmds/which/which.c create mode 100644 shell_cmds/who/utmpentry.c create mode 100644 shell_cmds/who/utmpentry.h create mode 100644 shell_cmds/who/who.1 create mode 100644 shell_cmds/who/who.c create mode 100644 shell_cmds/xargs/pathnames.h create mode 100644 shell_cmds/xargs/strnsubst.c create mode 100644 shell_cmds/xargs/xargs.1 create mode 100644 shell_cmds/xargs/xargs.c create mode 100644 shell_cmds/xcconfigs/base.xcconfig create mode 100644 shell_cmds/xcconfigs/sh.xcconfig create mode 100644 shell_cmds/xcodescripts/builtins-manpages.txt create mode 100644 shell_cmds/xcodescripts/builtins.txt create mode 100644 shell_cmds/xcodescripts/install-files.sh create mode 100644 shell_cmds/yes/yes.1 create mode 100644 shell_cmds/yes/yes.c create mode 100644 system_cmds/.upstream_base_commits create mode 100644 system_cmds/APPLE_LICENSE create mode 100644 system_cmds/ac.tproj/ac.8 create mode 100644 system_cmds/ac.tproj/ac.c create mode 100644 system_cmds/accton.tproj/accton.8 create mode 100644 system_cmds/accton.tproj/accton.c create mode 100644 system_cmds/arch.tproj/arch.1 create mode 100644 system_cmds/arch.tproj/arch.c create mode 100644 system_cmds/arch.tproj/machine.1 create mode 100644 system_cmds/at.tproj/LEGAL create mode 100644 system_cmds/at.tproj/at.1 create mode 100644 system_cmds/at.tproj/at.c create mode 100644 system_cmds/at.tproj/at.h create mode 100644 system_cmds/at.tproj/panic.c create mode 100644 system_cmds/at.tproj/panic.h create mode 100644 system_cmds/at.tproj/parsetime.c create mode 100644 system_cmds/at.tproj/parsetime.h create mode 100644 system_cmds/at.tproj/pathnames.h create mode 100644 system_cmds/at.tproj/perm.c create mode 100644 system_cmds/at.tproj/perm.h create mode 100644 system_cmds/at.tproj/privs.h create mode 100644 system_cmds/atrun.tproj/atrun.8 create mode 100644 system_cmds/atrun.tproj/atrun.c create mode 100644 system_cmds/atrun.tproj/com.apple.atrun.plist create mode 100644 system_cmds/atrun.tproj/gloadavg.c create mode 100644 system_cmds/atrun.tproj/gloadavg.h create mode 100644 system_cmds/base.xcconfig create mode 100644 system_cmds/chkpasswd.tproj/chkpasswd.8 create mode 100644 system_cmds/chkpasswd.tproj/chkpasswd.pam create mode 100644 system_cmds/chkpasswd.tproj/file_passwd.c create mode 100644 system_cmds/chkpasswd.tproj/nis_passwd.c create mode 100644 system_cmds/chkpasswd.tproj/od_passwd.c create mode 100644 system_cmds/chkpasswd.tproj/pam_passwd.c create mode 100644 system_cmds/chkpasswd.tproj/passwd.c create mode 100644 system_cmds/chkpasswd.tproj/passwd.h create mode 100644 system_cmds/chkpasswd.tproj/stringops.c create mode 100644 system_cmds/chkpasswd.tproj/stringops.h create mode 100644 system_cmds/chpass.tproj/IMPORT_NOTES create mode 100644 system_cmds/chpass.tproj/chpass.1 create mode 100644 system_cmds/chpass.tproj/chpass.c create mode 100644 system_cmds/chpass.tproj/chpass.h create mode 100644 system_cmds/chpass.tproj/edit.c create mode 100644 system_cmds/chpass.tproj/field.c create mode 100644 system_cmds/chpass.tproj/open_directory.c create mode 100644 system_cmds/chpass.tproj/open_directory.h create mode 100644 system_cmds/chpass.tproj/pw_copy.c create mode 100644 system_cmds/chpass.tproj/pw_copy.h create mode 100644 system_cmds/chpass.tproj/table.c create mode 100644 system_cmds/chpass.tproj/util.c create mode 100644 system_cmds/cpuctl.tproj/cpuctl.8 create mode 100644 system_cmds/cpuctl.tproj/cpuctl.c create mode 100644 system_cmds/dmesg.tproj/dmesg.8 create mode 100644 system_cmds/dmesg.tproj/dmesg.c create mode 100644 system_cmds/dynamic_pager.tproj/com.apple.dynamic_pager.plist create mode 100644 system_cmds/dynamic_pager.tproj/dynamic_pager.8 create mode 100644 system_cmds/dynamic_pager.tproj/dynamic_pager.c create mode 100644 system_cmds/dynamic_pager.tproj/entitlements.plist create mode 100644 system_cmds/dynamic_pager.tproj/generate_plist.sh create mode 100644 system_cmds/fs_usage.tproj/fs_usage.1 create mode 100644 system_cmds/fs_usage.tproj/fs_usage.c create mode 100644 system_cmds/gcore.tproj/convert.c create mode 100644 system_cmds/gcore.tproj/convert.h create mode 100644 system_cmds/gcore.tproj/corefile.c create mode 100644 system_cmds/gcore.tproj/corefile.h create mode 100644 system_cmds/gcore.tproj/dyld.c create mode 100644 system_cmds/gcore.tproj/dyld.h create mode 100644 system_cmds/gcore.tproj/dyld_shared_cache.c create mode 100644 system_cmds/gcore.tproj/dyld_shared_cache.h create mode 100644 system_cmds/gcore.tproj/gcore-entitlements.plist create mode 100644 system_cmds/gcore.tproj/gcore-internal.1 create mode 100644 system_cmds/gcore.tproj/gcore.1 create mode 100644 system_cmds/gcore.tproj/loader_additions.h create mode 100644 system_cmds/gcore.tproj/main.c create mode 100644 system_cmds/gcore.tproj/options.h create mode 100644 system_cmds/gcore.tproj/region.h create mode 100644 system_cmds/gcore.tproj/sparse.c create mode 100644 system_cmds/gcore.tproj/sparse.h create mode 100644 system_cmds/gcore.tproj/threads.c create mode 100644 system_cmds/gcore.tproj/threads.h create mode 100644 system_cmds/gcore.tproj/utils.c create mode 100644 system_cmds/gcore.tproj/utils.h create mode 100644 system_cmds/gcore.tproj/vanilla.c create mode 100644 system_cmds/gcore.tproj/vanilla.h create mode 100644 system_cmds/gcore.tproj/vm.c create mode 100644 system_cmds/gcore.tproj/vm.h create mode 100644 system_cmds/getconf.tproj/confstr.gperf create mode 100644 system_cmds/getconf.tproj/fake-gperf.awk create mode 100644 system_cmds/getconf.tproj/getconf.1 create mode 100644 system_cmds/getconf.tproj/getconf.c create mode 100644 system_cmds/getconf.tproj/getconf.h create mode 100644 system_cmds/getconf.tproj/limits.gperf create mode 100644 system_cmds/getconf.tproj/pathconf.gperf create mode 100644 system_cmds/getconf.tproj/progenv.gperf create mode 100644 system_cmds/getconf.tproj/sysconf.gperf create mode 100644 system_cmds/getty.tproj/chat.c create mode 100644 system_cmds/getty.tproj/com.apple.getty.internal.plist create mode 100644 system_cmds/getty.tproj/com.apple.getty.plist create mode 100644 system_cmds/getty.tproj/com.apple.serialdebugconsole.plist create mode 100644 system_cmds/getty.tproj/extern.h create mode 100644 system_cmds/getty.tproj/generate_plist.sh create mode 100644 system_cmds/getty.tproj/getty.8 create mode 100644 system_cmds/getty.tproj/gettytab.5 create mode 100644 system_cmds/getty.tproj/gettytab.h create mode 100644 system_cmds/getty.tproj/init.c create mode 100644 system_cmds/getty.tproj/main.c create mode 100644 system_cmds/getty.tproj/pathnames.h create mode 100644 system_cmds/getty.tproj/subr.c create mode 100644 system_cmds/getty.tproj/ttys.5 create mode 100644 system_cmds/hostinfo.tproj/hostinfo.8 create mode 100644 system_cmds/hostinfo.tproj/hostinfo.c create mode 100644 system_cmds/iosim.tproj/iosim.1 create mode 100644 system_cmds/iosim.tproj/iosim.c create mode 100644 system_cmds/iostat.tproj/iostat.8 create mode 100644 system_cmds/iostat.tproj/iostat.c create mode 100644 system_cmds/kpgo.tproj/kpgo.c create mode 100644 system_cmds/latency.tproj/latency.1 create mode 100644 system_cmds/latency.tproj/latency.c create mode 100644 system_cmds/login.tproj/klogin.c create mode 100644 system_cmds/login.tproj/login.1 create mode 100644 system_cmds/login.tproj/login.c create mode 100644 system_cmds/login.tproj/login.entitlements create mode 100644 system_cmds/login.tproj/login.h create mode 100644 system_cmds/login.tproj/login_audit.c create mode 100644 system_cmds/login.tproj/pam.d/login create mode 100644 system_cmds/login.tproj/pam.d/login.term create mode 100644 system_cmds/login.tproj/pathnames.h create mode 100644 system_cmds/lskq.tproj/common.h create mode 100644 system_cmds/lskq.tproj/lskq.1 create mode 100644 system_cmds/lskq.tproj/lskq.c create mode 100644 system_cmds/lsmp.tproj/common.h create mode 100644 system_cmds/lsmp.tproj/entitlements.plist create mode 100644 system_cmds/lsmp.tproj/json.h create mode 100644 system_cmds/lsmp.tproj/lsmp.1 create mode 100644 system_cmds/lsmp.tproj/lsmp.c create mode 100644 system_cmds/lsmp.tproj/port_details.c create mode 100644 system_cmds/lsmp.tproj/task_details.c create mode 100644 system_cmds/ltop.tproj/ltop.1 create mode 100644 system_cmds/ltop.tproj/ltop.c create mode 100644 system_cmds/mean.tproj/mean.c create mode 100644 system_cmds/memory_pressure.tproj/memory_pressure.1 create mode 100644 system_cmds/memory_pressure.tproj/memory_pressure.c create mode 100644 system_cmds/mkfile.tproj/mkfile.8 create mode 100644 system_cmds/mkfile.tproj/mkfile.c create mode 100644 system_cmds/mslutil/mslutil.1 create mode 100644 system_cmds/mslutil/mslutil.c create mode 100644 system_cmds/newgrp.tproj/newgrp.1 create mode 100644 system_cmds/newgrp.tproj/newgrp.c create mode 100644 system_cmds/nologin.tproj/nologin.5 create mode 100644 system_cmds/nologin.tproj/nologin.8 create mode 100644 system_cmds/nologin.tproj/nologin.c create mode 100644 system_cmds/nvram.tproj/nvram.8 create mode 100644 system_cmds/nvram.tproj/nvram.c create mode 100644 system_cmds/pagesize.tproj/pagesize.1 create mode 100644 system_cmds/pagesize.tproj/pagesize.sh create mode 100644 system_cmds/passwd.tproj/file_passwd.c create mode 100644 system_cmds/passwd.tproj/nis_passwd.c create mode 100644 system_cmds/passwd.tproj/od_passwd.c create mode 100644 system_cmds/passwd.tproj/pam_passwd.c create mode 100644 system_cmds/passwd.tproj/passwd.1 create mode 100644 system_cmds/passwd.tproj/passwd.c create mode 100644 system_cmds/passwd.tproj/passwd.entitlements create mode 100644 system_cmds/passwd.tproj/passwd.h create mode 100644 system_cmds/passwd.tproj/passwd.pam create mode 100644 system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.1 create mode 100644 system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.c create mode 100644 system_cmds/purge.tproj/purge.8 create mode 100644 system_cmds/purge.tproj/purge.c create mode 100644 system_cmds/pwd_mkdb.tproj/pw_scan.c create mode 100644 system_cmds/pwd_mkdb.tproj/pw_scan.h create mode 100644 system_cmds/pwd_mkdb.tproj/pwd_mkdb.8 create mode 100644 system_cmds/pwd_mkdb.tproj/pwd_mkdb.c create mode 100644 system_cmds/reboot.tproj/kextmanager.defs create mode 100644 system_cmds/reboot.tproj/reboot.8 create mode 100644 system_cmds/reboot.tproj/reboot.c create mode 100644 system_cmds/sa.tproj/db.c create mode 100644 system_cmds/sa.tproj/extern.h create mode 100644 system_cmds/sa.tproj/main.c create mode 100644 system_cmds/sa.tproj/pathnames.h create mode 100644 system_cmds/sa.tproj/pdb.c create mode 100644 system_cmds/sa.tproj/sa.8 create mode 100644 system_cmds/sa.tproj/usrdb.c create mode 100644 system_cmds/sc_usage.tproj/sc_usage.1 create mode 100644 system_cmds/sc_usage.tproj/sc_usage.c create mode 100644 system_cmds/shutdown.tproj/kextmanager.defs create mode 100644 system_cmds/shutdown.tproj/pathnames.h create mode 100644 system_cmds/shutdown.tproj/shutdown.8 create mode 100644 system_cmds/shutdown.tproj/shutdown.c create mode 100644 system_cmds/stackshot.tproj/stackshot.c create mode 100644 system_cmds/sync.tproj/sync.8 create mode 100644 system_cmds/sync.tproj/sync.c create mode 100644 system_cmds/sysctl.tproj/sysctl.8 create mode 100644 system_cmds/sysctl.tproj/sysctl.c create mode 100644 system_cmds/sysctl.tproj/sysctl.conf.5 create mode 100644 system_cmds/system_cmds.xcodeproj/project.pbxproj create mode 100644 system_cmds/system_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 system_cmds/system_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 system_cmds/system_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme create mode 100644 system_cmds/system_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme create mode 100644 system_cmds/taskpolicy.tproj/taskpolicy-entitlements.plist create mode 100644 system_cmds/taskpolicy.tproj/taskpolicy.8 create mode 100644 system_cmds/taskpolicy.tproj/taskpolicy.c create mode 100644 system_cmds/tests/system_cmds.plist create mode 100644 system_cmds/trace.tproj/trace.1 create mode 100644 system_cmds/trace.tproj/trace.c create mode 100644 system_cmds/vifs.tproj/vifs.8 create mode 100644 system_cmds/vifs.tproj/vifs.c create mode 100644 system_cmds/vipw.tproj/pw_util.c create mode 100644 system_cmds/vipw.tproj/pw_util.h create mode 100644 system_cmds/vipw.tproj/vipw.8 create mode 100644 system_cmds/vipw.tproj/vipw.c create mode 100644 system_cmds/vm_purgeable_stat.tproj/entitlements.plist create mode 100644 system_cmds/vm_purgeable_stat.tproj/vm_purgeable_stat.1 create mode 100644 system_cmds/vm_purgeable_stat.tproj/vm_purgeable_stat.c create mode 100644 system_cmds/vm_stat.tproj/vm_stat.1 create mode 100644 system_cmds/vm_stat.tproj/vm_stat.c create mode 100644 system_cmds/wait4path/wait4path.1 create mode 100644 system_cmds/wait4path/wait4path.c create mode 100644 system_cmds/wait4path/wait4path.version create mode 100644 system_cmds/wordexp-helper.tproj/wordexp-helper.c create mode 100644 system_cmds/xcconfigs/base.xcconfig create mode 100644 system_cmds/xcconfigs/development.xcconfig create mode 100644 system_cmds/xcconfigs/executable.xcconfig create mode 100644 system_cmds/xcconfigs/wait4path.xcconfig create mode 100644 system_cmds/xscripts/darwinversion.sh create mode 100644 system_cmds/zdump.tproj/zdump.8 create mode 100644 system_cmds/zdump.tproj/zdump.c create mode 100644 system_cmds/zic.tproj/Arts.htm create mode 100644 system_cmds/zic.tproj/Makefile.zoneinfo.dist create mode 100644 system_cmds/zic.tproj/README create mode 100644 system_cmds/zic.tproj/Theory create mode 100644 system_cmds/zic.tproj/ZIC_HACK create mode 100755 system_cmds/zic.tproj/build_zichost.sh create mode 100755 system_cmds/zic.tproj/generate_zone_file_list.sh create mode 100755 system_cmds/zic.tproj/generate_zoneinfo.sh create mode 100644 system_cmds/zic.tproj/ialloc.c create mode 100755 system_cmds/zic.tproj/install_zoneinfo.sh create mode 100644 system_cmds/zic.tproj/private.h create mode 100644 system_cmds/zic.tproj/scheck.c create mode 100644 system_cmds/zic.tproj/tz-art.htm create mode 100644 system_cmds/zic.tproj/tz-link.htm create mode 100644 system_cmds/zic.tproj/tzfile.h create mode 100644 system_cmds/zic.tproj/zic.8 create mode 100644 system_cmds/zic.tproj/zic.c create mode 100644 system_cmds/zlog.tproj/SymbolicationHelper.c create mode 100644 system_cmds/zlog.tproj/SymbolicationHelper.h create mode 100644 system_cmds/zlog.tproj/entitlements.plist create mode 100644 system_cmds/zlog.tproj/zlog.1 create mode 100644 system_cmds/zlog.tproj/zlog.c create mode 100644 system_cmds/zprint.tproj/entitlements.plist create mode 100644 system_cmds/zprint.tproj/test_zprint.lua create mode 100644 system_cmds/zprint.tproj/zprint.1 create mode 100644 system_cmds/zprint.tproj/zprint.c create mode 100644 system_cmds/zprint.tproj/zprint.lua create mode 100644 text_cmds/.upstream_base_commits create mode 100644 text_cmds/banner/banner.6 create mode 100644 text_cmds/banner/banner.c create mode 100644 text_cmds/cat/cat.1 create mode 100644 text_cmds/cat/cat.c create mode 100644 text_cmds/col/README create mode 100644 text_cmds/col/col.1 create mode 100644 text_cmds/col/col.c create mode 100644 text_cmds/colrm/colrm.1 create mode 100644 text_cmds/colrm/colrm.c create mode 100644 text_cmds/column/column.1 create mode 100644 text_cmds/column/column.c create mode 100644 text_cmds/comm/comm.1 create mode 100644 text_cmds/comm/comm.c create mode 100644 text_cmds/csplit/csplit.1 create mode 100644 text_cmds/csplit/csplit.c create mode 100644 text_cmds/cut/cut.1 create mode 100644 text_cmds/cut/cut.c create mode 100644 text_cmds/ed/POSIX create mode 100644 text_cmds/ed/README create mode 100644 text_cmds/ed/buf.c create mode 100644 text_cmds/ed/cbc.c create mode 100644 text_cmds/ed/ed.1 create mode 100644 text_cmds/ed/ed.h create mode 100644 text_cmds/ed/glbl.c create mode 100644 text_cmds/ed/io.c create mode 100644 text_cmds/ed/main.c create mode 100644 text_cmds/ed/re.c create mode 100644 text_cmds/ed/red.1 create mode 100644 text_cmds/ed/sub.c create mode 100644 text_cmds/ed/test/=.err create mode 100644 text_cmds/ed/test/README create mode 100644 text_cmds/ed/test/TODO create mode 100644 text_cmds/ed/test/a.d create mode 100644 text_cmds/ed/test/a.r create mode 100644 text_cmds/ed/test/a.t create mode 100644 text_cmds/ed/test/a1.err create mode 100644 text_cmds/ed/test/a2.err create mode 100644 text_cmds/ed/test/addr.d create mode 100644 text_cmds/ed/test/addr.r create mode 100644 text_cmds/ed/test/addr.t create mode 100644 text_cmds/ed/test/addr1.err create mode 100644 text_cmds/ed/test/addr2.err create mode 100644 text_cmds/ed/test/ascii.d.uu create mode 100644 text_cmds/ed/test/ascii.r.uu create mode 100644 text_cmds/ed/test/ascii.t create mode 100644 text_cmds/ed/test/bang1.d create mode 100644 text_cmds/ed/test/bang1.err create mode 100644 text_cmds/ed/test/bang1.r create mode 100644 text_cmds/ed/test/bang1.t create mode 100644 text_cmds/ed/test/bang2.err create mode 100644 text_cmds/ed/test/c.d create mode 100644 text_cmds/ed/test/c.r create mode 100644 text_cmds/ed/test/c.t create mode 100644 text_cmds/ed/test/c1.err create mode 100644 text_cmds/ed/test/c2.err create mode 100755 text_cmds/ed/test/ckscripts.sh create mode 100644 text_cmds/ed/test/d.d create mode 100644 text_cmds/ed/test/d.err create mode 100644 text_cmds/ed/test/d.r create mode 100644 text_cmds/ed/test/d.t create mode 100644 text_cmds/ed/test/e1.d create mode 100644 text_cmds/ed/test/e1.err create mode 100644 text_cmds/ed/test/e1.r create mode 100644 text_cmds/ed/test/e1.t create mode 100644 text_cmds/ed/test/e2.d create mode 100644 text_cmds/ed/test/e2.err create mode 100644 text_cmds/ed/test/e2.r create mode 100644 text_cmds/ed/test/e2.t create mode 100644 text_cmds/ed/test/e3.d create mode 100644 text_cmds/ed/test/e3.err create mode 100644 text_cmds/ed/test/e3.r create mode 100644 text_cmds/ed/test/e3.t create mode 100644 text_cmds/ed/test/e4.d create mode 100644 text_cmds/ed/test/e4.r create mode 100644 text_cmds/ed/test/e4.t create mode 100644 text_cmds/ed/test/f1.err create mode 100644 text_cmds/ed/test/f2.err create mode 100644 text_cmds/ed/test/g1.d create mode 100644 text_cmds/ed/test/g1.err create mode 100644 text_cmds/ed/test/g1.r create mode 100644 text_cmds/ed/test/g1.t create mode 100644 text_cmds/ed/test/g2.d create mode 100644 text_cmds/ed/test/g2.err create mode 100644 text_cmds/ed/test/g2.r create mode 100644 text_cmds/ed/test/g2.t create mode 100644 text_cmds/ed/test/g3.d create mode 100644 text_cmds/ed/test/g3.err create mode 100644 text_cmds/ed/test/g3.r create mode 100644 text_cmds/ed/test/g3.t create mode 100644 text_cmds/ed/test/g4.d create mode 100644 text_cmds/ed/test/g4.r create mode 100644 text_cmds/ed/test/g4.t create mode 100644 text_cmds/ed/test/g5.d create mode 100644 text_cmds/ed/test/g5.r create mode 100644 text_cmds/ed/test/g5.t create mode 100644 text_cmds/ed/test/h.err create mode 100644 text_cmds/ed/test/i.d create mode 100644 text_cmds/ed/test/i.r create mode 100644 text_cmds/ed/test/i.t create mode 100644 text_cmds/ed/test/i1.err create mode 100644 text_cmds/ed/test/i2.err create mode 100644 text_cmds/ed/test/i3.err create mode 100644 text_cmds/ed/test/j.d create mode 100644 text_cmds/ed/test/j.r create mode 100644 text_cmds/ed/test/j.t create mode 100644 text_cmds/ed/test/k.d create mode 100644 text_cmds/ed/test/k.r create mode 100644 text_cmds/ed/test/k.t create mode 100644 text_cmds/ed/test/k1.err create mode 100644 text_cmds/ed/test/k2.err create mode 100644 text_cmds/ed/test/k3.err create mode 100644 text_cmds/ed/test/k4.err create mode 100644 text_cmds/ed/test/l.d create mode 100644 text_cmds/ed/test/l.r create mode 100644 text_cmds/ed/test/l.t create mode 100644 text_cmds/ed/test/m.d create mode 100644 text_cmds/ed/test/m.err create mode 100644 text_cmds/ed/test/m.r create mode 100644 text_cmds/ed/test/m.t create mode 100755 text_cmds/ed/test/mkscripts.sh create mode 100644 text_cmds/ed/test/n.d create mode 100644 text_cmds/ed/test/n.r create mode 100644 text_cmds/ed/test/n.t create mode 100644 text_cmds/ed/test/nl.err create mode 100644 text_cmds/ed/test/nl1.d create mode 100644 text_cmds/ed/test/nl1.r create mode 100644 text_cmds/ed/test/nl1.t create mode 100644 text_cmds/ed/test/nl2.d create mode 100644 text_cmds/ed/test/nl2.r create mode 100644 text_cmds/ed/test/nl2.t create mode 100644 text_cmds/ed/test/p.d create mode 100644 text_cmds/ed/test/p.r create mode 100644 text_cmds/ed/test/p.t create mode 100644 text_cmds/ed/test/q.d create mode 100644 text_cmds/ed/test/q.r create mode 100644 text_cmds/ed/test/q.t create mode 100644 text_cmds/ed/test/q1.err create mode 100644 text_cmds/ed/test/r1.d create mode 100644 text_cmds/ed/test/r1.err create mode 100644 text_cmds/ed/test/r1.r create mode 100644 text_cmds/ed/test/r1.t create mode 100644 text_cmds/ed/test/r2.d create mode 100644 text_cmds/ed/test/r2.err create mode 100644 text_cmds/ed/test/r2.r create mode 100644 text_cmds/ed/test/r2.t create mode 100644 text_cmds/ed/test/r3.d create mode 100644 text_cmds/ed/test/r3.r create mode 100644 text_cmds/ed/test/r3.t create mode 100644 text_cmds/ed/test/s1.d create mode 100644 text_cmds/ed/test/s1.err create mode 100644 text_cmds/ed/test/s1.r create mode 100644 text_cmds/ed/test/s1.t create mode 100644 text_cmds/ed/test/s10.err create mode 100644 text_cmds/ed/test/s2.d create mode 100644 text_cmds/ed/test/s2.err create mode 100644 text_cmds/ed/test/s2.r create mode 100644 text_cmds/ed/test/s2.t create mode 100644 text_cmds/ed/test/s3.d create mode 100644 text_cmds/ed/test/s3.err create mode 100644 text_cmds/ed/test/s3.r create mode 100644 text_cmds/ed/test/s3.t create mode 100644 text_cmds/ed/test/s4.err create mode 100644 text_cmds/ed/test/s5.err create mode 100644 text_cmds/ed/test/s6.err create mode 100644 text_cmds/ed/test/s7.err create mode 100644 text_cmds/ed/test/s8.err create mode 100644 text_cmds/ed/test/s9.err create mode 100644 text_cmds/ed/test/t.d create mode 100644 text_cmds/ed/test/t.r create mode 100644 text_cmds/ed/test/t1.d create mode 100644 text_cmds/ed/test/t1.err create mode 100644 text_cmds/ed/test/t1.r create mode 100644 text_cmds/ed/test/t1.t create mode 100644 text_cmds/ed/test/t2.d create mode 100644 text_cmds/ed/test/t2.err create mode 100644 text_cmds/ed/test/t2.r create mode 100644 text_cmds/ed/test/t2.t create mode 100644 text_cmds/ed/test/u.d create mode 100644 text_cmds/ed/test/u.err create mode 100644 text_cmds/ed/test/u.r create mode 100644 text_cmds/ed/test/u.t create mode 100644 text_cmds/ed/test/v.d create mode 100644 text_cmds/ed/test/v.r create mode 100644 text_cmds/ed/test/v.t create mode 100644 text_cmds/ed/test/w.d create mode 100644 text_cmds/ed/test/w.r create mode 100644 text_cmds/ed/test/w.t create mode 100644 text_cmds/ed/test/w1.err create mode 100644 text_cmds/ed/test/w2.err create mode 100644 text_cmds/ed/test/w3.err create mode 100644 text_cmds/ed/test/x.err create mode 100644 text_cmds/ed/test/z.err create mode 100644 text_cmds/ed/undo.c create mode 100644 text_cmds/ee/Changes create mode 100644 text_cmds/ee/Makefile create mode 100644 text_cmds/ee/README.ee create mode 100755 text_cmds/ee/create.make create mode 100644 text_cmds/ee/ee.1 create mode 100644 text_cmds/ee/ee.c create mode 100644 text_cmds/ee/ee.i18n.guide create mode 100644 text_cmds/ee/ee.msg create mode 100644 text_cmds/ee/ee_version.h create mode 100755 text_cmds/ee/genstr create mode 100644 text_cmds/ee/make.default create mode 100644 text_cmds/ee/new_curse.c create mode 100644 text_cmds/ee/new_curse.h create mode 100644 text_cmds/expand/expand.1 create mode 100644 text_cmds/expand/expand.c create mode 100644 text_cmds/expand/xcodescripts/link-man-pages.sh create mode 100644 text_cmds/fmt/fmt.1 create mode 100644 text_cmds/fmt/fmt.c create mode 100644 text_cmds/fold/fold.1 create mode 100644 text_cmds/fold/fold.c create mode 100644 text_cmds/grep/file.c create mode 100644 text_cmds/grep/grep.1 create mode 100644 text_cmds/grep/grep.c create mode 100644 text_cmds/grep/grep.h create mode 100644 text_cmds/grep/queue.c create mode 100644 text_cmds/grep/util.c create mode 100644 text_cmds/head/head.1 create mode 100644 text_cmds/head/head.c create mode 100644 text_cmds/join/join.1 create mode 100644 text_cmds/join/join.c create mode 100644 text_cmds/lam/lam.1 create mode 100644 text_cmds/lam/lam.c create mode 100644 text_cmds/look/look.1 create mode 100644 text_cmds/look/look.c create mode 100644 text_cmds/look/pathnames.h create mode 100644 text_cmds/md5/commoncrypto.c create mode 100644 text_cmds/md5/commoncrypto.h create mode 100644 text_cmds/md5/md5.1 create mode 100644 text_cmds/md5/md5.c create mode 100644 text_cmds/nl/nl.1 create mode 100644 text_cmds/nl/nl.c create mode 100644 text_cmds/paste/paste.1 create mode 100644 text_cmds/paste/paste.c create mode 100644 text_cmds/pr/egetopt.c create mode 100644 text_cmds/pr/extern.h create mode 100644 text_cmds/pr/pr.1 create mode 100644 text_cmds/pr/pr.c create mode 100644 text_cmds/pr/pr.h create mode 100644 text_cmds/rev/rev.1 create mode 100644 text_cmds/rev/rev.c create mode 100644 text_cmds/rs/rs.1 create mode 100644 text_cmds/rs/rs.c create mode 100644 text_cmds/sed/POSIX create mode 100644 text_cmds/sed/TEST/hanoi.sed create mode 100644 text_cmds/sed/TEST/math.sed create mode 100644 text_cmds/sed/TEST/sed.test create mode 100644 text_cmds/sed/compile.c create mode 100644 text_cmds/sed/defs.h create mode 100644 text_cmds/sed/extern.h create mode 100644 text_cmds/sed/main.c create mode 100644 text_cmds/sed/misc.c create mode 100644 text_cmds/sed/process.c create mode 100644 text_cmds/sed/sed.1 create mode 100644 text_cmds/sort/bwstring.c create mode 100644 text_cmds/sort/bwstring.h create mode 100644 text_cmds/sort/coll.c create mode 100644 text_cmds/sort/coll.h create mode 100644 text_cmds/sort/commoncrypto.c create mode 100644 text_cmds/sort/commoncrypto.h create mode 100644 text_cmds/sort/file.c create mode 100644 text_cmds/sort/file.h create mode 100644 text_cmds/sort/mem.c create mode 100644 text_cmds/sort/mem.h create mode 100644 text_cmds/sort/nls/C.msg create mode 100644 text_cmds/sort/nls/hu_HU.ISO8859-2.msg create mode 100644 text_cmds/sort/radixsort.c create mode 100644 text_cmds/sort/radixsort.h create mode 100644 text_cmds/sort/sort.1.in create mode 100644 text_cmds/sort/sort.c create mode 100644 text_cmds/sort/sort.h create mode 100644 text_cmds/sort/testsuite/README.txt create mode 100644 text_cmds/sort/testsuite/bigsample.txt.xz create mode 100755 text_cmds/sort/testsuite/run.sh create mode 100644 text_cmds/sort/testsuite/sample.txt create mode 100644 text_cmds/sort/vsort.c create mode 100644 text_cmds/sort/vsort.h create mode 100644 text_cmds/split/split.1 create mode 100644 text_cmds/split/split.c create mode 100644 text_cmds/tail/extern.h create mode 100644 text_cmds/tail/forward.c create mode 100644 text_cmds/tail/misc.c create mode 100644 text_cmds/tail/read.c create mode 100644 text_cmds/tail/reverse.c create mode 100644 text_cmds/tail/tail.1 create mode 100644 text_cmds/tail/tail.c create mode 100644 text_cmds/tests/Makefile create mode 100644 text_cmds/tests/sort_vers.c create mode 100644 text_cmds/text_cmds.plist create mode 100644 text_cmds/text_cmds.xcodeproj/project.pbxproj create mode 100644 text_cmds/text_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 text_cmds/tr/cmap.c create mode 100644 text_cmds/tr/cmap.h create mode 100644 text_cmds/tr/cset.c create mode 100644 text_cmds/tr/cset.h create mode 100644 text_cmds/tr/extern.h create mode 100644 text_cmds/tr/str.c create mode 100644 text_cmds/tr/tr.1 create mode 100644 text_cmds/tr/tr.c create mode 100644 text_cmds/ul/ul.1 create mode 100644 text_cmds/ul/ul.c create mode 100644 text_cmds/unexpand/unexpand.c create mode 100644 text_cmds/uniq/uniq.1 create mode 100644 text_cmds/uniq/uniq.c create mode 100644 text_cmds/unvis/unvis.1 create mode 100644 text_cmds/unvis/unvis.c create mode 100644 text_cmds/vis/extern.h create mode 100644 text_cmds/vis/foldit.c create mode 100644 text_cmds/vis/vis.1 create mode 100644 text_cmds/vis/vis.c create mode 100644 text_cmds/wc/wc.1 create mode 100644 text_cmds/wc/wc.c create mode 100644 text_cmds/xcconfigs/base.xcconfig create mode 100644 text_cmds/xcconfigs/ee.xcconfig create mode 100644 text_cmds/xcconfigs/grep.xcconfig create mode 100644 text_cmds/xcconfigs/sort.xcconfig create mode 100644 text_cmds/xcodescripts/grep_variant_links.sh create mode 100644 text_cmds/xcodescripts/install-opensource.sh create mode 100644 text_cmds/xcodescripts/install-sort-man.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df967b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +base diff --git a/adv_cmds/.upstream_base_commits b/adv_cmds/.upstream_base_commits new file mode 100644 index 0000000..2e37ca8 --- /dev/null +++ b/adv_cmds/.upstream_base_commits @@ -0,0 +1,3 @@ +#freebsd = https://github.com/freebsd/freebsd.git +usr.bin/whois/whois.c freebsd whois/whois.c 872b698bd4a1bfc0bf008c09228e6fd238809c75 +usr.bin/whois/whois.1 freebsd whois/whois.1 7e6cabd06e6caa6a02eeb86308dc0cb3f27e10da diff --git a/adv_cmds/adv_cmds.xcodeproj/project.pbxproj b/adv_cmds/adv_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d1eda3c --- /dev/null +++ b/adv_cmds/adv_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,1806 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + FD0D7F98108FE550004F2A1C /* localedef */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FD0D7FA2108FE56E004F2A1C /* Build configuration list for PBXAggregateTarget "localedef" */; + buildPhases = ( + FD0D7F97108FE550004F2A1C /* ShellScript */, + FD0D7FA5108FE5AA004F2A1C /* Install man1 */, + ); + dependencies = ( + ); + name = localedef; + productName = localedef2; + }; + FD201DCD14369D0C00906237 /* pgrep */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FD201DCE14369D0C00906237 /* Build configuration list for PBXAggregateTarget "pgrep" */; + buildPhases = ( + FD201DD014369D1000906237 /* ShellScript */, + ); + dependencies = ( + FD201DD214369D5C00906237 /* PBXTargetDependency */, + ); + name = pgrep; + productName = pgrep; + }; + FDF2764E0FC60ECD00D7A3C6 /* Embedded */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDF276580FC60EE600D7A3C6 /* Build configuration list for PBXAggregateTarget "Embedded" */; + buildPhases = ( + ); + dependencies = ( + FD201DD614369D6700906237 /* PBXTargetDependency */, + FD201DBF14369B1700906237 /* PBXTargetDependency */, + FDF2766D0FC60F0D00D7A3C6 /* PBXTargetDependency */, + FDF2766B0FC60F0D00D7A3C6 /* PBXTargetDependency */, + ); + name = Embedded; + productName = Embedded; + }; + FDF276500FC60EDA00D7A3C6 /* Desktop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDF276570FC60EE600D7A3C6 /* Build configuration list for PBXAggregateTarget "Desktop" */; + buildPhases = ( + ); + dependencies = ( + FDF277670FC6102600D7A3C6 /* PBXTargetDependency */, + FDF277650FC6102600D7A3C6 /* PBXTargetDependency */, + FDF277630FC6102600D7A3C6 /* PBXTargetDependency */, + FDF2775F0FC6102600D7A3C6 /* PBXTargetDependency */, + FDF2775D0FC6102600D7A3C6 /* PBXTargetDependency */, + FDF2775B0FC6102600D7A3C6 /* PBXTargetDependency */, + FD0D7FA9108FE5C3004F2A1C /* PBXTargetDependency */, + FDF277570FC6102600D7A3C6 /* PBXTargetDependency */, + FDF277530FC6102600D7A3C6 /* PBXTargetDependency */, + FD201DD414369D6300906237 /* PBXTargetDependency */, + FD201DC114369B1D00906237 /* PBXTargetDependency */, + FDF2766F0FC60F0F00D7A3C6 /* PBXTargetDependency */, + FDF276710FC60F1300D7A3C6 /* PBXTargetDependency */, + FDF2776D0FC6102B00D7A3C6 /* PBXTargetDependency */, + FDF2776B0FC6102B00D7A3C6 /* PBXTargetDependency */, + FDF277690FC6102B00D7A3C6 /* PBXTargetDependency */, + ); + name = Desktop; + productName = Desktop; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + FD0D7FA4108FE58C004F2A1C /* localedef.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277140FC60FDF00D7A3C6 /* localedef.1 */; }; + FD201DC214369B4200906237 /* pkill.c in Sources */ = {isa = PBXBuildFile; fileRef = FD201DB014369AD000906237 /* pkill.c */; }; + FD201DC314369B4600906237 /* pkill.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD201DAF14369AD000906237 /* pkill.1 */; }; + FDCD383B143BC63000AB81C6 /* libsysmon.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FDCD383A143BC63000AB81C6 /* libsysmon.dylib */; }; + FDF2774B0FC6100400D7A3C6 /* cap_mkdb.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276DE0FC60FDF00D7A3C6 /* cap_mkdb.c */; }; + FDF277730FC6105F00D7A3C6 /* cap_mkdb.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF276DD0FC60FDF00D7A3C6 /* cap_mkdb.1 */; }; + FDF277790FC610EC00D7A3C6 /* finger.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276EC0FC60FDF00D7A3C6 /* finger.c */; }; + FDF2777A0FC610EC00D7A3C6 /* lprint.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276EF0FC60FDF00D7A3C6 /* lprint.c */; }; + FDF2777B0FC610EC00D7A3C6 /* net.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276F10FC60FDF00D7A3C6 /* net.c */; }; + FDF2777C0FC610EC00D7A3C6 /* sprint.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276F30FC60FDF00D7A3C6 /* sprint.c */; }; + FDF2777D0FC610EC00D7A3C6 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276F40FC60FDF00D7A3C6 /* util.c */; }; + FDF2779D0FC611B800D7A3C6 /* finger.conf.5 in Install man5 */ = {isa = PBXBuildFile; fileRef = FDF276ED0FC60FDF00D7A3C6 /* finger.conf.5 */; }; + FDF2779E0FC611BA00D7A3C6 /* finger.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF276EB0FC60FDF00D7A3C6 /* finger.1 */; }; + FDF277BE0FC612B000D7A3C6 /* whois.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277490FC60FDF00D7A3C6 /* whois.c */; }; + FDF277C20FC612C800D7A3C6 /* whois.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277480FC60FDF00D7A3C6 /* whois.1 */; }; + FDF277C40FC6133400D7A3C6 /* tty.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277450FC60FDF00D7A3C6 /* tty.c */; }; + FDF277C70FC6137B00D7A3C6 /* tty.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277440FC60FDF00D7A3C6 /* tty.1 */; }; + FDF277D70FC613F500D7A3C6 /* tabs.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277410FC60FDF00D7A3C6 /* tabs.c */; }; + FDF277D90FC6140400D7A3C6 /* tabs.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FDF277400FC60FDF00D7A3C6 /* tabs.1 */; }; + FDF277E80FC6144400D7A3C6 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FDF277E70FC6144400D7A3C6 /* libtermcap.dylib */; }; + FDF277EE0FC6148500D7A3C6 /* cchar.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277330FC60FDF00D7A3C6 /* cchar.c */; }; + FDF277EF0FC6148500D7A3C6 /* gfmt.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277350FC60FDF00D7A3C6 /* gfmt.c */; }; + FDF277F00FC6148500D7A3C6 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277360FC60FDF00D7A3C6 /* key.c */; }; + FDF277F10FC6148500D7A3C6 /* modes.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277380FC60FDF00D7A3C6 /* modes.c */; }; + FDF277F20FC6148500D7A3C6 /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277390FC60FDF00D7A3C6 /* print.c */; }; + FDF277F30FC6148500D7A3C6 /* stty.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2773B0FC60FDF00D7A3C6 /* stty.c */; }; + FDF277F40FC6148500D7A3C6 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2773D0FC60FDF00D7A3C6 /* util.c */; }; + FDF277F80FC614A300D7A3C6 /* stty.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF2773A0FC60FDF00D7A3C6 /* stty.1 */; }; + FDF278060FC6151E00D7A3C6 /* fmt.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277290FC60FDF00D7A3C6 /* fmt.c */; }; + FDF278070FC6151E00D7A3C6 /* keyword.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2772A0FC60FDF00D7A3C6 /* keyword.c */; }; + FDF278080FC6151E00D7A3C6 /* nlist.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2772C0FC60FDF00D7A3C6 /* nlist.c */; }; + FDF278090FC6151E00D7A3C6 /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2772D0FC60FDF00D7A3C6 /* print.c */; }; + FDF2780A0FC6151E00D7A3C6 /* ps.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF2772F0FC60FDF00D7A3C6 /* ps.c */; }; + FDF2780B0FC6151E00D7A3C6 /* tasks.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277310FC60FDF00D7A3C6 /* tasks.c */; }; + FDF278280FC615F900D7A3C6 /* ps.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF2772E0FC60FDF00D7A3C6 /* ps.1 */; }; + FDF278370FC6167800D7A3C6 /* lex.l in Sources */ = {isa = PBXBuildFile; fileRef = FDF277220FC60FDF00D7A3C6 /* lex.l */; }; + FDF278380FC6167800D7A3C6 /* yacc.y in Sources */ = {isa = PBXBuildFile; fileRef = FDF277260FC60FDF00D7A3C6 /* yacc.y */; }; + FDF278A30FC61D8900D7A3C6 /* mklocale.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277240FC60FDF00D7A3C6 /* mklocale.1 */; }; + FDF278C60FC61FDF00D7A3C6 /* lsvfs.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277180FC60FDF00D7A3C6 /* lsvfs.c */; }; + FDF278CA0FC61FFD00D7A3C6 /* lsvfs.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277170FC60FDF00D7A3C6 /* lsvfs.1 */; }; + FDF278D60FC6204E00D7A3C6 /* locale.cc in Sources */ = {isa = PBXBuildFile; fileRef = FDF2770A0FC60FDF00D7A3C6 /* locale.cc */; }; + FDF278DA0FC6206500D7A3C6 /* locale.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277090FC60FDF00D7A3C6 /* locale.1 */; }; + FDF278DB0FC6208600D7A3C6 /* last.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277060FC60FDF00D7A3C6 /* last.c */; }; + FDF278E00FC620A000D7A3C6 /* last.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF277050FC60FDF00D7A3C6 /* last.1 */; }; + FDF278F50FC623D300D7A3C6 /* gencat.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF276FE0FC60FDF00D7A3C6 /* gencat.c */; }; + FDF278F60FC623D300D7A3C6 /* genlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FDF277000FC60FDF00D7A3C6 /* genlib.c */; }; + FDF2792D0FC625B800D7A3C6 /* gencat.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF276FD0FC60FDF00D7A3C6 /* gencat.1 */; }; + FDF279390FC6263E00D7A3C6 /* parse.y in Sources */ = {isa = PBXBuildFile; fileRef = FDF276E70FC60FDF00D7A3C6 /* parse.y */; }; + FDF2793A0FC6263E00D7A3C6 /* scan.l in Sources */ = {isa = PBXBuildFile; fileRef = FDF276E80FC60FDF00D7A3C6 /* scan.l */; }; + FDF2795E0FC6272500D7A3C6 /* libl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FDF2795D0FC6272500D7A3C6 /* libl.a */; }; + FDF2798F0FC62B0800D7A3C6 /* colldef.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDF276E10FC60FDF00D7A3C6 /* colldef.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FD0D7FA8108FE5C3004F2A1C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD0D7F98108FE550004F2A1C; + remoteInfo = localedef; + }; + FD201DBE14369B1700906237 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD201DB414369B0300906237; + remoteInfo = pkill; + }; + FD201DC014369B1D00906237 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD201DB414369B0300906237; + remoteInfo = pkill; + }; + FD201DD114369D5C00906237 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD201DB414369B0300906237; + remoteInfo = pkill; + }; + FD201DD314369D6300906237 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD201DCD14369D0C00906237; + remoteInfo = pgrep; + }; + FD201DD514369D6700906237 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FD201DCD14369D0C00906237; + remoteInfo = pgrep; + }; + FDF2766A0FC60F0D00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276630FC60EFD00D7A3C6; + remoteInfo = stty; + }; + FDF2766C0FC60F0D00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF2765B0FC60EF600D7A3C6; + remoteInfo = ps; + }; + FDF2766E0FC60F0F00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF2765B0FC60EF600D7A3C6; + remoteInfo = ps; + }; + FDF276700FC60F1300D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276630FC60EFD00D7A3C6; + remoteInfo = stty; + }; + FDF277520FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276B00FC60F7600D7A3C6; + remoteInfo = mklocale; + }; + FDF277560FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276A40FC60F5E00D7A3C6; + remoteInfo = lsvfs; + }; + FDF2775A0FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276980FC60F5000D7A3C6; + remoteInfo = locale; + }; + FDF2775C0FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276920FC60F4B00D7A3C6; + remoteInfo = last; + }; + FDF2775E0FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF2768C0FC60F3D00D7A3C6; + remoteInfo = gencat; + }; + FDF277620FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276800FC60F3100D7A3C6; + remoteInfo = finger; + }; + FDF277640FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF2767A0FC60F2A00D7A3C6; + remoteInfo = colldef; + }; + FDF277660FC6102600D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276740FC60F2100D7A3C6; + remoteInfo = cap_mkdb; + }; + FDF277680FC6102B00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276C20FC60F8A00D7A3C6; + remoteInfo = whois; + }; + FDF2776A0FC6102B00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276BC0FC60F8400D7A3C6; + remoteInfo = tty; + }; + FDF2776C0FC6102B00D7A3C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDF276430FC60E9000D7A3C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDF276B60FC60F7F00D7A3C6; + remoteInfo = tabs; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FD0D7FA5108FE5AA004F2A1C /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FD0D7FA4108FE58C004F2A1C /* localedef.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FD201DB314369B0300906237 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + FD201DC314369B4600906237 /* pkill.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277780FC610A400D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF277730FC6105F00D7A3C6 /* cap_mkdb.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277A10FC611D800D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF2779E0FC611BA00D7A3C6 /* finger.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277A20FC611D800D7A3C6 /* Install man5 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man5; + dstSubfolderSpec = 0; + files = ( + FDF2779D0FC611B800D7A3C6 /* finger.conf.5 in Install man5 */, + ); + name = "Install man5"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277C30FC612D900D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF277C20FC612C800D7A3C6 /* whois.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277C60FC6135D00D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF277C70FC6137B00D7A3C6 /* tty.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF277E60FC6143000D7A3C6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF277D90FC6140400D7A3C6 /* tabs.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278030FC614B900D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF277F80FC614A300D7A3C6 /* stty.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278300FC6160800D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF278280FC615F900D7A3C6 /* ps.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278A40FC61D9600D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF278A30FC61D8900D7A3C6 /* mklocale.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278D50FC6201600D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF278CA0FC61FFD00D7A3C6 /* lsvfs.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278E70FC620B600D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF278E00FC620A000D7A3C6 /* last.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF278E80FC620B600D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF278DA0FC6206500D7A3C6 /* locale.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF279300FC625CB00D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF2792D0FC625B800D7A3C6 /* gencat.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDF279930FC62B0B00D7A3C6 /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + FDF2798F0FC62B0800D7A3C6 /* colldef.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + FD201DAF14369AD000906237 /* pkill.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; name = pkill.1; path = pkill/pkill.1; sourceTree = ""; }; + FD201DB014369AD000906237 /* pkill.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = pkill.c; path = pkill/pkill.c; sourceTree = ""; }; + FD201DB514369B0400906237 /* pkill */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pkill; sourceTree = BUILT_PRODUCTS_DIR; }; + FDCD383A143BC63000AB81C6 /* libsysmon.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsysmon.dylib; path = /usr/lib/libsysmon.dylib; sourceTree = ""; }; + FDF2765C0FC60EF600D7A3C6 /* ps */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ps; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276640FC60EFD00D7A3C6 /* stty */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stty; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276750FC60F2100D7A3C6 /* cap_mkdb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cap_mkdb; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF2767B0FC60F2A00D7A3C6 /* colldef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = colldef; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276810FC60F3100D7A3C6 /* finger */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = finger; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF2768D0FC60F3D00D7A3C6 /* gencat */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gencat; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276930FC60F4B00D7A3C6 /* last */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = last; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276990FC60F5000D7A3C6 /* locale */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locale; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276A50FC60F5E00D7A3C6 /* lsvfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lsvfs; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276B10FC60F7600D7A3C6 /* mklocale */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mklocale; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276B70FC60F7F00D7A3C6 /* tabs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tabs; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276BD0FC60F8400D7A3C6 /* tty */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tty; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276C30FC60F8A00D7A3C6 /* whois */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = whois; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF276DD0FC60FDF00D7A3C6 /* cap_mkdb.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = cap_mkdb.1; sourceTree = ""; }; + FDF276DE0FC60FDF00D7A3C6 /* cap_mkdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cap_mkdb.c; sourceTree = ""; }; + FDF276E10FC60FDF00D7A3C6 /* colldef.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = colldef.1; sourceTree = ""; }; + FDF276E20FC60FDF00D7A3C6 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + FDF276E50FC60FDF00D7A3C6 /* collate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = collate.h; sourceTree = ""; }; + FDF276E70FC60FDF00D7A3C6 /* parse.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = parse.y; sourceTree = ""; }; + FDF276E80FC60FDF00D7A3C6 /* scan.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = scan.l; sourceTree = ""; }; + FDF276EA0FC60FDF00D7A3C6 /* extern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + FDF276EB0FC60FDF00D7A3C6 /* finger.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = finger.1; sourceTree = ""; }; + FDF276EC0FC60FDF00D7A3C6 /* finger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finger.c; sourceTree = ""; }; + FDF276ED0FC60FDF00D7A3C6 /* finger.conf.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = finger.conf.5; sourceTree = ""; }; + FDF276EE0FC60FDF00D7A3C6 /* finger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = finger.h; sourceTree = ""; }; + FDF276EF0FC60FDF00D7A3C6 /* lprint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lprint.c; sourceTree = ""; }; + FDF276F10FC60FDF00D7A3C6 /* net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net.c; sourceTree = ""; }; + FDF276F20FC60FDF00D7A3C6 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = ""; }; + FDF276F30FC60FDF00D7A3C6 /* sprint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sprint.c; sourceTree = ""; }; + FDF276F40FC60FDF00D7A3C6 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + FDF276F60FC60FDF00D7A3C6 /* finger.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = finger.plist; sourceTree = ""; }; + FDF276F70FC60FDF00D7A3C6 /* fingerd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fingerd.8; sourceTree = ""; }; + FDF276F80FC60FDF00D7A3C6 /* fingerd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fingerd.c; sourceTree = ""; }; + FDF276FA0FC60FDF00D7A3C6 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = ""; }; + FDF276FD0FC60FDF00D7A3C6 /* gencat.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = gencat.1; sourceTree = ""; }; + FDF276FE0FC60FDF00D7A3C6 /* gencat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gencat.c; sourceTree = ""; }; + FDF276FF0FC60FDF00D7A3C6 /* gencat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gencat.h; sourceTree = ""; }; + FDF277000FC60FDF00D7A3C6 /* genlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genlib.c; sourceTree = ""; }; + FDF277050FC60FDF00D7A3C6 /* last.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = last.1; sourceTree = ""; }; + FDF277060FC60FDF00D7A3C6 /* last.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = last.c; sourceTree = ""; }; + FDF277090FC60FDF00D7A3C6 /* locale.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = locale.1; sourceTree = ""; }; + FDF2770A0FC60FDF00D7A3C6 /* locale.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = locale.cc; sourceTree = ""; }; + FDF277140FC60FDF00D7A3C6 /* localedef.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = localedef.1; sourceTree = ""; }; + FDF277170FC60FDF00D7A3C6 /* lsvfs.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = lsvfs.1; sourceTree = ""; }; + FDF277180FC60FDF00D7A3C6 /* lsvfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lsvfs.c; sourceTree = ""; }; + FDF2771F0FC60FDF00D7A3C6 /* extern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + FDF277210FC60FDF00D7A3C6 /* ldef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ldef.h; sourceTree = ""; }; + FDF277220FC60FDF00D7A3C6 /* lex.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = lex.l; sourceTree = ""; }; + FDF277240FC60FDF00D7A3C6 /* mklocale.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mklocale.1; sourceTree = ""; }; + FDF277250FC60FDF00D7A3C6 /* runefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runefile.h; sourceTree = ""; }; + FDF277260FC60FDF00D7A3C6 /* yacc.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = yacc.y; sourceTree = ""; }; + FDF277280FC60FDF00D7A3C6 /* extern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + FDF277290FC60FDF00D7A3C6 /* fmt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmt.c; sourceTree = ""; }; + FDF2772A0FC60FDF00D7A3C6 /* keyword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keyword.c; sourceTree = ""; }; + FDF2772C0FC60FDF00D7A3C6 /* nlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nlist.c; sourceTree = ""; }; + FDF2772D0FC60FDF00D7A3C6 /* print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + FDF2772E0FC60FDF00D7A3C6 /* ps.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ps.1; sourceTree = ""; }; + FDF2772F0FC60FDF00D7A3C6 /* ps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps.c; sourceTree = ""; }; + FDF277300FC60FDF00D7A3C6 /* ps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ps.h; sourceTree = ""; }; + FDF277310FC60FDF00D7A3C6 /* tasks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tasks.c; sourceTree = ""; }; + FDF277330FC60FDF00D7A3C6 /* cchar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cchar.c; sourceTree = ""; }; + FDF277340FC60FDF00D7A3C6 /* extern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + FDF277350FC60FDF00D7A3C6 /* gfmt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gfmt.c; sourceTree = ""; }; + FDF277360FC60FDF00D7A3C6 /* key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = ""; }; + FDF277380FC60FDF00D7A3C6 /* modes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = modes.c; sourceTree = ""; }; + FDF277390FC60FDF00D7A3C6 /* print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + FDF2773A0FC60FDF00D7A3C6 /* stty.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = stty.1; sourceTree = ""; }; + FDF2773B0FC60FDF00D7A3C6 /* stty.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stty.c; sourceTree = ""; }; + FDF2773C0FC60FDF00D7A3C6 /* stty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stty.h; sourceTree = ""; }; + FDF2773D0FC60FDF00D7A3C6 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + FDF277400FC60FDF00D7A3C6 /* tabs.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = tabs.1; sourceTree = ""; }; + FDF277410FC60FDF00D7A3C6 /* tabs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tabs.c; sourceTree = ""; }; + FDF277440FC60FDF00D7A3C6 /* tty.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = tty.1; sourceTree = ""; }; + FDF277450FC60FDF00D7A3C6 /* tty.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tty.c; sourceTree = ""; }; + FDF277480FC60FDF00D7A3C6 /* whois.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = whois.1; sourceTree = ""; }; + FDF277490FC60FDF00D7A3C6 /* whois.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = whois.c; sourceTree = ""; }; + FDF277E70FC6144400D7A3C6 /* libtermcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtermcap.dylib; path = /usr/lib/libtermcap.dylib; sourceTree = ""; }; + FDF2795D0FC6272500D7A3C6 /* libl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libl.a; path = /usr/lib/libl.a; sourceTree = ""; }; + FDF279760FC629B100D7A3C6 /* localedef.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = localedef.pl; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FD201DB214369B0300906237 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FDCD383B143BC63000AB81C6 /* libsysmon.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF2765A0FC60EF600D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276620FC60EFD00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276730FC60F2100D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276790FC60F2A00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF2795E0FC6272500D7A3C6 /* libl.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF2767F0FC60F3100D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF2768B0FC60F3D00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276910FC60F4B00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276970FC60F5000D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276A30FC60F5E00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276AF0FC60F7600D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276B50FC60F7F00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277E80FC6144400D7A3C6 /* libtermcap.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276BB0FC60F8400D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276C10FC60F8A00D7A3C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FD201DAD14369AB300906237 /* pkill */ = { + isa = PBXGroup; + children = ( + FD201DB014369AD000906237 /* pkill.c */, + FD201DAF14369AD000906237 /* pkill.1 */, + ); + name = pkill; + sourceTree = ""; + }; + FDF276410FC60E9000D7A3C6 = { + isa = PBXGroup; + children = ( + FDF276DA0FC60FD800D7A3C6 /* Source */, + FDF2765D0FC60EF600D7A3C6 /* Products */, + FDF277E70FC6144400D7A3C6 /* libtermcap.dylib */, + FDF2795D0FC6272500D7A3C6 /* libl.a */, + FDCD383A143BC63000AB81C6 /* libsysmon.dylib */, + ); + sourceTree = ""; + }; + FDF2765D0FC60EF600D7A3C6 /* Products */ = { + isa = PBXGroup; + children = ( + FDF2765C0FC60EF600D7A3C6 /* ps */, + FDF276640FC60EFD00D7A3C6 /* stty */, + FDF276750FC60F2100D7A3C6 /* cap_mkdb */, + FDF2767B0FC60F2A00D7A3C6 /* colldef */, + FDF276810FC60F3100D7A3C6 /* finger */, + FDF2768D0FC60F3D00D7A3C6 /* gencat */, + FDF276930FC60F4B00D7A3C6 /* last */, + FDF276990FC60F5000D7A3C6 /* locale */, + FDF276A50FC60F5E00D7A3C6 /* lsvfs */, + FDF276B10FC60F7600D7A3C6 /* mklocale */, + FDF276B70FC60F7F00D7A3C6 /* tabs */, + FDF276BD0FC60F8400D7A3C6 /* tty */, + FDF276C30FC60F8A00D7A3C6 /* whois */, + FD201DB514369B0400906237 /* pkill */, + ); + name = Products; + sourceTree = ""; + }; + FDF276DA0FC60FD800D7A3C6 /* Source */ = { + isa = PBXGroup; + children = ( + FDF276DC0FC60FDF00D7A3C6 /* cap_mkdb */, + FDF276E00FC60FDF00D7A3C6 /* colldef */, + FDF276E90FC60FDF00D7A3C6 /* finger */, + FDF276F50FC60FDF00D7A3C6 /* fingerd */, + FDF276FB0FC60FDF00D7A3C6 /* gencat */, + FDF277040FC60FDF00D7A3C6 /* last */, + FDF277080FC60FDF00D7A3C6 /* locale */, + FDF2770C0FC60FDF00D7A3C6 /* localedef */, + FDF277160FC60FDF00D7A3C6 /* lsvfs */, + FDF2771E0FC60FDF00D7A3C6 /* mklocale */, + FD201DAD14369AB300906237 /* pkill */, + FDF277270FC60FDF00D7A3C6 /* ps */, + FDF277320FC60FDF00D7A3C6 /* stty */, + FDF2773E0FC60FDF00D7A3C6 /* tabs */, + FDF277420FC60FDF00D7A3C6 /* tty */, + FDF277460FC60FDF00D7A3C6 /* whois */, + ); + name = Source; + sourceTree = ""; + }; + FDF276DC0FC60FDF00D7A3C6 /* cap_mkdb */ = { + isa = PBXGroup; + children = ( + FDF276DE0FC60FDF00D7A3C6 /* cap_mkdb.c */, + FDF276DD0FC60FDF00D7A3C6 /* cap_mkdb.1 */, + ); + path = cap_mkdb; + sourceTree = ""; + }; + FDF276E00FC60FDF00D7A3C6 /* colldef */ = { + isa = PBXGroup; + children = ( + FDF276E70FC60FDF00D7A3C6 /* parse.y */, + FDF276E80FC60FDF00D7A3C6 /* scan.l */, + FDF276E20FC60FDF00D7A3C6 /* common.h */, + FDF276E40FC60FDF00D7A3C6 /* locale */, + FDF276E10FC60FDF00D7A3C6 /* colldef.1 */, + ); + path = colldef; + sourceTree = ""; + }; + FDF276E40FC60FDF00D7A3C6 /* locale */ = { + isa = PBXGroup; + children = ( + FDF276E50FC60FDF00D7A3C6 /* collate.h */, + ); + path = locale; + sourceTree = ""; + }; + FDF276E90FC60FDF00D7A3C6 /* finger */ = { + isa = PBXGroup; + children = ( + FDF276EC0FC60FDF00D7A3C6 /* finger.c */, + FDF276EF0FC60FDF00D7A3C6 /* lprint.c */, + FDF276F10FC60FDF00D7A3C6 /* net.c */, + FDF276F30FC60FDF00D7A3C6 /* sprint.c */, + FDF276F40FC60FDF00D7A3C6 /* util.c */, + FDF276EA0FC60FDF00D7A3C6 /* extern.h */, + FDF276EE0FC60FDF00D7A3C6 /* finger.h */, + FDF276F20FC60FDF00D7A3C6 /* pathnames.h */, + FDF276EB0FC60FDF00D7A3C6 /* finger.1 */, + FDF276ED0FC60FDF00D7A3C6 /* finger.conf.5 */, + ); + path = finger; + sourceTree = ""; + }; + FDF276F50FC60FDF00D7A3C6 /* fingerd */ = { + isa = PBXGroup; + children = ( + FDF276F80FC60FDF00D7A3C6 /* fingerd.c */, + FDF276FA0FC60FDF00D7A3C6 /* pathnames.h */, + FDF276F70FC60FDF00D7A3C6 /* fingerd.8 */, + FDF276F60FC60FDF00D7A3C6 /* finger.plist */, + ); + path = fingerd; + sourceTree = ""; + }; + FDF276FB0FC60FDF00D7A3C6 /* gencat */ = { + isa = PBXGroup; + children = ( + FDF276FE0FC60FDF00D7A3C6 /* gencat.c */, + FDF277000FC60FDF00D7A3C6 /* genlib.c */, + FDF276FF0FC60FDF00D7A3C6 /* gencat.h */, + FDF276FD0FC60FDF00D7A3C6 /* gencat.1 */, + ); + path = gencat; + sourceTree = ""; + }; + FDF277040FC60FDF00D7A3C6 /* last */ = { + isa = PBXGroup; + children = ( + FDF277050FC60FDF00D7A3C6 /* last.1 */, + FDF277060FC60FDF00D7A3C6 /* last.c */, + ); + path = last; + sourceTree = ""; + }; + FDF277080FC60FDF00D7A3C6 /* locale */ = { + isa = PBXGroup; + children = ( + FDF277090FC60FDF00D7A3C6 /* locale.1 */, + FDF2770A0FC60FDF00D7A3C6 /* locale.cc */, + ); + path = locale; + sourceTree = ""; + }; + FDF2770C0FC60FDF00D7A3C6 /* localedef */ = { + isa = PBXGroup; + children = ( + FDF279760FC629B100D7A3C6 /* localedef.pl */, + FDF277140FC60FDF00D7A3C6 /* localedef.1 */, + ); + path = localedef; + sourceTree = ""; + }; + FDF277160FC60FDF00D7A3C6 /* lsvfs */ = { + isa = PBXGroup; + children = ( + FDF277170FC60FDF00D7A3C6 /* lsvfs.1 */, + FDF277180FC60FDF00D7A3C6 /* lsvfs.c */, + ); + path = lsvfs; + sourceTree = ""; + }; + FDF2771E0FC60FDF00D7A3C6 /* mklocale */ = { + isa = PBXGroup; + children = ( + FDF277220FC60FDF00D7A3C6 /* lex.l */, + FDF277260FC60FDF00D7A3C6 /* yacc.y */, + FDF2771F0FC60FDF00D7A3C6 /* extern.h */, + FDF277210FC60FDF00D7A3C6 /* ldef.h */, + FDF277250FC60FDF00D7A3C6 /* runefile.h */, + FDF277240FC60FDF00D7A3C6 /* mklocale.1 */, + ); + path = mklocale; + sourceTree = ""; + }; + FDF277270FC60FDF00D7A3C6 /* ps */ = { + isa = PBXGroup; + children = ( + FDF277290FC60FDF00D7A3C6 /* fmt.c */, + FDF2772A0FC60FDF00D7A3C6 /* keyword.c */, + FDF2772C0FC60FDF00D7A3C6 /* nlist.c */, + FDF2772D0FC60FDF00D7A3C6 /* print.c */, + FDF2772F0FC60FDF00D7A3C6 /* ps.c */, + FDF277310FC60FDF00D7A3C6 /* tasks.c */, + FDF277300FC60FDF00D7A3C6 /* ps.h */, + FDF277280FC60FDF00D7A3C6 /* extern.h */, + FDF2772E0FC60FDF00D7A3C6 /* ps.1 */, + ); + path = ps; + sourceTree = ""; + }; + FDF277320FC60FDF00D7A3C6 /* stty */ = { + isa = PBXGroup; + children = ( + FDF277330FC60FDF00D7A3C6 /* cchar.c */, + FDF277350FC60FDF00D7A3C6 /* gfmt.c */, + FDF277360FC60FDF00D7A3C6 /* key.c */, + FDF277380FC60FDF00D7A3C6 /* modes.c */, + FDF277390FC60FDF00D7A3C6 /* print.c */, + FDF2773B0FC60FDF00D7A3C6 /* stty.c */, + FDF2773D0FC60FDF00D7A3C6 /* util.c */, + FDF277340FC60FDF00D7A3C6 /* extern.h */, + FDF2773C0FC60FDF00D7A3C6 /* stty.h */, + FDF2773A0FC60FDF00D7A3C6 /* stty.1 */, + ); + path = stty; + sourceTree = ""; + }; + FDF2773E0FC60FDF00D7A3C6 /* tabs */ = { + isa = PBXGroup; + children = ( + FDF277400FC60FDF00D7A3C6 /* tabs.1 */, + FDF277410FC60FDF00D7A3C6 /* tabs.c */, + ); + path = tabs; + sourceTree = ""; + }; + FDF277420FC60FDF00D7A3C6 /* tty */ = { + isa = PBXGroup; + children = ( + FDF277440FC60FDF00D7A3C6 /* tty.1 */, + FDF277450FC60FDF00D7A3C6 /* tty.c */, + ); + path = tty; + sourceTree = ""; + }; + FDF277460FC60FDF00D7A3C6 /* whois */ = { + isa = PBXGroup; + children = ( + FDF277480FC60FDF00D7A3C6 /* whois.1 */, + FDF277490FC60FDF00D7A3C6 /* whois.c */, + ); + path = whois; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FD201DB414369B0300906237 /* pkill */ = { + isa = PBXNativeTarget; + buildConfigurationList = FD201DBC14369B0400906237 /* Build configuration list for PBXNativeTarget "pkill" */; + buildPhases = ( + FD201DB114369B0300906237 /* Sources */, + FD201DB214369B0300906237 /* Frameworks */, + FD201DB314369B0300906237 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = pkill; + productName = pkill; + productReference = FD201DB514369B0400906237 /* pkill */; + productType = "com.apple.product-type.tool"; + }; + FDF2765B0FC60EF600D7A3C6 /* ps */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276600FC60EF700D7A3C6 /* Build configuration list for PBXNativeTarget "ps" */; + buildPhases = ( + FDF276590FC60EF600D7A3C6 /* Sources */, + FDF2765A0FC60EF600D7A3C6 /* Frameworks */, + FDF278300FC6160800D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ps; + productName = ps; + productReference = FDF2765C0FC60EF600D7A3C6 /* ps */; + productType = "com.apple.product-type.tool"; + }; + FDF276630FC60EFD00D7A3C6 /* stty */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276690FC60EFF00D7A3C6 /* Build configuration list for PBXNativeTarget "stty" */; + buildPhases = ( + FDF276610FC60EFD00D7A3C6 /* Sources */, + FDF276620FC60EFD00D7A3C6 /* Frameworks */, + FDF278030FC614B900D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = stty; + productName = stty; + productReference = FDF276640FC60EFD00D7A3C6 /* stty */; + productType = "com.apple.product-type.tool"; + }; + FDF276740FC60F2100D7A3C6 /* cap_mkdb */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276C80FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "cap_mkdb" */; + buildPhases = ( + FDF276720FC60F2100D7A3C6 /* Sources */, + FDF276730FC60F2100D7A3C6 /* Frameworks */, + FDF277780FC610A400D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = cap_mkdb; + productName = cap_mkdb; + productReference = FDF276750FC60F2100D7A3C6 /* cap_mkdb */; + productType = "com.apple.product-type.tool"; + }; + FDF2767A0FC60F2A00D7A3C6 /* colldef */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276C90FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "colldef" */; + buildPhases = ( + FDF276780FC60F2A00D7A3C6 /* Sources */, + FDF276790FC60F2A00D7A3C6 /* Frameworks */, + FDF279930FC62B0B00D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = colldef; + productName = colldef; + productReference = FDF2767B0FC60F2A00D7A3C6 /* colldef */; + productType = "com.apple.product-type.tool"; + }; + FDF276800FC60F3100D7A3C6 /* finger */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276CA0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "finger" */; + buildPhases = ( + FDF2767E0FC60F3100D7A3C6 /* Sources */, + FDF2767F0FC60F3100D7A3C6 /* Frameworks */, + FDF277A10FC611D800D7A3C6 /* Install man1 */, + FDF277A20FC611D800D7A3C6 /* Install man5 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = finger; + productName = finger; + productReference = FDF276810FC60F3100D7A3C6 /* finger */; + productType = "com.apple.product-type.tool"; + }; + FDF2768C0FC60F3D00D7A3C6 /* gencat */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276CC0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "gencat" */; + buildPhases = ( + FDF2768A0FC60F3D00D7A3C6 /* Sources */, + FDF2768B0FC60F3D00D7A3C6 /* Frameworks */, + FDF279300FC625CB00D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = gencat; + productName = gencat; + productReference = FDF2768D0FC60F3D00D7A3C6 /* gencat */; + productType = "com.apple.product-type.tool"; + }; + FDF276920FC60F4B00D7A3C6 /* last */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276CD0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "last" */; + buildPhases = ( + FDF276900FC60F4B00D7A3C6 /* Sources */, + FDF276910FC60F4B00D7A3C6 /* Frameworks */, + FDF278E70FC620B600D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = last; + productName = last; + productReference = FDF276930FC60F4B00D7A3C6 /* last */; + productType = "com.apple.product-type.tool"; + }; + FDF276980FC60F5000D7A3C6 /* locale */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276CE0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "locale" */; + buildPhases = ( + FDF276960FC60F5000D7A3C6 /* Sources */, + FDF276970FC60F5000D7A3C6 /* Frameworks */, + FDF278E80FC620B600D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = locale; + productName = locale; + productReference = FDF276990FC60F5000D7A3C6 /* locale */; + productType = "com.apple.product-type.tool"; + }; + FDF276A40FC60F5E00D7A3C6 /* lsvfs */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276D00FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "lsvfs" */; + buildPhases = ( + FDF276A20FC60F5E00D7A3C6 /* Sources */, + FDF276A30FC60F5E00D7A3C6 /* Frameworks */, + FDF278D50FC6201600D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = lsvfs; + productName = lsvfs; + productReference = FDF276A50FC60F5E00D7A3C6 /* lsvfs */; + productType = "com.apple.product-type.tool"; + }; + FDF276B00FC60F7600D7A3C6 /* mklocale */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276D20FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "mklocale" */; + buildPhases = ( + FDF276AE0FC60F7600D7A3C6 /* Sources */, + FDF276AF0FC60F7600D7A3C6 /* Frameworks */, + FDF278A40FC61D9600D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = mklocale; + productName = mklocale; + productReference = FDF276B10FC60F7600D7A3C6 /* mklocale */; + productType = "com.apple.product-type.tool"; + }; + FDF276B60FC60F7F00D7A3C6 /* tabs */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276D30FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "tabs" */; + buildPhases = ( + FDF276B40FC60F7F00D7A3C6 /* Sources */, + FDF276B50FC60F7F00D7A3C6 /* Frameworks */, + FDF277E60FC6143000D7A3C6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tabs; + productName = tabs; + productReference = FDF276B70FC60F7F00D7A3C6 /* tabs */; + productType = "com.apple.product-type.tool"; + }; + FDF276BC0FC60F8400D7A3C6 /* tty */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276D40FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "tty" */; + buildPhases = ( + FDF276BA0FC60F8400D7A3C6 /* Sources */, + FDF276BB0FC60F8400D7A3C6 /* Frameworks */, + FDF277C60FC6135D00D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tty; + productName = tty; + productReference = FDF276BD0FC60F8400D7A3C6 /* tty */; + productType = "com.apple.product-type.tool"; + }; + FDF276C20FC60F8A00D7A3C6 /* whois */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDF276D50FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "whois" */; + buildPhases = ( + FDF276C00FC60F8A00D7A3C6 /* Sources */, + FDF276C10FC60F8A00D7A3C6 /* Frameworks */, + FDF277C30FC612D900D7A3C6 /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = whois; + productName = whois; + productReference = FDF276C30FC60F8A00D7A3C6 /* whois */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FDF276430FC60E9000D7A3C6 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0820; + }; + buildConfigurationList = FDF276460FC60E9000D7A3C6 /* Build configuration list for PBXProject "adv_cmds" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FDF276410FC60E9000D7A3C6; + productRefGroup = FDF2765D0FC60EF600D7A3C6 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FDF276500FC60EDA00D7A3C6 /* Desktop */, + FDF2764E0FC60ECD00D7A3C6 /* Embedded */, + FDF276740FC60F2100D7A3C6 /* cap_mkdb */, + FDF2767A0FC60F2A00D7A3C6 /* colldef */, + FDF276800FC60F3100D7A3C6 /* finger */, + FDF2768C0FC60F3D00D7A3C6 /* gencat */, + FDF276920FC60F4B00D7A3C6 /* last */, + FDF276980FC60F5000D7A3C6 /* locale */, + FD0D7F98108FE550004F2A1C /* localedef */, + FDF276A40FC60F5E00D7A3C6 /* lsvfs */, + FDF276B00FC60F7600D7A3C6 /* mklocale */, + FD201DCD14369D0C00906237 /* pgrep */, + FD201DB414369B0300906237 /* pkill */, + FDF2765B0FC60EF600D7A3C6 /* ps */, + FDF276630FC60EFD00D7A3C6 /* stty */, + FDF276B60FC60F7F00D7A3C6 /* tabs */, + FDF276BC0FC60F8400D7A3C6 /* tty */, + FDF276C20FC60F8A00D7A3C6 /* whois */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + FD0D7F97108FE550004F2A1C /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "set -ex\n/usr/bin/install -m ${INSTALL_MODE_FLAG} ${SRCROOT}/localedef/localedef.pl ${INSTALL_DIR}/localedef\n${CHMOD} +x ${INSTALL_DIR}/localedef"; + }; + FD201DD014369D1000906237 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". ${SRCROOT}/xcodescripts/variant_links.sh"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FD201DB114369B0300906237 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FD201DC214369B4200906237 /* pkill.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276590FC60EF600D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278060FC6151E00D7A3C6 /* fmt.c in Sources */, + FDF278070FC6151E00D7A3C6 /* keyword.c in Sources */, + FDF278080FC6151E00D7A3C6 /* nlist.c in Sources */, + FDF278090FC6151E00D7A3C6 /* print.c in Sources */, + FDF2780A0FC6151E00D7A3C6 /* ps.c in Sources */, + FDF2780B0FC6151E00D7A3C6 /* tasks.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276610FC60EFD00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277EE0FC6148500D7A3C6 /* cchar.c in Sources */, + FDF277EF0FC6148500D7A3C6 /* gfmt.c in Sources */, + FDF277F00FC6148500D7A3C6 /* key.c in Sources */, + FDF277F10FC6148500D7A3C6 /* modes.c in Sources */, + FDF277F20FC6148500D7A3C6 /* print.c in Sources */, + FDF277F30FC6148500D7A3C6 /* stty.c in Sources */, + FDF277F40FC6148500D7A3C6 /* util.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276720FC60F2100D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF2774B0FC6100400D7A3C6 /* cap_mkdb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276780FC60F2A00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF279390FC6263E00D7A3C6 /* parse.y in Sources */, + FDF2793A0FC6263E00D7A3C6 /* scan.l in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF2767E0FC60F3100D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277790FC610EC00D7A3C6 /* finger.c in Sources */, + FDF2777A0FC610EC00D7A3C6 /* lprint.c in Sources */, + FDF2777B0FC610EC00D7A3C6 /* net.c in Sources */, + FDF2777C0FC610EC00D7A3C6 /* sprint.c in Sources */, + FDF2777D0FC610EC00D7A3C6 /* util.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF2768A0FC60F3D00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278F50FC623D300D7A3C6 /* gencat.c in Sources */, + FDF278F60FC623D300D7A3C6 /* genlib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276900FC60F4B00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278DB0FC6208600D7A3C6 /* last.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276960FC60F5000D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278D60FC6204E00D7A3C6 /* locale.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276A20FC60F5E00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278C60FC61FDF00D7A3C6 /* lsvfs.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276AE0FC60F7600D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF278380FC6167800D7A3C6 /* yacc.y in Sources */, + FDF278370FC6167800D7A3C6 /* lex.l in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276B40FC60F7F00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277D70FC613F500D7A3C6 /* tabs.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276BA0FC60F8400D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277C40FC6133400D7A3C6 /* tty.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF276C00FC60F8A00D7A3C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDF277BE0FC612B000D7A3C6 /* whois.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FD0D7FA9108FE5C3004F2A1C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD0D7F98108FE550004F2A1C /* localedef */; + targetProxy = FD0D7FA8108FE5C3004F2A1C /* PBXContainerItemProxy */; + }; + FD201DBF14369B1700906237 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD201DB414369B0300906237 /* pkill */; + targetProxy = FD201DBE14369B1700906237 /* PBXContainerItemProxy */; + }; + FD201DC114369B1D00906237 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD201DB414369B0300906237 /* pkill */; + targetProxy = FD201DC014369B1D00906237 /* PBXContainerItemProxy */; + }; + FD201DD214369D5C00906237 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD201DB414369B0300906237 /* pkill */; + targetProxy = FD201DD114369D5C00906237 /* PBXContainerItemProxy */; + }; + FD201DD414369D6300906237 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD201DCD14369D0C00906237 /* pgrep */; + targetProxy = FD201DD314369D6300906237 /* PBXContainerItemProxy */; + }; + FD201DD614369D6700906237 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FD201DCD14369D0C00906237 /* pgrep */; + targetProxy = FD201DD514369D6700906237 /* PBXContainerItemProxy */; + }; + FDF2766B0FC60F0D00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276630FC60EFD00D7A3C6 /* stty */; + targetProxy = FDF2766A0FC60F0D00D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2766D0FC60F0D00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF2765B0FC60EF600D7A3C6 /* ps */; + targetProxy = FDF2766C0FC60F0D00D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2766F0FC60F0F00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF2765B0FC60EF600D7A3C6 /* ps */; + targetProxy = FDF2766E0FC60F0F00D7A3C6 /* PBXContainerItemProxy */; + }; + FDF276710FC60F1300D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276630FC60EFD00D7A3C6 /* stty */; + targetProxy = FDF276700FC60F1300D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277530FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276B00FC60F7600D7A3C6 /* mklocale */; + targetProxy = FDF277520FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277570FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276A40FC60F5E00D7A3C6 /* lsvfs */; + targetProxy = FDF277560FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2775B0FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276980FC60F5000D7A3C6 /* locale */; + targetProxy = FDF2775A0FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2775D0FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276920FC60F4B00D7A3C6 /* last */; + targetProxy = FDF2775C0FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2775F0FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF2768C0FC60F3D00D7A3C6 /* gencat */; + targetProxy = FDF2775E0FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277630FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276800FC60F3100D7A3C6 /* finger */; + targetProxy = FDF277620FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277650FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF2767A0FC60F2A00D7A3C6 /* colldef */; + targetProxy = FDF277640FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277670FC6102600D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276740FC60F2100D7A3C6 /* cap_mkdb */; + targetProxy = FDF277660FC6102600D7A3C6 /* PBXContainerItemProxy */; + }; + FDF277690FC6102B00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276C20FC60F8A00D7A3C6 /* whois */; + targetProxy = FDF277680FC6102B00D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2776B0FC6102B00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276BC0FC60F8400D7A3C6 /* tty */; + targetProxy = FDF2776A0FC6102B00D7A3C6 /* PBXContainerItemProxy */; + }; + FDF2776D0FC6102B00D7A3C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDF276B60FC60F7F00D7A3C6 /* tabs */; + targetProxy = FDF2776C0FC6102B00D7A3C6 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + FD0D7F99108FE550004F2A1C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = localedef; + }; + name = Release; + }; + FD201DBD14369B0400906237 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = pkill/entitlements.plist; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + FD201DCF14369D0C00906237 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + FDF276450FC60E9000D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx.internal; + USE_HEADERMAP = NO; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = __; + ZERO_LINK = NO; + }; + name = Release; + }; + FDF2764F0FC60ECD00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = Embedded; + }; + name = Release; + }; + FDF276510FC60EDA00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = Desktop; + }; + name = Release; + }; + FDF2765F0FC60EF700D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ps/entitlements.plist; + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + "INSTALL_MODE_FLAG[sdk=macosx*]" = "u+sw,go-w,a+rX"; + INSTALL_PATH = /bin; + PRODUCT_NAME = ps; + WARNING_CFLAGS = "-Wno-#warnings"; + }; + name = Release; + }; + FDF276660FC60EFD00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /bin; + PRODUCT_NAME = stty; + }; + name = Release; + }; + FDF276770FC60F2100D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = cap_mkdb; + }; + name = Release; + }; + FDF2767D0FC60F2A00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "__FBSDID=__RCSID", + COLLATE_DEBUG, + YY_NO_UNPUT, + ); + GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + INSTALL_PATH = /usr/bin; + LEXFLAGS = "-8"; + LEX_CASE_INSENSITIVE_SCANNER = YES; + PRODUCT_NAME = colldef; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/colldef $(SRCROOT)/colldef/locale"; + }; + name = Release; + }; + FDF276830FC60F3100D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = finger; + }; + name = Release; + }; + FDF2768F0FC60F3E00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = gencat; + }; + name = Release; + }; + FDF276950FC60F4C00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = last; + }; + name = Release; + }; + FDF2769B0FC60F5100D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = locale; + }; + name = Release; + }; + FDF276A70FC60F5F00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = lsvfs; + }; + name = Release; + }; + FDF276B30FC60F7700D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = mklocale; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/mklocale"; + }; + name = Release; + }; + FDF276B90FC60F8000D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = tabs; + }; + name = Release; + }; + FDF276BF0FC60F8500D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = "__FBSDID=__RCSID"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = tty; + }; + name = Release; + }; + FDF276C50FC60F8A00D7A3C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = whois; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FD0D7FA2108FE56E004F2A1C /* Build configuration list for PBXAggregateTarget "localedef" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD0D7F99108FE550004F2A1C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FD201DBC14369B0400906237 /* Build configuration list for PBXNativeTarget "pkill" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD201DBD14369B0400906237 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FD201DCE14369D0C00906237 /* Build configuration list for PBXAggregateTarget "pgrep" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD201DCF14369D0C00906237 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276460FC60E9000D7A3C6 /* Build configuration list for PBXProject "adv_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276450FC60E9000D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276570FC60EE600D7A3C6 /* Build configuration list for PBXAggregateTarget "Desktop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276510FC60EDA00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276580FC60EE600D7A3C6 /* Build configuration list for PBXAggregateTarget "Embedded" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF2764F0FC60ECD00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276600FC60EF700D7A3C6 /* Build configuration list for PBXNativeTarget "ps" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF2765F0FC60EF700D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276690FC60EFF00D7A3C6 /* Build configuration list for PBXNativeTarget "stty" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276660FC60EFD00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276C80FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "cap_mkdb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276770FC60F2100D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276C90FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "colldef" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF2767D0FC60F2A00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276CA0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "finger" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276830FC60F3100D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276CC0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "gencat" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF2768F0FC60F3E00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276CD0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "last" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276950FC60F4C00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276CE0FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "locale" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF2769B0FC60F5100D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276D00FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "lsvfs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276A70FC60F5F00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276D20FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "mklocale" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276B30FC60F7700D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276D30FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "tabs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276B90FC60F8000D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276D40FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "tty" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276BF0FC60F8500D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDF276D50FC60F9700D7A3C6 /* Build configuration list for PBXNativeTarget "whois" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDF276C50FC60F8A00D7A3C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FDF276430FC60E9000D7A3C6 /* Project object */; +} diff --git a/adv_cmds/adv_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/adv_cmds/adv_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/adv_cmds/adv_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/adv_cmds/cap_mkdb/cap_mkdb.1 b/adv_cmds/cap_mkdb/cap_mkdb.1 new file mode 100644 index 0000000..5bc4674 --- /dev/null +++ b/adv_cmds/cap_mkdb/cap_mkdb.1 @@ -0,0 +1,101 @@ +.\" 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. +.\" +.\" @(#)cap_mkdb.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd "June 6, 1993" +.Dt CAP_MKDB 1 +.Os +.Sh NAME +.Nm cap_mkdb +.Nd create capability database +.Pp +.Sh SYNOPSIS +.Nm cap_mkdb +.Op Fl v +.Op Fl f Ar outfile +.Ar file1 +.Op Ar file2 ... +.Pp +.Sh DESCRIPTION +.Nm Cap_mkdb +builds a hashed database out of the +.Xr getcap 3 +logical database constructed by the concatenation of the specified +files . +.Pp +The database is named by the basename of the first file argument and +the string +.Dq .db . +The +.Xr getcap 3 +routines can access the database in this form much more quickly +than they can the original text file(s). +.Pp +The ``tc'' capabilities of the records are expanded before the +record is stored into the database. +.Pp +The options as as follows: +.Bl -tag -width XXXXXX +.It Fl f Ar outfile +Specify a different database basename. +.It Fl v +Print out the number of capability records in the database. +.El +.Pp +.Sh FORMAT +Each record is stored in the database using two different types of keys. +.Pp +The first type is a key which consists of the first capability of +the record (not including the trailing colon (``:'')) with a data +field consisting of a special byte followed by the rest of the record. +The special byte is either a 0 or 1, where a 0 means that the record +is okay, and a 1 means that there was a ``tc'' capability in the record +that couldn't be expanded. +.Pp +The second type is a key which consists of one of the names from the +first capability of the record with a data field consisting a special +byte followed by the the first capability of the record. +The special byte is a 2. +.Pp +In normal operation names are looked up in the database, resulting +in a key/data pair of the second type. +The data field of this key/data pair is used to look up a key/data +pair of the first type which has the real data associated with the +name. +.Sh RETURN VALUE +The +.Nm cap_mkdb +utility exits 0 on success and >0 if an error occurs. +.Sh SEE ALSO +.Xr dbopen 3 , +.Xr getcap 3 , +.Xr termcap 5 diff --git a/adv_cmds/cap_mkdb/cap_mkdb.c b/adv_cmds/cap_mkdb/cap_mkdb.c new file mode 100644 index 0000000..9c26d59 --- /dev/null +++ b/adv_cmds/cap_mkdb/cap_mkdb.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * The NEXTSTEP Software License Agreement specifies the terms + * and conditions for redistribution. + * + * @(#)cap_mkdb.c 8.2 (Berkeley) 4/27/95 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void db_build __P((char **)); +void dounlink __P((void)); +void usage __P((void)); + +DB *capdbp; +int verbose; +char *capdb, *capname, buf[8 * 1024]; + +HASHINFO openinfo = { + 4096, /* bsize */ + 16, /* ffactor */ + 256, /* nelem */ + 2048 * 1024, /* cachesize */ + NULL, /* hash() */ + 0 /* lorder */ +}; + +/* + * Mkcapdb creates a capability hash database for quick retrieval of capability + * records. The database contains 2 types of entries: records and references + * marked by the first byte in the data. A record entry contains the actual + * capability record whereas a reference contains the name (key) under which + * the correct record is stored. + */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c; + + capname = NULL; + while ((c = getopt(argc, argv, "f:v")) != EOF) { + switch(c) { + case 'f': + capname = optarg; + break; + case 'v': + verbose = 1; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (*argv == NULL) + usage(); + + /* + * The database file is the first argument if no name is specified. + * Make arrangements to unlink it if exit badly. + */ + (void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv); + if ((capname = strdup(buf)) == NULL) + err(1, ""); + if ((capdbp = dbopen(capname, O_CREAT | O_TRUNC | O_RDWR, + DEFFILEMODE, DB_HASH, &openinfo)) == NULL) + err(1, "%s", buf); + + if (atexit(dounlink)) + err(1, "atexit"); + + db_build(argv); + + if (capdbp->close(capdbp) < 0) + err(1, "%s", capname); + capname = NULL; + exit(0); +} + +void +dounlink() +{ + if (capname != NULL) + (void)unlink(capname); +} + +/* + * Any changes to these definitions should be made also in the getcap(3) + * library routines. + */ +#define RECOK (char)0 +#define TCERR (char)1 +#define SHADOW (char)2 + +/* + * Db_build() builds the name and capabilty databases according to the + * details above. + */ +void +db_build(ifiles) + char **ifiles; +{ + DBT key, data; + recno_t reccnt; + size_t len, bplen; + int st; + char *bp, *p, *t; + + data.data = NULL; + key.data = NULL; + for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) { + + /* + * Allocate enough memory to store record, terminating + * NULL and one extra byte. + */ + len = strlen(bp); + if (bplen <= len + 2) { + bplen += MAX(256, len + 2); + if ((data.data = realloc(data.data, bplen)) == NULL) + err(1, ""); + } + + /* Find the end of the name field. */ + if ((p = strchr(bp, ':')) == NULL) { + warnx("no name field: %.*s", MIN(len, 20), bp); + continue; + } + + /* First byte of stored record indicates status. */ + switch(st) { + case 1: + ((char *)(data.data))[0] = RECOK; + break; + case 2: + ((char *)(data.data))[0] = TCERR; + warnx("Record not tc expanded: %.*s", p - bp, bp); + break; + } + + /* Create the stored record. */ + memmove(&((u_char *)(data.data))[1], bp, len + 1); + data.size = len + 2; + + /* Store the record under the name field. */ + key.data = bp; + key.size = p - bp; + + switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) { + case -1: + err(1, "put"); + /* NOTREACHED */ + case 1: + warnx("ignored duplicate: %.*s", + key.size, (char *)key.data); + continue; + } + ++reccnt; + + /* If only one name, ignore the rest. */ + if ((p = strchr(bp, '|')) == NULL) + continue; + + /* The rest of the names reference the entire name. */ + ((char *)(data.data))[0] = SHADOW; + memmove(&((u_char *)(data.data))[1], key.data, key.size); + data.size = key.size + 1; + + /* Store references for other names. */ + for (p = t = bp;; ++p) { + if (p > t && (*p == ':' || *p == '|')) { + key.size = p - t; + key.data = t; + switch(capdbp->put(capdbp, + &key, &data, R_NOOVERWRITE)) { + case -1: + err(1, "put"); + /* NOTREACHED */ + case 1: + warnx("ignored duplicate: %.*s", + key.size, (char *)key.data); + } + t = p + 1; + } + if (*p == ':') + break; + } + } + + switch(st) { + case -1: + err(1, "file argument"); + /* NOTREACHED */ + case -2: + errx(1, "potential reference loop detected"); + /* NOTREACHED */ + } + + if (verbose) + (void)printf("cap_mkdb: %d capability records\n", reccnt); +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: cap_mkdb [-v] [-f outfile] file1 [file2 ...]\n"); + exit(1); +} diff --git a/adv_cmds/colldef/colldef.1 b/adv_cmds/colldef/colldef.1 new file mode 100644 index 0000000..f4f875b --- /dev/null +++ b/adv_cmds/colldef/colldef.1 @@ -0,0 +1,274 @@ +.\" Copyright (c) 1995 Alex Tatmanjants +.\" 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. +.\" +.\" $FreeBSD: src/usr.bin/colldef/colldef.1,v 1.21 2004/05/19 09:45:46 ru Exp $ +.\" +.Dd January 27, 1995 +.Dt COLLDEF 1 +.Os +.Sh NAME +.Nm colldef +.Nd convert collation sequence source definition +.Sh SYNOPSIS +.Nm +.Op Fl I Ar map_dir +.Op Fl o Ar out_file +.Op Ar filename +.Sh DESCRIPTION +The +.Nm +utility converts a collation sequence source definition +into a format usable by the +.Fn strxfrm +and +.Fn strcoll +functions. +It is used to define the many ways in which +strings can be ordered and collated. +The +.Fn strxfrm +function transforms +its first argument and places the result in its second +argument. +The transformed string is such that it can be +correctly ordered with other transformed strings by using +.Fn strcmp , +.Fn strncmp , +or +.Fn memcmp . +The +.Fn strcoll +function transforms its arguments and does a +comparison. +.Pp +The +.Nm +utility reads the collation sequence source definition +from the standard input and stores the converted definition in filename. +The output file produced contains the +database with collating sequence information in a form +usable by system commands and routines. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl I Ar map_dir +Set directory name where +.Ar charmap +files can be found, current directory by default. +.It Fl o Ar out_file +Set output file name, +.Ar LC_COLLATE +by default. +.El +.Pp +The collation sequence definition specifies a set of collating elements and +the rules defining how strings containing these should be ordered. +This is most useful for different language definitions. +.Pp +The specification file can consist of three statements: +.Ar charmap , +.Ar substitute +and +.Ar order . +.Pp +Of these, only the +.Ar order +statement is required. +When +.Ar charmap +or +.Ar substitute +is +supplied, these statements must be ordered as above. +Any +statements after the order statement are ignored. +.Pp +Lines in the specification file beginning with a +.Ql # +are +treated as comments and are ignored. +Blank lines are also +ignored. +.Pp +.Dl "charmap charmapfile" +.Pp +.Ar Charmap +defines where a mapping of the character +and collating element symbols to the actual +character encoding can be found. +.Pp +The format of +.Ar charmapfile +is shown below. +Symbol +names are separated from their values by TAB or +SPACE characters. +Symbol-value can be specified in +a hexadecimal (\ex\fI??\fR) or octal (\e\fI???\fR) +representation, and can be only one character in length. +.Pp +.Bd -literal -offset indent +symbol-name1 symbol-value1 +symbol-name2 symbol-value2 +\&... +.Ed +.Pp +Symbol names cannot be specified in +.Ar substitute +fields. +.Pp +The +.Ar charmap +statement is optional. +.Pp +.Bd -literal -offset indent +substitute "symbol" with "repl_string" +.Ed +.Pp +The +.Ar substitute +statement substitutes the character +.Ar symbol +with the string +.Ar repl_string . +Symbol names cannot be specified in +.Ar repl_string +field. +The +.Ar substitute +statement is optional. +.Pp +.Dl "order order_list" +.Pp +.Ar Order_list +is a list of symbols, separated by semi colons, that defines the +collating sequence. +The +special symbol +.Ar ... +specifies, in a short-hand +form, symbols that are sequential in machine code +order. +.Pp +An order list element +can be represented in any one of the following +ways: +.Bl -bullet +.It +The symbol itself (for example, +.Ar a +for the lower-case letter +.Ar a ) . +.It +The symbol in octal representation (for example, +.Ar \e141 +for the letter +.Ar a ) . +.It +The symbol in hexadecimal representation (for example, +.Ar \ex61 +for the letter +.Ar a ) . +.It +The symbol name as defined in the +.Ar charmap +file (for example, +.Ar +for +.Ar letterA \e023 +record in +.Ar charmapfile ) . +If character map name have +.Ar > +character, it must be escaped as +.Ar /> , +single +.Ar / +must be escaped as +.Ar // . +.It +Symbols +.Ar \ea , +.Ar \eb , +.Ar \ef , +.Ar \en , +.Ar \er , +.Ar \ev +are permitted in its usual C-language meaning. +.It +The symbol chain (for example: +.Ar abc , +.Ar c , +.Ar \exf1b\exf2 ) +.It +The symbol range (for example, +.Ar a;...;z ) . +.It +Comma-separated symbols, ranges and chains enclosed in parenthesis (for example +.Ar \&( +.Ar sym1 , +.Ar sym2 , +.Ar ... +.Ar \&) ) +are assigned the +same primary ordering but different secondary +ordering. +.It +Comma-separated symbols, ranges and chains enclosed in curly brackets (for example +.Ar \&{ +.Ar sym1 , +.Ar sym2 , +.Ar ... +.Ar \&} ) +are assigned the same primary ordering only. +.El +.Pp +The backslash character +.Ar \e +is used for continuation. +In this case, no characters are permitted +after the backslash character. +.Sh DIAGNOSTICS +The +.Nm +utility exits with the following values: +.Bl -tag -width indent +.It Li 0 +No errors were found and the output was successfully created. +.It Li !=0 +Errors were found. +.El +.Sh FILES +.Bl -tag -width indent +.It Pa /usr/share/locale/ Ns Ao Ar language Ac Ns Pa /LC_COLLATE +The standard shared location for collation orders +under the locale +.Aq Ar language . +.El +.Sh SEE ALSO +.Xr mklocale 1 , +.Xr setlocale 3 , +.Xr strcoll 3 , +.Xr strxfrm 3 diff --git a/adv_cmds/colldef/common.h b/adv_cmds/colldef/common.h new file mode 100644 index 0000000..b59c125 --- /dev/null +++ b/adv_cmds/colldef/common.h @@ -0,0 +1,36 @@ +/* + * $FreeBSD: src/usr.bin/colldef/common.h,v 1.2 2001/11/28 09:50:24 ache Exp $ + */ + +#include +#include +#include + +#define CHARMAP_SYMBOL_LEN 64 +#define BUFSIZE 80 + +#define NOTEXISTS 0 +#define EXISTS 1 + +#define SYMBOL_CHAR 0 +#define SYMBOL_CHAIN 1 +#define SYMBOL_SYMBOL 2 +#define SYMBOL_STRING 3 +#define SYMBOL_IGNORE 4 +#define SYMBOL_ELLIPSIS 5 +struct symbol { + int type; + int val; + wchar_t name[CHARMAP_SYMBOL_LEN]; + union { + wchar_t wc; + wchar_t str[STR_LEN]; + } u; +}; + +extern int line_no; + +struct symbol *getsymbol(const wchar_t *, int); +extern char *showwcs(const wchar_t *, int); + +extern char map_name[FILENAME_MAX]; diff --git a/adv_cmds/colldef/locale/collate.h b/adv_cmds/colldef/locale/collate.h new file mode 100644 index 0000000..494e231 --- /dev/null +++ b/adv_cmds/colldef/locale/collate.h @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 1995 Alex Tatmanjants + * 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. + * + * $FreeBSD: src/lib/libc/locale/collate.h,v 1.14 2002/08/30 20:26:02 ache Exp $ + */ + +#ifndef _COLLATE_H_ +#define _COLLATE_H_ + +#include +#ifndef __LIBC__ +#include +#endif /* !__LIBC__ */ +#include + +#define STR_LEN 10 +#define TABLE_SIZE 100 +#define COLLATE_VERSION "1.0\n" +#define COLLATE_VERSION1_1 "1.1\n" +#define COLLATE_VERSION1_1A "1.1A\n" +/* see discussion in string/FreeBSD/strxfrm for this value */ +#define COLLATE_MAX_PRIORITY ((1 << 24) - 1) + +#define DIRECTIVE_UNDEF 0x00 +#define DIRECTIVE_FORWARD 0x01 +#define DIRECTIVE_BACKWARD 0x02 +#define DIRECTIVE_POSITION 0x04 + +#define DIRECTIVE_DIRECTION_MASK (DIRECTIVE_FORWARD | DIRECTIVE_BACKWARD) + +#define COLLATE_SUBST_DUP 0x0001 + +#define IGNORE_EQUIV_CLASS 1 + +struct __collate_st_info { + __uint8_t directive[COLL_WEIGHTS_MAX]; + __uint8_t flags; +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + __uint8_t directive_count:4; + __uint8_t chain_max_len:4; +#else + __uint8_t chain_max_len:4; + __uint8_t directive_count:4; +#endif + __int32_t undef_pri[COLL_WEIGHTS_MAX]; + __int32_t subst_count[COLL_WEIGHTS_MAX]; + __int32_t chain_count; + __int32_t large_pri_count; +}; + +struct __collate_st_char_pri { + __int32_t pri[COLL_WEIGHTS_MAX]; +}; +struct __collate_st_chain_pri { + __darwin_wchar_t str[STR_LEN]; + __int32_t pri[COLL_WEIGHTS_MAX]; +}; +struct __collate_st_large_char_pri { + __int32_t val; + struct __collate_st_char_pri pri; +}; +struct __collate_st_subst { + __int32_t val; + __darwin_wchar_t str[STR_LEN]; +}; + +#ifndef __LIBC__ +extern int __collate_load_error; +extern int __collate_substitute_nontrivial; +#define __collate_char_pri_table (*__collate_char_pri_table_ptr) +extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; +extern struct __collate_st_chain_pri *__collate_chain_pri_table; +extern __int32_t *__collate_chain_equiv_table; +extern struct __collate_st_info __collate_info; +#endif /* !__LIBC__ */ + +__BEGIN_DECLS +#ifdef __LIBC__ +__darwin_wchar_t *__collate_mbstowcs(const char *, locale_t); +__darwin_wchar_t *__collate_wcsdup(const __darwin_wchar_t *); +__darwin_wchar_t *__collate_substitute(const __darwin_wchar_t *, int, locale_t); +int __collate_load_tables(const char *, locale_t); +void __collate_lookup_l(const __darwin_wchar_t *, int *, int *, int *, locale_t); +void __collate_lookup_which(const __darwin_wchar_t *, int *, int *, int, locale_t); +void __collate_xfrm(const __darwin_wchar_t *, __darwin_wchar_t **, locale_t); +int __collate_range_cmp(__darwin_wchar_t, __darwin_wchar_t, locale_t); +size_t __collate_collating_symbol(__darwin_wchar_t *, size_t, const char *, size_t, __darwin_mbstate_t *, locale_t); +int __collate_equiv_class(const char *, size_t, __darwin_mbstate_t *, locale_t); +size_t __collate_equiv_match(int, __darwin_wchar_t *, size_t, __darwin_wchar_t, const char *, size_t, __darwin_mbstate_t *, size_t *, locale_t); +#else /* !__LIBC__ */ +void __collate_lookup(const unsigned char *, int *, int *, int *); +#endif /* __LIBC__ */ +#ifdef COLLATE_DEBUG +void __collate_print_tables(void); +#endif +__END_DECLS + +#endif /* !_COLLATE_H_ */ diff --git a/adv_cmds/colldef/parse.y b/adv_cmds/colldef/parse.y new file mode 100644 index 0000000..495c2f3 --- /dev/null +++ b/adv_cmds/colldef/parse.y @@ -0,0 +1,1416 @@ +%{ +/*- + * Copyright (c) 1995 Alex Tatmanjants + * 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. + */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/colldef/parse.y,v 1.31 2002/10/16 12:56:22 charnier Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "collate.h" +#include "common.h" + +#define PRI_UNDEFINED (-1) +#define PRI_IGNORE 0 +#define LINE_NONE (-1) +#define LINE_NORMAL 0 +#define LINE_ELLIPSIS 1 +#define LINE_UNDEFINED 2 +/* If UNDEFINED is specified with ellipses, we reposition prim_pri to + * UNDEFINED_PRI, leaving gap for undefined characters. */ +#define UNDEFINED_PRI (COLLATE_MAX_PRIORITY - (COLLATE_MAX_PRIORITY >> 2)) + +extern FILE *yyin; +void yyerror(const char *fmt, ...) __printflike(1, 2); +int yyparse(void); +int yylex(void); +static void usage(void); +static void collate_print_tables(void); +static struct __collate_st_char_pri *getpri(int32_t); +static struct __collate_st_char_pri *haspri(int32_t); +static struct __collate_st_chain_pri *getchain(const wchar_t *, int); +static struct symbol *getsymbolbychar(wchar_t); +static struct symbol *hassymbolbychar(wchar_t); +static void setsymbolbychar(struct symbol *); +struct symbol *getstring(const wchar_t *); +static void makeforwardref(int, const struct symbol *, const struct symbol *); +static int charpricompar(const void *, const void *); +static int substcompar(const void *, const void *); +static int chainpricompar(const void *, const void *); +static void putsubst(int32_t, int, const wchar_t *); +static int hassubst(int32_t, int); +static const wchar_t *__collate_wcsnchr(const wchar_t *, wchar_t, int); +static int __collate_wcsnlen(const wchar_t *, int); +char *showwcs(const wchar_t *, int); +static char *charname(wchar_t); +static char *charname2(wchar_t); + +char map_name[FILENAME_MAX] = "."; +wchar_t curr_chain[STR_LEN + 1]; + +char __collate_version[STR_LEN]; +DB *charmapdb; +static DB *charmapdb2; +static DB *largemapdb; +static int nlargemap = 0; +static DB *substdb[COLL_WEIGHTS_MAX]; +static int nsubst[COLL_WEIGHTS_MAX]; +static DB *chaindb; +static int nchain = 0; +static DB *stringdb; +static DB *forward_ref[COLL_WEIGHTS_MAX]; +static struct symbol *prev_weight_table[COLL_WEIGHTS_MAX]; +static struct symbol *prev2_weight_table[COLL_WEIGHTS_MAX]; +static struct symbol *weight_table[COLL_WEIGHTS_MAX]; +static int prev_line = LINE_NONE; +static struct symbol *prev_elem; +static int weight_index = 0; +static int allow_ellipsis = 0; +static struct symbol sym_ellipsis = {SYMBOL_ELLIPSIS, PRI_UNDEFINED}; +static struct symbol sym_ignore = {SYMBOL_IGNORE, PRI_IGNORE}; +static struct symbol sym_undefined = {SYMBOL_CHAR, PRI_UNDEFINED}; +static int order_pass = 0; + +#undef __collate_char_pri_table +struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; +struct __collate_st_chain_pri *__collate_chain_pri_table; +struct __collate_st_subst *__collate_substitute_table[COLL_WEIGHTS_MAX]; +struct __collate_st_large_char_pri *__collate_large_char_pri_table; + +int prim_pri = 2, sec_pri = 2; +#ifdef COLLATE_DEBUG +int debug; +#endif +struct __collate_st_info info = {{DIRECTIVE_FORWARD, DIRECTIVE_FORWARD}, 0, 0, 0, {PRI_UNDEFINED, PRI_UNDEFINED}}; + +/* Some of the code expects COLL_WEIGHTS_MAX == 2 */ +int directive_count = COLL_WEIGHTS_MAX; + +const char *out_file = "LC_COLLATE"; +%} +%union { + int32_t ch; + wchar_t str[BUFSIZE]; +} +%token SUBSTITUTE WITH +%token START_LC_COLLATE END_LC_COLLATE COLLATING_ELEMENT FROM COLLATING_SYMBOL +%token ELLIPSIS IGNORE UNDEFINED +%token ORDER RANGE ORDER_START ORDER_END ORDER_SECOND_PASS +%token STRING +%token DEFN +%token ELEM +%token CHAR +%token ORDER_DIRECTIVE +%% +collate : datafile { + FILE *fp; + int localedef = (stringdb != NULL); + int z; + + if (nchain > 0) { + DBT key, val; + struct __collate_st_chain_pri *t, *v; + wchar_t *wp, *tp; + int flags, i, len; + + if ((__collate_chain_pri_table = (struct __collate_st_chain_pri *)malloc(nchain * sizeof(struct __collate_st_chain_pri))) == NULL) + err(1, "chain malloc"); + flags = R_FIRST; + t = __collate_chain_pri_table; + for(i = 0; i < nchain; i++) { + if (chaindb->seq(chaindb, &key, &val, flags) != 0) + err(1, "Can't retrieve chaindb %d", i); + memcpy(&v, val.data, sizeof(struct __collate_st_chain_pri *)); + *t++ = *v; + if ((len = __collate_wcsnlen(v->str, STR_LEN)) > info.chain_max_len) + info.chain_max_len = len; + flags = R_NEXT; + } + if (chaindb->seq(chaindb, &key, &val, flags) == 0) + err(1, "More in chaindb after retrieving %d", nchain); + qsort(__collate_chain_pri_table, nchain, sizeof(struct __collate_st_chain_pri), chainpricompar); + } + for(z = 0; z < directive_count; z++) { + if (nsubst[z] > 0) { + DBT key, val; + struct __collate_st_subst *t; + wchar_t *wp, *tp; + int flags, i, j; + int32_t cval; + + if ((__collate_substitute_table[z] = (struct __collate_st_subst *)calloc(nsubst[z], sizeof(struct __collate_st_subst))) == NULL) + err(1, "__collate_substitute_table[%d] calloc", z); + flags = R_FIRST; + t = __collate_substitute_table[z]; + for(i = 0; i < nsubst[z]; i++) { + if (substdb[z]->seq(substdb[z], &key, &val, flags) != 0) + err(1, "Can't retrieve substdb[%d]", z); + memcpy(&cval, key.data, sizeof(int32_t)); + /* we don't set the byte order of t->val, since we + * need it for sorting */ + t->val = cval; + for(wp = (wchar_t *)val.data, tp = t->str, j = STR_LEN; *wp && j-- > 0;) + *tp++ = htonl(*wp++); + t++; + flags = R_NEXT; + } + if (substdb[z]->seq(substdb[z], &key, &val, flags) == 0) + err(1, "More in substdb[%d] after retrieving %d", z, nsubst[z]); + qsort(__collate_substitute_table[z], nsubst[z], sizeof(struct __collate_st_subst), substcompar); + } + } + if (nlargemap > 0) { + DBT key, val; + struct __collate_st_large_char_pri *t; + struct __collate_st_char_pri *p; + int flags, i, z; + int32_t cval; + + if ((__collate_large_char_pri_table = (struct __collate_st_large_char_pri *)malloc(nlargemap * sizeof(struct __collate_st_large_char_pri))) == NULL) + err(1, "nlargemap malloc"); + flags = R_FIRST; + t = __collate_large_char_pri_table; + for(i = 0; i < nlargemap; i++) { + if (largemapdb->seq(largemapdb, &key, &val, flags) != 0) + err(1, "Can't retrieve largemapdb %d", i); + memcpy(&cval, key.data, sizeof(int32_t)); + memcpy(&p, val.data, sizeof(struct __collate_st_char_pri *)); + /* we don't set the byte order of t->val, since we + * need it for sorting */ + t->val = cval; + for(z = 0; z < directive_count; z++) + t->pri.pri[z] = htonl(p->pri[z]); + t++; + flags = R_NEXT; + } + if (largemapdb->seq(largemapdb, &key, &val, flags) == 0) + err(1, "More in largemapdb after retrieving %d", nlargemap); + qsort(__collate_large_char_pri_table, nlargemap, sizeof(struct __collate_st_large_char_pri), charpricompar); + } + + if (info.undef_pri[0] == PRI_UNDEFINED) { + int i; + info.undef_pri[0] = prim_pri; + for(i = 1; i < directive_count; i++) + info.undef_pri[i] = -prim_pri; + } + + if (localedef) { + int ch, z, ret; + if (sym_undefined.val == PRI_UNDEFINED) { + int flags = R_FIRST; + DBT key, val; + struct symbol *v; + while((ret = charmapdb->seq(charmapdb, &key, &val, flags)) == 0) { + memcpy(&v, val.data, sizeof(struct symbol *)); + switch(v->type) { + case SYMBOL_CHAR: { + struct __collate_st_char_pri *p = haspri(v->u.wc); + if (!p || p->pri[0] == PRI_UNDEFINED) + warnx("<%s> was not defined", showwcs((const wchar_t *)key.data, key.size / sizeof(wchar_t))); + break; + } + case SYMBOL_CHAIN: { + struct __collate_st_chain_pri *p = getchain(v->u.str, EXISTS); + if (p->pri[0] == PRI_UNDEFINED) + warnx("<%s> was not defined", showwcs((const wchar_t *)key.data, key.size / sizeof(wchar_t))); + break; + } + } + flags = R_NEXT; + } + if (ret < 0) + err(1, "Error retrieving from charmapdb"); + } + for (ch = 1; ch < UCHAR_MAX + 1; ch++) { + for(z = 0; z < directive_count; z++) + if (__collate_char_pri_table[ch].pri[z] == PRI_UNDEFINED) + __collate_char_pri_table[ch].pri[z] = (info.undef_pri[z] >= 0) ? info.undef_pri[z] : (ch - info.undef_pri[z]); + } + for (ch = 0; ch < nlargemap; ch++) { + for(z = 0; z < directive_count; z++) + if (__collate_large_char_pri_table[ch].pri.pri[z] == PRI_UNDEFINED) + __collate_large_char_pri_table[ch].pri.pri[z] = (info.undef_pri[z] >= 0) ? info.undef_pri[z] : (__collate_large_char_pri_table[ch].val - info.undef_pri[z]); + } + } else { + int ch, substed, ordered; + int fatal = 0; + for (ch = 1; ch < UCHAR_MAX + 1; ch++) { + substed = hassubst(ch, 0); + ordered = (__collate_char_pri_table[ch].pri[0] != PRI_UNDEFINED); + if (!ordered && !substed) { + fatal = 1; + warnx("%s not found", charname(ch)); + } + if (substed && ordered) { + fatal = 1; + warnx("%s can't be ordered since substituted", charname(ch)); + } + } + if (fatal) + exit(1); + } + + /* COLLATE_SUBST_DUP depends on COLL_WEIGHTS_MAX == 2 */ + if (localedef) { + if (nsubst[0] == nsubst[1] && (nsubst[0] == 0 || + memcmp(__collate_substitute_table[0], __collate_substitute_table[1], nsubst[0] * sizeof(struct __collate_st_subst)) == 0)) { + info.flags |= COLLATE_SUBST_DUP; + nsubst[1] = 0; + } + } else { + info.flags |= COLLATE_SUBST_DUP; + nsubst[1] = 0; + } + + for(z = 0; z < directive_count; z++) + info.subst_count[z] = nsubst[z]; + + info.directive_count = directive_count; + info.chain_count = nchain; + info.large_pri_count = nlargemap; + + if ((fp = fopen(out_file, "w")) == NULL) + err(EX_UNAVAILABLE, "can't open destination file %s", + out_file); + + strcpy(__collate_version, COLLATE_VERSION1_1A); + if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1) + err(EX_IOERR, + "IO error writting collate version to destination file %s", + out_file); +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + for(z = 0; z < directive_count; z++) { + info.undef_pri[z] = htonl(info.undef_pri[z]); + info.subst_count[z] = htonl(info.subst_count[z]); + } + info.chain_count = htonl(info.chain_count); + info.large_pri_count = htonl(info.large_pri_count); +#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ + if (fwrite(&info, sizeof(info), 1, fp) != 1) + err(EX_IOERR, + "IO error writting collate info to destination file %s", + out_file); +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + { + int i, z; + struct __collate_st_char_pri *p = __collate_char_pri_table; + + for(i = UCHAR_MAX + 1; i-- > 0; p++) { + for(z = 0; z < directive_count; z++) + p->pri[z] = htonl(p->pri[z]); + } + } +#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ + if (fwrite(__collate_char_pri_table, + sizeof(__collate_char_pri_table), 1, fp) != 1) + err(EX_IOERR, + "IO error writting char table to destination file %s", + out_file); + for(z = 0; z < directive_count; z++) { + if (nsubst[z] > 0) { +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + struct __collate_st_subst *t = __collate_substitute_table[z]; + int i; + for(i = nsubst[z]; i > 0; i--) { + t->val = htonl(t->val); + t++; + } +#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ + if (fwrite(__collate_substitute_table[z], sizeof(struct __collate_st_subst), nsubst[z], fp) != nsubst[z]) + err(EX_IOERR, + "IO error writting large substprim table %d to destination file %s", + z, out_file); + } + } + if (nchain > 0) { +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + int i, j, z; + struct __collate_st_chain_pri *p = __collate_chain_pri_table; + wchar_t *w; + + for(i = nchain; i-- > 0; p++) { + for(j = STR_LEN, w = p->str; *w && j-- > 0; w++) + *w = htonl(*w); + for(z = 0; z < directive_count; z++) + p->pri[z] = htonl(p->pri[z]); + } +#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ + if (fwrite(__collate_chain_pri_table, + sizeof(*__collate_chain_pri_table), nchain, fp) != + (size_t)nchain) + err(EX_IOERR, + "IO error writting chain table to destination file %s", + out_file); + } + + if (nlargemap > 0) { +#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN + struct __collate_st_large_char_pri *t = __collate_large_char_pri_table; + int i; + for(i = 0; i < nlargemap; i++) { + t->val = htonl(t->val); + t++; + } +#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ + if (fwrite(__collate_large_char_pri_table, sizeof(struct __collate_st_large_char_pri), nlargemap, fp) != nlargemap) + err(EX_IOERR, + "IO error writting large pri tables to destination file %s", + out_file); + } + + if (fclose(fp) != 0) + err(EX_IOERR, "IO error closing destination file %s", + out_file); + +#ifdef COLLATE_DEBUG + if (debug) + collate_print_tables(); +#endif + exit(EX_OK); +} +; +datafile : statment_list + | blank_lines start_localedef localedef_sections blank_lines end_localedef blank_lines +; +statment_list : statment + | statment_list '\n' statment +; +statment : + | charmap + | substitute + | order +; +blank_lines : + | '\n' + | blank_lines '\n' +; +start_localedef : START_LC_COLLATE '\n' { + int i; + if ((stringdb = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen stringdb"); + directive_count = 0; + for(i = 0; i < COLL_WEIGHTS_MAX; i++) + info.directive[i] = DIRECTIVE_UNDEF; +} +; +end_localedef : END_LC_COLLATE '\n' +; +localedef_sections : localedef_preface localedef_order +; +localedef_preface : localedef_statment '\n' + | localedef_preface localedef_statment '\n' +; +localedef_statment : + | charmap + | collating_element + | collating_symbol +; +collating_element : COLLATING_ELEMENT ELEM FROM STRING { + int len; + struct symbol *s; + if (wcslen($2) > CHARMAP_SYMBOL_LEN) + yyerror("collating-element symbol name '%s' is too long", showwcs($2, CHARMAP_SYMBOL_LEN)); + if ((len = wcslen($4)) > STR_LEN) + yyerror("collating-element string '%s' is too long", showwcs($4, STR_LEN)); + if (len < 2) + yyerror("collating-element string '%s' must be at least two characters", showwcs($4, STR_LEN)); + s = getsymbol($2, NOTEXISTS); + s->val = PRI_UNDEFINED; + s->type = SYMBOL_CHAIN; + wcsncpy(s->u.str, $4, STR_LEN); + getchain($4, NOTEXISTS); +} +; +collating_symbol : COLLATING_SYMBOL ELEM { + struct symbol *s; + if (wcslen($2) > CHARMAP_SYMBOL_LEN) + yyerror("collating-element symbol name '%s' is too long", showwcs($2, CHARMAP_SYMBOL_LEN)); + s = getsymbol($2, NOTEXISTS); + s->val = PRI_UNDEFINED; + s->type = SYMBOL_SYMBOL; +} +; +localedef_order : order_start order_lines1 order_second_pass order_lines2 order_end +; +order_start: ORDER_START order_start_list '\n' +; +order_second_pass: ORDER_SECOND_PASS { + prev_line = LINE_NONE; + prev_elem = NULL; + order_pass++; +} +; +order_start_list : order_start_list_directives { + if (directive_count > 0) + yyerror("Multiple order_start lines not allowed"); + if ((info.directive[0] & DIRECTIVE_DIRECTION_MASK) == 0) + info.directive[0] |= DIRECTIVE_FORWARD; + directive_count++; +} + | order_start_list ';' order_start_list_directives { + if (directive_count >= COLL_WEIGHTS_MAX) + yyerror("only COLL_WEIGHTS_MAX weights allowed"); + if ((info.directive[directive_count] & DIRECTIVE_DIRECTION_MASK) == 0) + info.directive[directive_count] |= DIRECTIVE_FORWARD; + directive_count++; +} +; +order_start_list_directives : ORDER_DIRECTIVE { + info.directive[directive_count] = $1; +} + | order_start_list_directives ',' ORDER_DIRECTIVE { + int direction = ($3 & DIRECTIVE_DIRECTION_MASK); + int prev = (info.directive[directive_count] & DIRECTIVE_DIRECTION_MASK); + if (direction && prev && direction != prev) + yyerror("The forward and backward directives are mutually exclusive"); + info.directive[directive_count] |= $3; +} +; +order_lines1 : order_line1 '\n' + | order_lines1 order_line1 '\n' +; +order_line1 : + | ELEM { + struct symbol *s = getsymbol($1, EXISTS); + if (s->val != PRI_UNDEFINED) + yyerror("<%s> redefined", showwcs($1, CHARMAP_SYMBOL_LEN)); + if (prev_line == LINE_ELLIPSIS) { + struct symbol *m; + wchar_t i; + int v; + switch (s->type) { + case SYMBOL_CHAIN: + yyerror("Chain <%s> can't be endpoints of ellipsis", showwcs($1, CHARMAP_SYMBOL_LEN)); + case SYMBOL_SYMBOL: + yyerror("Collating symbol <%s> can't be endpoints of ellipsis", showwcs($1, CHARMAP_SYMBOL_LEN)); + } + if (s->u.wc <= prev_elem->u.wc) + yyerror("<%s> is before starting point of ellipsis", showwcs($1, CHARMAP_SYMBOL_LEN)); + for(i = prev_elem->u.wc + 1, v = prev_elem->val + 1; i < s->u.wc; i++, v++) { + m = getsymbolbychar(i); + if (m->val != PRI_UNDEFINED) + yyerror("<%s> was previously defined while filling ellipsis symbols", showwcs(m->name, CHARMAP_SYMBOL_LEN)); + m->val = v; + } + s->val = v; + } else + s->val = prim_pri; + prim_pri = s->val + 1; + weight_index = 0; +} weights { + int i; + struct symbol *s = getsymbol($1, EXISTS); + if (s->type == SYMBOL_SYMBOL) { + if (weight_index != 0) + yyerror("Can't specify weights for collating symbol <%s>", showwcs($1, CHARMAP_SYMBOL_LEN)); + } else if (weight_index == 0) { + for(i = 0; i < directive_count; i++) + weight_table[i] = s; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_NORMAL; + prev_elem = s; +} + | ELLIPSIS { weight_index = 0; allow_ellipsis = 1; } weights { + int i; + if (prev_line == LINE_ELLIPSIS) + yyerror("Illegal sequential ellipsis lines"); + if (prev_line == LINE_UNDEFINED) + yyerror("Ellipsis line can not follow UNDEFINED line"); + if (prev_line == LINE_NONE) + yyerror("Ellipsis line must follow a collating identifier lines"); + if (weight_index == 0) { + for(i = 0; i < directive_count; i++) + weight_table[i] = &sym_ellipsis; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + for(i = 0; i < directive_count; i++) { + if (weight_table[i]->type != SYMBOL_ELLIPSIS) + continue; + switch (prev_weight_table[i]->type) { + case SYMBOL_CHAIN: + yyerror("Startpoint of ellipsis can't be a collating element"); + case SYMBOL_IGNORE: + yyerror("Startpoint of ellipsis can't be IGNORE"); + case SYMBOL_SYMBOL: + yyerror("Startpoint of ellipsis can't be a collating symbol"); + case SYMBOL_STRING: + yyerror("Startpoint of ellipsis can't be a string"); + } + } + memcpy(prev2_weight_table, prev_weight_table, sizeof(prev_weight_table)); + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_ELLIPSIS; + allow_ellipsis = 0; +} + | UNDEFINED { + if (sym_undefined.val != PRI_UNDEFINED) + yyerror("Multiple UNDEFINED lines not allowed"); + sym_undefined.val = prim_pri++; + weight_index = 0; + allow_ellipsis = 1; +} weights { + int i; + if (weight_index == 0) { + weight_table[0] = &sym_undefined; + for(i = 1; i < directive_count; i++) + weight_table[i] = &sym_ellipsis; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_UNDEFINED; +} +; +order_lines2 : order_line2 '\n' + | order_lines2 order_line2 '\n' +; +order_line2 : + | ELEM { weight_index = 0; } weights { + int i; + struct symbol *s = getsymbol($1, EXISTS); + if (s->val == PRI_UNDEFINED) + yyerror("<%s> undefined", showwcs($1, CHARMAP_SYMBOL_LEN)); + if (s->type == SYMBOL_SYMBOL) { + if (weight_index != 0) + yyerror("Can't specify weights for collating symbol <%s>", showwcs($1, CHARMAP_SYMBOL_LEN)); + } else if (weight_index == 0) { + for(i = 0; i < directive_count; i++) + weight_table[i] = s; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + if (prev_line == LINE_ELLIPSIS) { + int w, x; + for(i = 0; i < directive_count; i++) { + switch (prev_weight_table[i]->type) { + case SYMBOL_CHAR: + case SYMBOL_CHAIN: + case SYMBOL_IGNORE: + case SYMBOL_SYMBOL: + for (w = prev_elem->u.wc + 1; w < s->u.wc; w++) { + struct __collate_st_char_pri *p = getpri(w); + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Char 0x02x previously defined", w); + p->pri[i] = prev_weight_table[i]->val; + } + break; + case SYMBOL_ELLIPSIS: + + switch (weight_table[i]->type) { + case SYMBOL_STRING: + yyerror("Strings can't be endpoints of ellipsis"); + case SYMBOL_CHAIN: + yyerror("Chains can't be endpoints of ellipsis"); + case SYMBOL_IGNORE: + yyerror("IGNORE can't be endpoints of ellipsis"); + case SYMBOL_SYMBOL: + yyerror("Collation symbols can't be endpoints of ellipsis"); + } + if (s->val - prev_elem->val != weight_table[i]->val - prev2_weight_table[i]->val) + yyerror("Range mismatch in weight %d", i); + x = prev2_weight_table[i]->val + 1; + for (w = prev_elem->u.wc + 1; w < s->u.wc; w++) { + struct __collate_st_char_pri *p = getpri(w); + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Char 0x02x previously defined", w); + p->pri[i] = x++; + } + break; + case SYMBOL_STRING: + for (w = prev_elem->u.wc + 1; w < s->u.wc; w++) { + struct __collate_st_char_pri *p = getpri(w); + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Char 0x02x previously defined", w); + putsubst(w, i, prev_weight_table[i]->u.str); + p->pri[i] = prev_weight_table[i]->val; + } + break; + } + } + } + switch(s->type) { + case SYMBOL_CHAR: { + struct __collate_st_char_pri *p = getpri(s->u.wc); + for(i = 0; i < directive_count; i++) { + switch (weight_table[i]->type) { + case SYMBOL_CHAR: + case SYMBOL_CHAIN: + case SYMBOL_IGNORE: + case SYMBOL_SYMBOL: + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Char 0x02x previously defined", s->u.wc); + p->pri[i] = weight_table[i]->val; + break; + case SYMBOL_STRING: + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Char 0x02x previously defined", s->u.wc); + putsubst(s->u.wc, i, weight_table[i]->u.str); + p->pri[i] = weight_table[i]->val; + break; + } + } + break; + } + case SYMBOL_CHAIN: { + struct __collate_st_chain_pri *p = getchain(s->u.str, EXISTS); + for(i = 0; i < directive_count; i++) { + switch (weight_table[i]->type) { + case SYMBOL_CHAR: + case SYMBOL_CHAIN: + case SYMBOL_IGNORE: + case SYMBOL_SYMBOL: + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Chain %s previously defined", showwcs(s->u.str, STR_LEN)); + p->pri[i] = weight_table[i]->val; + break; + case SYMBOL_STRING : + if (wcsncmp(s->u.str, weight_table[i]->u.str, STR_LEN) != 0) + yyerror("Chain/string mismatch"); + if (p->pri[i] != PRI_UNDEFINED) + yyerror("Chain %s previously defined", showwcs(s->u.str, STR_LEN)); + /* negative value mean don't substitute + * the chain, but it is in an + * equivalence class */ + p->pri[i] = -weight_table[i]->val; + } + } + break; + } + } + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_NORMAL; + prev_elem = s; +} + | ELLIPSIS { weight_index = 0; allow_ellipsis = 1; } weights { + int i; + if (prev_line == LINE_ELLIPSIS) + yyerror("Illegal sequential ellipsis lines"); + if (prev_line == LINE_UNDEFINED) + yyerror("Ellipsis line can not follow UNDEFINED line"); + if (prev_line == LINE_NONE) + yyerror("Ellipsis line must follow a collating identifier lines"); + if (weight_index == 0) { + for(i = 0; i < directive_count; i++) + weight_table[i] = &sym_ellipsis; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + for(i = 0; i < directive_count; i++) { + if (weight_table[i]->type != SYMBOL_ELLIPSIS) + continue; + switch (prev_weight_table[i]->type) { + case SYMBOL_CHAIN: + yyerror("Startpoint of ellipsis can't be a collating element"); + case SYMBOL_IGNORE: + yyerror("Startpoint of ellipsis can't be IGNORE"); + case SYMBOL_SYMBOL: + yyerror("Startpoint of ellipsis can't be a collating symbol"); + case SYMBOL_STRING: + yyerror("Startpoint of ellipsis can't be a string"); + } + } + memcpy(prev2_weight_table, prev_weight_table, sizeof(prev_weight_table)); + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_ELLIPSIS; + allow_ellipsis = 0; +} + | UNDEFINED { weight_index = 0; allow_ellipsis = 1; } weights { + int i; + + if (weight_index == 0) { + weight_table[0] = &sym_undefined; + for(i = 1; i < directive_count; i++) + weight_table[i] = &sym_ellipsis; + } else if (weight_index != directive_count) + yyerror("Not enough weights specified"); + for(i = 0; i < directive_count; i++) { + switch (weight_table[i]->type) { + case SYMBOL_CHAR: + case SYMBOL_CHAIN: + case SYMBOL_IGNORE: + case SYMBOL_SYMBOL: + info.undef_pri[i] = weight_table[i]->val; + break; + case SYMBOL_ELLIPSIS : + /* Negative values mean that the priority is + * relative to the lexical value */ + info.undef_pri[i] = -sym_undefined.val; + prim_pri = UNDEFINED_PRI; + break; + case SYMBOL_STRING : + yyerror("Strings can't be used with UNDEFINED"); + } + } + memcpy(prev_weight_table, weight_table, sizeof(weight_table)); + prev_line = LINE_UNDEFINED; +} +; +weights : + | weight + | weights ';' weight +; +weight : ELEM { + struct symbol *s; + if (weight_index >= directive_count) + yyerror("More weights than specified by order_start"); + s = getsymbol($1, EXISTS); + if (order_pass && s->val == PRI_UNDEFINED) + yyerror("<%s> is undefined", showwcs($1, CHARMAP_SYMBOL_LEN)); + weight_table[weight_index++] = s; +} + | ELLIPSIS { + if (weight_index >= directive_count) + yyerror("More weights than specified by order_start"); + if (!allow_ellipsis) + yyerror("Ellipsis weight not allowed"); + weight_table[weight_index++] = &sym_ellipsis; +} + | IGNORE { + if (weight_index >= directive_count) + yyerror("More weights than specified by order_start"); + weight_table[weight_index++] = &sym_ignore; +} + | STRING { + if (weight_index >= directive_count) + yyerror("More weights than specified by order_start"); + if (wcslen($1) > STR_LEN) + yyerror("String '%s' is too long", showwcs($1, STR_LEN)); + weight_table[weight_index++] = getstring($1); +} +; +order_end : ORDER_END '\n' +; +charmap : DEFN CHAR { + int len = wcslen($1); + struct symbol *s; + if (len > CHARMAP_SYMBOL_LEN) + yyerror("Charmap symbol name '%s' is too long", showwcs($1, CHARMAP_SYMBOL_LEN)); + s = getsymbol($1, NOTEXISTS); + s->type = SYMBOL_CHAR; + s->val = PRI_UNDEFINED; + s->u.wc = $2; + setsymbolbychar(s); +} +; +substitute : SUBSTITUTE CHAR WITH STRING { + if (wcslen($4) + 1 > STR_LEN) + yyerror("%s substitution is too long", charname($2)); + putsubst($2, 0, $4); +} +; +order : ORDER order_list +; +order_list : item + | order_list ';' item +; +chain : CHAR CHAR { + curr_chain[0] = $1; + curr_chain[1] = $2; + if (curr_chain[0] == '\0' || curr_chain[1] == '\0') + yyerror("\\0 can't be chained"); + curr_chain[2] = '\0'; +} + | chain CHAR { + static wchar_t tb[2]; + tb[0] = $2; + if (tb[0] == '\0') + yyerror("\\0 can't be chained"); + if (wcslen(curr_chain) + 1 > STR_LEN) + yyerror("Chain '%s' grows too long", curr_chain); + (void)wcscat(curr_chain, tb); +} +; +item : CHAR { + struct __collate_st_char_pri *p = getpri($1); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname($1)); + p->pri[0] = p->pri[1] = prim_pri; + sec_pri = ++prim_pri; +} + | chain { + struct __collate_st_chain_pri *c = getchain(curr_chain, NOTEXISTS); + c->pri[0] = c->pri[1] = prim_pri; + sec_pri = ++prim_pri; +} + | CHAR RANGE CHAR { + u_int i; + struct __collate_st_char_pri *p; + + if ($3 <= $1) + yyerror("Illegal range %s -- %s", charname($1), charname2($3)); + + for (i = $1; i <= $3; i++) { + p = getpri(i); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname(i)); + p->pri[0] = p->pri[1] = prim_pri++; + } + sec_pri = prim_pri; +} + | '{' mixed_order_list '}' { + prim_pri = sec_pri; +} + | '(' sec_order_list ')' { + prim_pri = sec_pri; +} +; +mixed_order_list : mixed_sub_list { + sec_pri++; +} + | mixed_order_list ';' mixed_sub_list { + sec_pri++; +} +; +mixed_sub_list : mixed_sub_item + | mixed_sub_list ',' mixed_sub_item +; +sec_order_list : sec_sub_item + | sec_order_list ',' sec_sub_item +; +mixed_sub_item : CHAR { + struct __collate_st_char_pri *p = getpri($1); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname($1)); + p->pri[0] = prim_pri; + p->pri[1] = sec_pri; +} + | CHAR RANGE CHAR { + u_int i; + struct __collate_st_char_pri *p; + + if ($3 <= $1) + yyerror("Illegal range %s -- %s", + charname($1), charname2($3)); + + for (i = $1; i <= $3; i++) { + p = getpri(i); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname(i)); + p->pri[0] = prim_pri; + p->pri[1] = sec_pri; + } +} + | chain { + struct __collate_st_chain_pri *c = getchain(curr_chain, NOTEXISTS); + c->pri[0] = prim_pri; + c->pri[1] = sec_pri; +} +sec_sub_item : CHAR { + struct __collate_st_char_pri *p = getpri($1); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname($1)); + p->pri[0] = prim_pri; + p->pri[1] = sec_pri++; +} + | CHAR RANGE CHAR { + u_int i; + struct __collate_st_char_pri *p; + + if ($3 <= $1) + yyerror("Illegal range %s -- %s", + charname($1), charname2($3)); + + for (i = $1; i <= $3; i++) { + p = getpri(i); + if (p->pri[0] >= 0) + yyerror("%s duplicated", charname(i)); + p->pri[0] = prim_pri; + p->pri[1] = sec_pri++; + } +} + | chain { + struct __collate_st_chain_pri *c = getchain(curr_chain, NOTEXISTS); + c->pri[0] = prim_pri; + c->pri[1] = sec_pri++; +} +; +%% +int +main(int ac, char **av) +{ + int ch, z; + + if ((charmapdb = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen charmapdb"); + if ((charmapdb2 = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen charmapdb"); + if ((largemapdb = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen largemapdb"); + if ((substdb[0] = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen substdb[0]"); + if ((chaindb = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen chaindb"); + /* -1 means an undefined priority, which we adjust after parsing */ + for (ch = 0; ch <= UCHAR_MAX; ch++) + for(z = 0; z < COLL_WEIGHTS_MAX; z++) + __collate_char_pri_table[ch].pri[z] = PRI_UNDEFINED; +#ifdef COLLATE_DEBUG + while((ch = getopt(ac, av, ":do:I:")) != -1) { +#else + while((ch = getopt(ac, av, ":o:I:")) != -1) { +#endif + switch (ch) + { +#ifdef COLLATE_DEBUG + case 'd': + debug++; + break; +#endif + case 'o': + out_file = optarg; + break; + + case 'I': + strlcpy(map_name, optarg, sizeof(map_name)); + break; + + default: + usage(); + } + } + ac -= optind; + av += optind; + if (ac > 0) { + if ((yyin = fopen(*av, "r")) == NULL) + err(EX_UNAVAILABLE, "can't open source file %s", *av); + } + yyparse(); + return 0; +} + +static struct __collate_st_char_pri * +getpri(int32_t c) +{ + DBT key, val; + struct __collate_st_char_pri *p; + int ret; + + if (c <= UCHAR_MAX) + return &__collate_char_pri_table[c]; + key.data = &c; + key.size = sizeof(int32_t); + if ((ret = largemapdb->get(largemapdb, &key, &val, 0)) < 0) + err(1, "getpri: Error getting %s", charname(c)); + if (ret != 0) { + struct __collate_st_char_pri *pn; + int z; + if ((pn = (struct __collate_st_char_pri *)malloc(sizeof(struct __collate_st_char_pri))) == NULL) + err(1, "getpri: malloc"); + for(z = 0; z < COLL_WEIGHTS_MAX; z++) + pn->pri[z] = PRI_UNDEFINED; + val.data = &pn; + val.size = sizeof(struct __collate_st_char_pri *); + if (largemapdb->put(largemapdb, &key, &val, 0) < 0) + err(1, "getpri: Error storing %s", charname(c)); + nlargemap++; + } + memcpy(&p, val.data, sizeof(struct __collate_st_char_pri *)); + return p; +} + +static struct __collate_st_char_pri * +haspri(int32_t c) +{ + DBT key, val; + struct __collate_st_char_pri *p; + int ret; + + if (c <= UCHAR_MAX) + return &__collate_char_pri_table[c]; + key.data = &c; + key.size = sizeof(int32_t); + if ((ret = largemapdb->get(largemapdb, &key, &val, 0)) < 0) + err(1, "haspri: Error getting %s", charname(c)); + if (ret != 0) + return NULL; + memcpy(&p, val.data, sizeof(struct __collate_st_char_pri *)); + return p; +} + +static struct __collate_st_chain_pri * +getchain(const wchar_t *wcs, int exists) +{ + DBT key, val; + struct __collate_st_chain_pri *p; + int ret; + + key.data = (void *)wcs; + key.size = __collate_wcsnlen(wcs, STR_LEN) * sizeof(wchar_t); + if ((ret = chaindb->get(chaindb, &key, &val, 0)) < 0) + err(1, "getchain: Error getting \"%s\"", showwcs(wcs, STR_LEN)); + if (ret != 0) { + struct __collate_st_chain_pri *pn; + int z; + if (exists > 0) + errx(1, "getchain: \"%s\" is not defined", showwcs(wcs, STR_LEN)); + if ((pn = (struct __collate_st_chain_pri *)malloc(sizeof(struct __collate_st_chain_pri))) == NULL) + err(1, "getchain: malloc"); + for(z = 0; z < COLL_WEIGHTS_MAX; z++) + pn->pri[z] = PRI_UNDEFINED; + bzero(pn->str, sizeof(pn->str)); + wcsncpy(pn->str, wcs, STR_LEN); + val.data = &pn; + val.size = sizeof(struct __collate_st_chain_pri *); + if (chaindb->put(chaindb, &key, &val, 0) < 0) + err(1, "getchain: Error storing \"%s\"", showwcs(wcs, STR_LEN)); + nchain++; + } else if (exists == 0) + errx(1, "getchain: \"%s\" already exists", showwcs(wcs, STR_LEN)); + memcpy(&p, val.data, sizeof(struct __collate_st_chain_pri *)); + return p; +} + +struct symbol * +getsymbol(const wchar_t *wcs, int exists) +{ + DBT key, val; + struct symbol *p; + int ret; + + key.data = (void *)wcs; + key.size = wcslen(wcs) * sizeof(wchar_t); + if ((ret = charmapdb->get(charmapdb, &key, &val, 0)) < 0) + err(1, "getsymbol: Error getting \"%s\"", showwcs(wcs, CHARMAP_SYMBOL_LEN)); + if (ret != 0) { + struct symbol *pn; + if (exists > 0) + errx(1, "getsymbol: \"%s\" is not defined", showwcs(wcs, CHARMAP_SYMBOL_LEN)); + if ((pn = (struct symbol *)malloc(sizeof(struct symbol))) == NULL) + err(1, "getsymbol: malloc"); + pn->val = PRI_UNDEFINED; + wcsncpy(pn->name, wcs, CHARMAP_SYMBOL_LEN); + val.data = &pn; + val.size = sizeof(struct symbol *); + if (charmapdb->put(charmapdb, &key, &val, 0) < 0) + err(1, "getsymbol: Error storing \"%s\"", showwcs(wcs, CHARMAP_SYMBOL_LEN)); + } else if (exists == 0) + errx(1, "getsymbol: \"%s\" already exists", showwcs(wcs, CHARMAP_SYMBOL_LEN)); + memcpy(&p, val.data, sizeof(struct symbol *)); + return p; +} + +static struct symbol * +getsymbolbychar(wchar_t wc) +{ + DBT key, val; + struct symbol *p; + int ret; + + key.data = &wc; + key.size = sizeof(wchar_t); + if ((ret = charmapdb2->get(charmapdb2, &key, &val, 0)) < 0) + err(1, "getsymbolbychar: Error getting Char 0x%02x", wc); + if (ret != 0) + errx(1, "getsymbolbychar: Char 0x%02x is not defined", wc); + memcpy(&p, val.data, sizeof(struct symbol *)); + return p; +} + +static struct symbol * +hassymbolbychar(wchar_t wc) +{ + DBT key, val; + struct symbol *p; + int ret; + + key.data = &wc; + key.size = sizeof(wchar_t); + if ((ret = charmapdb2->get(charmapdb2, &key, &val, 0)) < 0) + err(1, "hassymbolbychar: Error getting Char 0x%02x", wc); + if (ret != 0) + return NULL; + memcpy(&p, val.data, sizeof(struct symbol *)); + return p; +} + +static void +setsymbolbychar(struct symbol *s) +{ + DBT key, val; + struct symbol *p; + int ret; + + key.data = &s->u.wc; + key.size = sizeof(wchar_t); + val.data = &s; + val.size = sizeof(struct symbol *); + if (charmapdb2->put(charmapdb2, &key, &val, 0) < 0) + err(1, "setsymbolbychar: Error storing <%s>", showwcs(s->name, CHARMAP_SYMBOL_LEN)); +} + +struct symbol * +getstring(const wchar_t *wcs) +{ + DBT key, val; + struct symbol *p; + int ret; + + key.data = (void *)wcs; + key.size = wcslen(wcs) * sizeof(wchar_t); + if ((ret = stringdb->get(stringdb, &key, &val, 0)) < 0) + err(1, "getstring: Error getting \"%s\"", showwcs(wcs, STR_LEN)); + if (ret != 0) { + struct symbol *pn; + if ((pn = (struct symbol *)malloc(sizeof(struct symbol))) == NULL) + err(1, "getstring: malloc"); + pn->type = SYMBOL_STRING; + pn->val = prim_pri++; + wcsncpy(pn->u.str, wcs, STR_LEN); + val.data = &pn; + val.size = sizeof(struct symbol *); + if (stringdb->put(stringdb, &key, &val, 0) < 0) + err(1, "getstring: Error storing \"%s\"", showwcs(wcs, STR_LEN)); + } + memcpy(&p, val.data, sizeof(struct symbol *)); + return p; +} + +static void +makeforwardref(int i, const struct symbol *from, const struct symbol * to) +{ +} + +static void +putsubst(int32_t c, int i, const wchar_t *str) +{ + DBT key, val; + int ret; + wchar_t clean[STR_LEN]; + + if (!substdb[i]) + if ((substdb[i] = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL)) == NULL) + err(1, "dbopen substdb[%d]", i); + key.data = &c; + key.size = sizeof(int32_t); + bzero(clean, sizeof(clean)); + wcsncpy(clean, str, STR_LEN); + val.data = clean; + val.size = sizeof(clean); + if ((ret = substdb[i]->put(substdb[i], &key, &val, R_NOOVERWRITE)) < 0) + err(1, "putsubst: Error on %s", charname(c)); + if (ret != 0) + errx(1, "putsubst: Duplicate substitution of %s", charname(c)); + nsubst[i]++; +} + +static int +hassubst(int32_t c, int i) +{ + DBT key, val; + int ret; + + if (!substdb[i]) + return 0; + key.data = &c; + key.size = sizeof(int32_t); + if ((ret = substdb[i]->get(substdb[i], &key, &val, 0)) < 0) + err(1, "hassubst: Error getting %s", charname(c)); + return (ret == 0); +} + +static int +chainpricompar(const void *a, const void *b) +{ + return wcsncmp(((struct __collate_st_chain_pri *)a)->str, ((struct __collate_st_chain_pri *)b)->str, STR_LEN); +} + +static int +charpricompar(const void *a, const void *b) +{ + return ((struct __collate_st_large_char_pri *)a)->val - ((struct __collate_st_large_char_pri *)b)->val; +} + +static int +substcompar(const void *a, const void *b) +{ + return ((struct __collate_st_subst *)a)->val - ((struct __collate_st_subst *)b)->val; +} + +static const wchar_t * +__collate_wcsnchr(const wchar_t *s, wchar_t c, int len) +{ + while (*s && len > 0) { + if (*s == c) + return s; + s++; + len--; + } + return NULL; +} + +static int +__collate_wcsnlen(const wchar_t *s, int len) +{ + int n = 0; + while (*s && n < len) { + s++; + n++; + } + return n; +} + +static void +usage(void) +{ + fprintf(stderr, "usage: colldef [-o out_file] [-I map_dir] [filename]\n"); + exit(EX_USAGE); +} + +void +yyerror(const char *fmt, ...) +{ + va_list ap; + char msg[128]; + + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + errx(EX_UNAVAILABLE, "%s, near line %d", msg, line_no); +} + +char * +showwcs(const wchar_t *t, int len) +{ + static char buf[8* CHARMAP_SYMBOL_LEN]; + char *cp = buf; + + for(; *t && len > 0; len--, t++) { + if (*t >=32 && *t <= 126) + *cp++ = *t; + else { + sprintf(cp, "\\x{%02x}", *t); + cp += strlen(cp); + } + } + *cp = 0; + return buf; +} + +static char * +charname(wchar_t wc) +{ + static char buf[CHARMAP_SYMBOL_LEN + 1]; + struct symbol *s = hassymbolbychar(wc); + + if (s) + strcpy(buf, showwcs(s->name, CHARMAP_SYMBOL_LEN)); + else + sprintf(buf, "Char 0x%02x", wc); + return buf; +} + +static char * +charname2(wchar_t wc) +{ + static char buf[CHARMAP_SYMBOL_LEN + 1]; + struct symbol *s = hassymbolbychar(wc); + + if (s) + strcpy(buf, showwcs(s->name, CHARMAP_SYMBOL_LEN)); + else + sprintf(buf, "Char 0x%02x", wc); + return buf; +} + +#ifdef COLLATE_DEBUG +static char * +show(int c) +{ + static char buf[5]; + + if (c >=32 && c <= 126) + sprintf(buf, "'%c' ", c); + else + sprintf(buf, "\\x{%02x}", c); + return buf; +} + +static void +collate_print_tables(void) +{ + int i, z; + + printf("Info: p=%d s=%d f=0x%02x m=%d dc=%d up=%d us=%d pc=%d sc=%d cc=%d lc=%d\n", + info.directive[0], info.directive[1], + info.flags, info.chain_max_len, + info.directive_count, + info.undef_pri[0], info.undef_pri[1], + info.subst_count[0], info.subst_count[1], + info.chain_count, info.large_pri_count); + for(z = 0; z < info.directive_count; z++) { + if (info.subst_count[z] > 0) { + struct __collate_st_subst *p2 = __collate_substitute_table[z]; + if (z == 0 && (info.flags & COLLATE_SUBST_DUP)) + printf("Both substitute tables:\n"); + else + printf("Substitute table %d:\n", z); + for (i = info.subst_count[z]; i-- > 0; p2++) + printf("\t%s --> \"%s\"\n", + show(p2->val), + showwcs(p2->str, STR_LEN)); + } + } + if (info.chain_count > 0) { + printf("Chain priority table:\n"); + struct __collate_st_chain_pri *p2 = __collate_chain_pri_table; + for (i = info.chain_count; i-- > 0; p2++) { + printf("\t\"%s\" :", showwcs(p2->str, STR_LEN)); + for(z = 0; z < info.directive_count; z++) + printf(" %d", p2->pri[z]); + putchar('\n'); + } + } + printf("Char priority table:\n"); + { + struct __collate_st_char_pri *p2 = __collate_char_pri_table; + for (i = 0; i < UCHAR_MAX + 1; i++, p2++) { + printf("\t%s :", show(i)); + for(z = 0; z < info.directive_count; z++) + printf(" %d", p2->pri[z]); + putchar('\n'); + } + } + if (info.large_pri_count > 0) { + struct __collate_st_large_char_pri *p2 = __collate_large_char_pri_table; + printf("Large priority table:\n"); + for (i = info.large_pri_count; i-- > 0; p2++) { + printf("\t%s :", show(p2->val)); + for(z = 0; z < info.directive_count; z++) + printf(" %d", p2->pri.pri[z]); + putchar('\n'); + } + } +} +#endif diff --git a/adv_cmds/colldef/scan.l b/adv_cmds/colldef/scan.l new file mode 100644 index 0000000..ce14492 --- /dev/null +++ b/adv_cmds/colldef/scan.l @@ -0,0 +1,398 @@ +%x string s_name charmap defn nchar subs subs2 ldef elem +%{ +/*- + * Copyright (c) 1995 Alex Tatmanjants + * 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. + */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/colldef/scan.l,v 1.19 2002/08/23 04:18:26 ache Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include "collate.h" +#include "common.h" +#include "y.tab.h" + +int line_no = 1, save_no, fromsubs; +wchar_t buf0[BUFSIZE], *ptr; +wchar_t *buf = buf0; +wchar_t bufstr[BUFSIZE], *ptrsave; +FILE *map_fp; +YY_BUFFER_STATE main_buf, map_buf; +#ifdef FLEX_DEBUG +YYSTYPE yylval; +#endif /* FLEX_DEBUG */ +int yylex(void); +static int localedefmode = 0; +static orderpass = 0; +%} +%% +[ \t]+ ; +\" { ptr = buf; BEGIN(string); } +\< { + if(localedefmode) { + ptrsave = ptr; + ptr = buf = bufstr; + BEGIN(s_name); + } else { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '<'", + line_no); + *ptr++ = '<'; + } +} +\< { ptr = buf; fromsubs = 1; BEGIN(s_name); } +[,;] return *yytext; +forward { yylval.ch = DIRECTIVE_FORWARD; return ORDER_DIRECTIVE; } +backward { yylval.ch = DIRECTIVE_BACKWARD; return ORDER_DIRECTIVE; } +position { yylval.ch = DIRECTIVE_POSITION; return ORDER_DIRECTIVE; } +collating[-_]element return COLLATING_ELEMENT; +collating[-_]symbol return COLLATING_SYMBOL; +from return FROM; +\.\.\. return ELLIPSIS; +IGNORE return IGNORE; +UNDEFINED return UNDEFINED; +order[-_]start return ORDER_START; +order[-_]end { + char line[YY_BUF_SIZE]; + if (orderpass) + return ORDER_END; + /* The first pass only defined the left-most symbol. We reread the + * order lines, and forward references should now be resolved. */ + orderpass++; + YY_FLUSH_BUFFER; + rewind(yyin); + for(;;) { + if (fgets(line, sizeof(line), yyin) == NULL) + errx(EX_UNAVAILABLE, "EOF rescanning for order_start"); + if (*line == '#') + continue; + if (strstr(line, "order_start") != NULL) + break; + } + return ORDER_SECOND_PASS; +} +END[ \t]+LC_COLLATE return END_LC_COLLATE; +\n { + line_no++; + return '\n'; +} +\< { ptr = buf; BEGIN(elem); } +\< { ptr = buf; fromsubs = 0; BEGIN(s_name); } +<*>^#.*\n line_no++; +^\n line_no++; +\\\n line_no++; +\\t { yylval.ch = '\t'; return CHAR; } +\\n { yylval.ch = '\n'; return CHAR; } +\\b { yylval.ch = '\b'; return CHAR; } +\\f { yylval.ch = '\f'; return CHAR; } +\\v { yylval.ch = '\v'; return CHAR; } +\\r { yylval.ch = '\r'; return CHAR; } +\\a { yylval.ch = '\a'; return CHAR; } +\n { + line_no++; + BEGIN(INITIAL); + return '\n'; +} +\n { + line_no++; + if (map_fp != NULL) { + ptr = buf; + BEGIN(defn); + } + return '\n'; +} +[;,{}()] return *yytext; +substitute { BEGIN(subs); return SUBSTITUTE; } +LC_COLLATE { BEGIN(ldef); localedefmode++; return START_LC_COLLATE; } +with { BEGIN(subs2); return WITH; } +order return ORDER; +charmap BEGIN(charmap); +;[ \t]*\.\.\.[ \t]*; return RANGE; +\\([0-7]{3}) { + u_int v; + + sscanf(&yytext[1], "%o", &v); + yylval.ch = v; + return CHAR; +} +\\x\{([0-9a-fA-F]{2,8})\} { + u_int v; + + sscanf(&yytext[3], "%x", &v); + yylval.ch = v; + return CHAR; +} +\\x([0-9a-fA-F]{2}) { + u_int v; + + sscanf(&yytext[2], "%x", &v); + yylval.ch = v; + return CHAR; +} +\\. { yylval.ch = yytext[1]; return CHAR; } +. { yylval.ch = *(u_char *)yytext; return CHAR; } +^\n line_no++; +[ \t]+ { + if (ptr == buf) + errx(EX_UNAVAILABLE, "map expected near line %u of %s", + line_no, map_name); + *ptr = 0; + if (localedefmode && *buf == '<' && ptr[-1] == '>') { + if (ptr == buf + 2) + errx(EX_UNAVAILABLE, "map expected near line %u of %s", + line_no, map_name); + *--ptr = 0; + wcscpy(yylval.str, buf + 1); + } else + wcscpy(yylval.str, buf); + BEGIN(nchar); + return DEFN; +} +\/\/ { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", + line_no); + *ptr++ = '/'; +} +\/\> { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", + line_no); + *ptr++ = '>'; +} +\\\" { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", + line_no); + *ptr++ = '"'; +} +\> { + if (ptr == buf) + errx(EX_UNAVAILABLE, "non-empty name expected near line %u", + line_no); + *ptr = 0; + wcscpy(yylval.str, buf); + BEGIN(ldef); + return ELEM; +} +\> { + struct symbol *s; + + if (ptr == buf) + errx(EX_UNAVAILABLE, "non-empty name expected near line %u", + line_no); + *ptr = 0; + s = getsymbol(buf, EXISTS); + switch (s->type) { + case SYMBOL_CHAR: + break; + case SYMBOL_CHAIN: + errx(EX_UNAVAILABLE, "name <%s> is chain type near line %u", + showwcs(buf, CHARMAP_SYMBOL_LEN), line_no); + case SYMBOL_SYMBOL: + errx(EX_UNAVAILABLE, "name <%s> is symbol type near line %u", + showwcs(buf, CHARMAP_SYMBOL_LEN), line_no); + default: + errx(EX_UNAVAILABLE, "name <%s>: unknown symbol type (%d) near line %u", + showwcs(buf, CHARMAP_SYMBOL_LEN), s->type, line_no); + } + if (localedefmode) { + ptr = ptrsave; + buf = buf0; + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character <%s>", + line_no, showwcs(bufstr, CHARMAP_SYMBOL_LEN)); + *ptr++ = s->u.wc; + BEGIN(string); + } else { + yylval.ch = s->u.wc; + if (fromsubs) + BEGIN(subs); + else + BEGIN(INITIAL); + return CHAR; + } +} +\" { + *ptr = 0; + wcscpy(yylval.str, buf); + if (localedefmode) + BEGIN(ldef); + else + BEGIN(subs2); + return STRING; +} +. { + const char *s = (map_fp != NULL) ? map_name : "input"; + + if (!isascii(*yytext) || !isprint(*yytext)) + errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", + *yytext, line_no, s); + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", + line_no, s, *yytext); + *ptr++ = *yytext; +} +\\t { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", + line_no); + *ptr++ = '\t'; +} +\\b { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", + line_no); + *ptr++ = '\b'; +} +\\f { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", + line_no); + *ptr++ = '\f'; +} +\\v { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", + line_no); + *ptr++ = '\v'; +} +\\n { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", + line_no); + *ptr++ = '\n'; +} +\\r { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", + line_no); + *ptr++ = '\r'; +} +\\a { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", + line_no); + *ptr++ = '\a'; +} +\n { + const char *s = (map_fp != NULL) ? map_name : "input"; + + errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); +} +<> { + const char *s = (map_fp != NULL) ? map_name : "input"; + + errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); +} +\\x\{([0-9a-f]{2,8})\} { + u_int v; + + sscanf(&yytext[3], "%x", &v); + *ptr++ = v; +} +\\x([0-9a-f]{2}) { + u_int v; + + sscanf(&yytext[2], "%x", &v); + *ptr++ = v; +} +\\([0-7]{3}) { + u_int v; + + sscanf(&yytext[1], "%o", &v); + *ptr++ = v; +} +\\. { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", + line_no, yytext[1]); + *ptr++ = yytext[1]; +} +. { + if(ptr >= buf + BUFSIZE - 1) + errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", + line_no, *yytext); + *ptr++ = *yytext; +} +[^ \t\n]+ { + if(*yytext == '/') + strcpy(map_name, yytext); + else { + strcat(map_name, "/"); + strcat(map_name, yytext); + } + if((map_fp = fopen(map_name, "r")) == NULL) + err(EX_UNAVAILABLE, "can't open 'charmap' file %s", + map_name); + save_no = line_no; + line_no = 1; + map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); + main_buf = YY_CURRENT_BUFFER; + yy_switch_to_buffer(map_buf); + ptr = buf; + BEGIN(defn); +} +\n { + errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", + line_no); +} +<> { + errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", + line_no); +} +<> { + if(map_fp != NULL) { + if (ptr != buf) + errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); + yy_switch_to_buffer(main_buf); + yy_delete_buffer(map_buf); + fclose(map_fp); + map_fp = NULL; + line_no = save_no; + if (localedefmode) + BEGIN(ldef); + else + BEGIN(INITIAL); + } else + yyterminate(); +} +%% +#ifdef FLEX_DEBUG +main() +{ + while(yylex()) + ; + return 0; +} +#endif /* FLEX_DEBUG */ diff --git a/adv_cmds/finger/extern.h b/adv_cmds/finger/extern.h new file mode 100644 index 0000000..7b8f29c --- /dev/null +++ b/adv_cmds/finger/extern.h @@ -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. + * + * @(#)extern.h 8.2 (Berkeley) 4/28/95 + * $FreeBSD: src/usr.bin/finger/extern.h,v 1.10 2005/09/19 10:11:46 dds Exp $ + */ + +#ifndef _EXTERN_H_ +#define _EXTERN_H_ + +extern char tbuf[1024]; /* Temp buffer for anybody. */ +extern int entries; /* Number of people. */ +extern DB *db; /* Database. */ +extern int d_first; +extern sa_family_t family; +extern int gflag; +extern int lflag; +extern time_t now; +extern int oflag; +extern int pplan; /* don't show .plan/.project */ +#ifndef __APPLE__ +extern int Tflag; +#endif +extern int invoker_root; /* Invoked by root */ + +void enter_lastlog(PERSON *); +PERSON *enter_person(struct passwd *); +void enter_where(struct utmpx *, PERSON *); +PERSON *find_person(const char *); +int hide(struct passwd *); +void lflag_print(void); +int match(struct passwd *, const char *); +void netfinger(char *); +PERSON *palloc(void); +char *prphone(char *); +void sflag_print(void); +int show_text(const char *, const char *, const char *); + +#endif /* !_EXTERN_H_ */ diff --git a/adv_cmds/finger/finger.1 b/adv_cmds/finger/finger.1 new file mode 100644 index 0000000..4fbdfeb --- /dev/null +++ b/adv_cmds/finger/finger.1 @@ -0,0 +1,257 @@ +.\" Copyright (c) 1989, 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. +.\" +.\" @(#)finger.1 8.3 (Berkeley) 5/5/94 +.\" $FreeBSD: src/usr.bin/finger/finger.1,v 1.31 2005/09/19 10:11:46 dds Exp $ +.\" +.Dd July 17, 2004 +.Dt FINGER 1 +.Os +.Sh NAME +.Nm finger +.Nd user information lookup program +.Sh SYNOPSIS +.Nm +.Op Fl 46gklmpsho +.Op Ar user ...\& +.Op Ar user@host ...\& +.Sh DESCRIPTION +The +.Nm +utility displays information about the system users. +.Pp +Options are: +.Bl -tag -width indent +.It Fl 4 +Forces +.Nm +to use IPv4 addresses only. +.It Fl 6 +Forces +.Nm +to use IPv6 addresses only. +.It Fl g +This option restricts the gecos output to only the users' real +name. +It also has the side-effect of restricting the output +of the remote host when used in conjunction with the +.Fl h +option. +.It Fl h +When used in conjunction with the +.Fl s +option, the name of the remote host is displayed instead of the office +location and office phone. +.It Fl k +Disable all use of +.Xr utmpx 5 . +.It Fl l +Produce a multi-line format displaying all of the information +described for the +.Fl s +option as well as the user's home directory, home phone number, login +shell, mail status, and the contents of the files +.Pa .forward , +.Pa .plan , +.Pa .project +and +.Pa .pubkey +from the user's home directory. +.Pp +If idle time is at least a minute and less than a day, it is +presented in the form ``hh:mm''. +Idle times greater than a day are presented as ``d day[s]hh:mm''. +.Pp +Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''. +Numbers specified as ten or seven digits are printed as the appropriate +subset of that string. +Numbers specified as five digits are printed as ``xN-NNNN''. +Numbers specified as four digits are printed as ``xNNNN''. +.Pp +If write permission is denied to the device, the phrase ``(messages off)'' +is appended to the line containing the device name. +One entry per user is displayed with the +.Fl l +option; if a user is logged on multiple times, terminal information +is repeated once per login. +.Pp +Mail status is shown as ``No Mail.'' if there is no mail at all, ``Mail +last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked at their +mailbox since new mail arriving, or ``New mail received ...'', ``Unread +since ...'' if they have new mail. +.It Fl m +Prevent matching of +.Ar user +names. +.Ar User +is usually a login name; however, matching will also be done on the +users' real names, unless the +.Fl m +option is supplied. +All name matching performed by +.Nm +is case insensitive. +.It Fl o +When used in conjunction with the +.Fl s +option, the office location and office phone information is displayed +instead of the name of the remote host. +.It Fl p +Prevent +the +.Fl l +option of +.Nm +from displaying the contents of the +.Pa .forward , +.Pa .plan , +.Pa .project +and +.Pa .pubkey +files. +.It Fl s +Display the user's login name, real name, terminal name and write +status (as a ``*'' before the terminal name if write permission is +denied), idle time, login time, and either office location and office +phone number, or the remote host. +If +.Fl o +is given, the office location and office phone number is printed +(the default). +If +.Fl h +is given, the remote host is printed instead. +.Pp +Idle time is in minutes if it is a single integer, hours and minutes +if a ``:'' is present, or days if a ``d'' is present. +If it is an +.Dq * , +the login time indicates the time of last login. +Login time is displayed as the day name if less than 6 days, else month, day; +hours and minutes, unless more than six months ago, in which case the year +is displayed rather than the hours and minutes. +.Pp +Unknown devices as well as nonexistent idle and login times are +displayed as single asterisks. +.El +.Pp +If no options are specified, +.Nm +defaults to the +.Fl l +style output if operands are provided, otherwise to the +.Fl s +style. +Note that some fields may be missing, in either format, if information +is not available for them. +.Pp +If no arguments are specified, +.Nm +will print an entry for each user currently logged into the system. +.Pp +The +.Nm +utility may be used to look up users on a remote machine. +The format is to specify a +.Ar user +as +.Dq Li user@host , +or +.Dq Li @host , +where the default output +format for the former is the +.Fl l +style, and the default output format for the latter is the +.Fl s +style. +The +.Fl l +option is the only option that may be passed to a remote machine. +.Pp +If the file +.Pa .nofinger +exists in the user's home directory, +and the program is not run with superuser privileges, +.Nm +behaves as if the user in question does not exist. +.Pp +The optional +.Xr finger.conf 5 +configuration file can be used to specify aliases. +Since +.Nm +is invoked by +.Xr fingerd 8 , +aliases will work for both local and network queries. +.Sh ENVIRONMENT +The +.Nm +utility utilizes the following environment variable, if it exists: +.Bl -tag -width Fl +.It Ev FINGER +This variable may be set with favored options to +.Nm . +.El +.Sh FILES +.Bl -tag -width /var/log/lastlog -compact +.It Pa /etc/finger.conf +alias definition data base +.It Pa /var/log/lastlog +last login data base +.El +.Sh SEE ALSO +.Xr chpass 1 , +.Xr w 1 , +.Xr who 1 , +.Xr finger.conf 5 , +.Xr fingerd 8 +.Rs +.%A D. Zimmerman +.%T The Finger User Information Protocol +.%R RFC 1288 +.%D December, 1991 +.Re +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . +.Sh BUGS +The current FINGER protocol RFC requires that the client keep the connection +fully open until the server closes. +This prevents the use of the optimal +three-packet T/TCP exchange. +(Servers which depend on this requirement are +bogus but have nonetheless been observed in the Internet at large.) +.Pp +The +.Nm +utility does not recognize multibyte characters. diff --git a/adv_cmds/finger/finger.c b/adv_cmds/finger/finger.c new file mode 100644 index 0000000..0cbb887 --- /dev/null +++ b/adv_cmds/finger/finger.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + */ + +/* + * Luke Mewburn added the following on 940622: + * - mail status ("No Mail", "Mail read:...", or "New Mail ..., + * Unread since ...".) + * - 4 digit phone extensions (3210 is printed as x3210.) + * - host/office toggling in short format with -h & -o. + * - short day names (`Tue' printed instead of `Jun 21' if the + * login time is < 6 days. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/finger/finger.c,v 1.36 2005/09/19 10:11:46 dds Exp $"); + +/* + * Finger prints out information about users. It is not portable since + * certain fields (e.g. the full user name, office, and phone numbers) are + * extracted from the gecos field of the passwd file which other UNIXes + * may not have or may use for other things. + * + * There are currently two output formats; the short format is one line + * per user and displays login name, tty, login time, real name, idle time, + * and either remote host information (default) or office location/phone + * number, depending on if -h or -o is used respectively. + * The long format gives the same information (in a more legible format) as + * well as home directory, shell, mail info, and .plan/.project files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "finger.h" +#include "pathnames.h" + +DB *db; +time_t now; +int entries, gflag, kflag, lflag, mflag, pplan, sflag, oflag, Tflag; +sa_family_t family = PF_UNSPEC; +int d_first = -1; +char tbuf[1024]; +int invoker_root = 0; + +static void loginlist(void); +static int option(int, char **); +static void usage(void); +static void userlist(int, char **); + +static int +option(int argc, char **argv) +{ + int ch; + + optind = 1; /* reset getopt */ + +#ifdef __APPLE__ + while ((ch = getopt(argc, argv, "46gklmpsho")) != -1) +#else + while ((ch = getopt(argc, argv, "46gklmpshoT")) != -1) +#endif + switch(ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'g': + gflag = 1; + break; + case 'k': + kflag = 1; /* keep going without utmpx */ + break; + case 'l': + lflag = 1; /* long format */ + break; + case 'm': + mflag = 1; /* force exact match of names */ + break; + case 'p': + pplan = 1; /* don't show .plan/.project */ + break; + case 's': + sflag = 1; /* short format */ + break; + case 'h': + oflag = 0; /* remote host info */ + break; + case 'o': + oflag = 1; /* office info */ + break; +#ifndef __APPLE__ + case 'T': + Tflag = 1; /* disable T/TCP */ + break; +#endif + case '?': + default: + usage(); + } + + return optind; +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: finger [-46gklmpshoT] [user ...] [user@host ...]\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int envargc, argcnt; + char *envargv[3]; + struct passwd *pw; + static char myname[] = "finger"; + + if (getuid() == 0 || geteuid() == 0) { + invoker_root = 1; + if ((pw = getpwnam(UNPRIV_NAME)) && pw->pw_uid > 0) { + setgid(pw->pw_gid); + setuid(pw->pw_uid); + } else { + setgid(UNPRIV_UGID); + setuid(UNPRIV_UGID); + } + } + + (void) setlocale(LC_ALL, ""); + + /* remove this line to get remote host */ + oflag = 1; /* default to old "office" behavior */ + + /* + * Process environment variables followed by command line arguments. + */ + if ((envargv[1] = getenv("FINGER"))) { + envargc = 2; + envargv[0] = myname; + envargv[2] = NULL; + (void) option(envargc, envargv); + } + + argcnt = option(argc, argv); + argc -= argcnt; + argv += argcnt; + + (void)time(&now); + setpassent(1); + if (!*argv) { + /* + * Assign explicit "small" format if no names given and -l + * not selected. Force the -s BEFORE we get names so proper + * screening will be done. + */ + if (!lflag) + sflag = 1; /* if -l not explicit, force -s */ + loginlist(); + if (entries == 0) + (void)printf("No one logged on.\n"); + } else { + userlist(argc, argv); + /* + * Assign explicit "large" format if names given and -s not + * explicitly stated. Force the -l AFTER we get names so any + * remote finger attempts specified won't be mishandled. + */ + if (!sflag) + lflag = 1; /* if -s not explicit, force -l */ + } + if (entries) { + if (lflag) + lflag_print(); + else + sflag_print(); + } + return (0); +} + +static void +loginlist(void) +{ + PERSON *pn; + DBT data, key; + struct passwd *pw; + struct utmpx *user; + int r, sflag1; + char name[_UTX_USERSIZE + 1]; + + if (kflag) + errx(1, "can't list logins without reading utmpx"); + + setutxent(); + name[_UTX_USERSIZE] = '\0'; + while ((user = getutxent()) != NULL) { + if (!user->ut_user[0] || user->ut_type != USER_PROCESS) + continue; + if ((pn = find_person(user->ut_user)) == NULL) { + bcopy(user->ut_user, name, _UTX_USERSIZE); + if ((pw = getpwnam(name)) == NULL) + continue; + if (hide(pw)) + continue; + pn = enter_person(pw); + } + enter_where(user, pn); + } + endutxent(); + if (db && lflag) + for (sflag1 = R_FIRST;; sflag1 = R_NEXT) { + PERSON *tmp; + + r = (*db->seq)(db, &key, &data, sflag1); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); + } +} + +static void +userlist(int argc, char **argv) +{ + PERSON *pn; + DBT data, key; + struct utmpx *user; + struct passwd *pw; + int r, sflag1, *used, *ip; + char **ap, **nargv, **np, **p; + FILE *conf_fp; + char conf_alias[LINE_MAX]; + char *conf_realname; + int conf_length; + + if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL || + (used = calloc(argc, sizeof(int))) == NULL) + err(1, NULL); + + /* Pull out all network requests. */ + for (ap = p = argv, np = nargv; *p; ++p) + if (index(*p, '@')) + *np++ = *p; + else + *ap++ = *p; + + *np++ = NULL; + *ap++ = NULL; + + if (!*argv) + goto net; + + /* + * Mark any arguments beginning with '/' as invalid so that we + * don't accidently confuse them with expansions from finger.conf + */ + for (p = argv, ip = used; *p; ++p, ++ip) + if (**p == '/') { + *ip = 1; + warnx("%s: no such user", *p); + } + + /* + * Traverse the finger alias configuration file of the form + * alias:(user|alias), ignoring comment lines beginning '#'. + */ + if ((conf_fp = fopen(_PATH_FINGERCONF, "r")) != NULL) { + while(fgets(conf_alias, sizeof(conf_alias), conf_fp) != NULL) { + conf_length = strlen(conf_alias); + if (*conf_alias == '#' || conf_alias[--conf_length] != '\n') + continue; + conf_alias[conf_length] = '\0'; /* Remove trailing LF */ + if ((conf_realname = strchr(conf_alias, ':')) == NULL) + continue; + *conf_realname = '\0'; /* Replace : with NUL */ + for (p = argv; *p; ++p) { + if (strcmp(*p, conf_alias) == 0) { + if ((*p = strdup(conf_realname+1)) == NULL) { + err(1, NULL); + } + } + } + } + (void)fclose(conf_fp); + } + + /* + * Traverse the list of possible login names and check the login name + * and real name against the name specified by the user. If the name + * begins with a '/', try to read the file of that name instead of + * gathering the traditional finger information. + */ + if (mflag) + for (p = argv, ip = used; *p; ++p, ++ip) { + if (**p != '/' || *ip == 1 || !show_text("", *p, "")) { + if (((pw = getpwnam(*p)) != NULL) && !hide(pw)) + enter_person(pw); + else if (!*ip) + warnx("%s: no such user", *p); + } + } + else { + while ((pw = getpwent()) != NULL) { + for (p = argv, ip = used; *p; ++p, ++ip) + if (**p == '/' && *ip != 1 + && show_text("", *p, "")) + *ip = 1; + else if (match(pw, *p) && !hide(pw)) { + enter_person(pw); + *ip = 1; + } + } + for (p = argv, ip = used; *p; ++p, ++ip) + if (!*ip) + warnx("%s: no such user", *p); + } + + /* Handle network requests. */ +net: for (p = nargv; *p;) { + netfinger(*p++); + if (*p || entries) + printf("\n"); + } + + if (entries == 0) + return; + + if (kflag) + return; + + /* + * Scan thru the list of users currently logged in, saving + * appropriate data whenever a match occurs. + */ + setutxent(); + while ((user = getutxent()) != NULL) { + if (!user->ut_user && user->ut_type != USER_PROCESS) + continue; + if ((pn = find_person(user->ut_user)) == NULL) + continue; + enter_where(user, pn); + } + endutxent(); + if (db) + for (sflag1 = R_FIRST;; sflag1 = R_NEXT) { + PERSON *tmp; + + r = (*db->seq)(db, &key, &data, sflag1); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); + } +} diff --git a/adv_cmds/finger/finger.conf.5 b/adv_cmds/finger/finger.conf.5 new file mode 100644 index 0000000..83ebc5b --- /dev/null +++ b/adv_cmds/finger/finger.conf.5 @@ -0,0 +1,91 @@ +.\" Copyright (c) 2000 Mark Knight +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/usr.bin/finger/finger.conf.5,v 1.6 2005/02/09 18:04:22 ru Exp $ +.\" +.Dd August 16, 2000 +.Dt FINGER.CONF 5 +.Os +.Sh NAME +.Nm finger.conf +.Nd +.Xr finger 1 +alias configuration file +.Sh DESCRIPTION +The optional +.Nm +file is used to provide aliases that can be fingered by local +and network users. +This may be useful where a user's login name is not the same +as their preferred mail address, or for providing virtual login names +than can be fingered. +.Pp +Lines beginning with ``#'' are comments. +Other lines must consist of an +alias name and a target name separated by a colon. +A target name should be either a user, a forward +reference to another alias or the path of a world readable file. +.Pp +Where an alias points to a file, the contents of that file will be displayed +when the alias is fingered. +.Sh FILES +.Bl -tag -width /etc/finger.conf -compact +.It Pa /etc/finger.conf +.Xr finger 1 +alias definition data base +.El +.Sh EXAMPLES +.Bd -literal +# /etc/finger.conf alias definition file +# +# Format alias:(user|alias) +# +# Individual aliases +# +markk:mkn +john.smith:dev329 +john:dev329 +sue:/etc/finger/sue.txt +# +# Network status message +# +status:/usr/local/etc/status.txt +# +# Administrative redirects +# +root:admin +postmaster:admin +abuse:admin +# +# For the time being, 'sod' is sysadmin. +# +admin:sod +.Ed +.Sh SEE ALSO +.Xr finger 1 +.Sh HISTORY +Support for the +.Nm +file was submitted by Mark Knight and first appeared in +.Fx 4.2 . diff --git a/adv_cmds/finger/finger.h b/adv_cmds/finger/finger.h new file mode 100644 index 0000000..19b30fb --- /dev/null +++ b/adv_cmds/finger/finger.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + * + * @(#)finger.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/finger/finger.h,v 1.5 2004/03/14 06:43:34 jmallett Exp $ + */ + +#ifndef _FINGER_H_ +#define _FINGER_H_ + +typedef struct person { + uid_t uid; /* user id */ + char *dir; /* user's home directory */ + char *homephone; /* pointer to home phone no. */ + char *name; /* login name */ + char *office; /* pointer to office name */ + char *officephone; /* pointer to office phone no. */ + char *realname; /* pointer to full name */ + char *shell; /* user's shell */ + time_t mailread; /* last time mail was read */ + time_t mailrecv; /* last time mail was received */ + struct where *whead, *wtail; /* list of where user is or has been */ +} PERSON; + +enum status { LASTLOG, LOGGEDIN }; + +typedef struct where { + struct where *next; /* next place user is or has been */ + enum status info; /* type/status of request */ + short writable; /* tty is writable */ + time_t loginat; /* time of (last) login */ + time_t idletime; /* how long idle (if logged in) */ + char tty[_UTX_LINESIZE+1]; /* null terminated tty line */ + char host[_UTX_HOSTSIZE+1]; /* null terminated remote host name */ +} WHERE; + +#define UNPRIV_NAME "nobody" /* Preferred privilege level */ +#define UNPRIV_UGID 32767 /* Default uid and gid */ +#define OUTPUT_MAX 100000 /* Do not keep listinging forever */ +#define TIME_LIMIT 360 /* Do not keep listinging forever */ + +#define UT_NAMESIZE 8 /* old utmp.h value */ + +#include "extern.h" + +#endif /* !_FINGER_H_ */ diff --git a/adv_cmds/finger/lprint.c b/adv_cmds/finger/lprint.c new file mode 100644 index 0000000..6e9b42d --- /dev/null +++ b/adv_cmds/finger/lprint.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/finger/lprint.c,v 1.25 2004/03/14 06:43:34 jmallett Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "finger.h" +#include "pathnames.h" + +#define LINE_LEN 80 +#define TAB_LEN 8 /* 8 spaces between tabs */ + +static int demi_print(char *, int); +static void lprint(PERSON *); +static void vputc(unsigned char); + +void +lflag_print(void) +{ + PERSON *pn; + int sflag, r; + PERSON *tmp; + DBT data, key; + + for (sflag = R_FIRST;; sflag = R_NEXT) { + r = (*db->seq)(db, &key, &data, sflag); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + pn = tmp; + if (sflag != R_FIRST) + putchar('\n'); + lprint(pn); + if (!pplan) { + (void)show_text(pn->dir, + _PATH_FORWARD, "Mail forwarded to"); + (void)show_text(pn->dir, _PATH_PROJECT, "Project"); + if (!show_text(pn->dir, _PATH_PLAN, "Plan")) + (void)printf("No Plan.\n"); + (void)show_text(pn->dir, + _PATH_PUBKEY, "Public key"); + } + } +} + +static void +lprint(PERSON *pn) +{ + struct tm *delta; + WHERE *w; + int cpr, len, maxlen; + struct tm *tp; + int oddfield; + char t[80]; + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + /* + * long format -- + * login name + * real name + * home directory + * shell + * office, office phone, home phone if available + * mail status + */ + (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", + pn->name, pn->realname, pn->dir); + (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); + + if (gflag) + goto no_gecos; + /* + * try and print office, office phone, and home phone on one line; + * if that fails, do line filling so it looks nice. + */ +#define OFFICE_TAG "Office" +#define OFFICE_PHONE_TAG "Office Phone" + oddfield = 0; + if (pn->office && pn->officephone && + strlen(pn->office) + strlen(pn->officephone) + + sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { + (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", + OFFICE_TAG, pn->office, prphone(pn->officephone)); + oddfield = demi_print(tbuf, oddfield); + } else { + if (pn->office) { + (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", + OFFICE_TAG, pn->office); + oddfield = demi_print(tbuf, oddfield); + } + if (pn->officephone) { + (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", + OFFICE_PHONE_TAG, prphone(pn->officephone)); + oddfield = demi_print(tbuf, oddfield); + } + } + if (pn->homephone) { + (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", + prphone(pn->homephone)); + oddfield = demi_print(tbuf, oddfield); + } + if (oddfield) + putchar('\n'); + +no_gecos: + /* + * long format con't: + * if logged in + * terminal + * idle time + * if messages allowed + * where logged in from + * if not logged in + * when last logged in + */ + /* find out longest device name for this user for formatting */ + for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) + if ((len = strlen(w->tty)) > maxlen) + maxlen = len; + /* find rest of entries for user */ + for (w = pn->whead; w != NULL; w = w->next) { + if (w->info == LOGGEDIN) { + tp = localtime(&w->loginat); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R (%Z)" : "%a %b %e %R (%Z)", + tp); + cpr = printf("On since %s on %s", t, w->tty); + /* + * idle time is tough; if have one, print a comma, + * then spaces to pad out the device name, then the + * idle time. Follow with a comma if a remote login. + */ + delta = gmtime(&w->idletime); + if (w->idletime != -1 && (delta->tm_yday || + delta->tm_hour || delta->tm_min)) { + cpr += printf("%-*s idle ", + maxlen - (int)strlen(w->tty) + 1, ","); + if (delta->tm_yday > 0) { + cpr += printf("%d day%s ", + delta->tm_yday, + delta->tm_yday == 1 ? "" : "s"); + } + cpr += printf("%d:%02d", + delta->tm_hour, delta->tm_min); + if (*w->host) { + putchar(','); + ++cpr; + } + } + if (!w->writable) + cpr += printf(" (messages off)"); + } else if (w->loginat == 0) { + cpr = printf("Never logged in."); + } else { + tp = localtime(&w->loginat); + if (now - w->loginat > 86400 * 365 / 2) { + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + } else { + strftime(t, sizeof(t), + d_first ? "%a %e %b %R (%Z)" : + "%a %b %e %R (%Z)", + tp); + } + cpr = printf("Last login %s on %s", t, w->tty); + } + if (*w->host) { + if (LINE_LEN < (cpr + 6 + strlen(w->host))) + (void)printf("\n "); + (void)printf(" from %s", w->host); + } + putchar('\n'); + } + if (pn->mailrecv == -1) + printf("No Mail.\n"); + else if (pn->mailrecv > pn->mailread) { + tp = localtime(&pn->mailrecv); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf("New mail received %s\n", t); + tp = localtime(&pn->mailread); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf(" Unread since %s\n", t); + } else { + tp = localtime(&pn->mailread); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf("Mail last read %s\n", t); + } +} + +static int +demi_print(char *str, int oddfield) +{ + static int lenlast; + int lenthis, maxlen; + + lenthis = strlen(str); + if (oddfield) { + /* + * We left off on an odd number of fields. If we haven't + * crossed the midpoint of the screen, and we have room for + * the next field, print it on the same line; otherwise, + * print it on a new line. + * + * Note: we insist on having the right hand fields start + * no less than 5 tabs out. + */ + maxlen = 5 * TAB_LEN; + if (maxlen < lenlast) + maxlen = lenlast; + if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + + lenthis) <= LINE_LEN) { + while(lenlast < (4 * TAB_LEN)) { + putchar('\t'); + lenlast += TAB_LEN; + } + (void)printf("\t%s\n", str); /* force one tab */ + } else { + (void)printf("\n%s", str); /* go to next line */ + oddfield = !oddfield; /* this'll be undone below */ + } + } else + (void)printf("%s", str); + oddfield = !oddfield; /* toggle odd/even marker */ + lenlast = lenthis; + return(oddfield); +} + +int +show_text(const char *directory, const char *file_name, const char *header) +{ + struct stat sb; + FILE *fp; + int ch, cnt; + char *p, lastc; + int fd, nr; + + lastc = '\0'; + + (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); + if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || + sb.st_size == 0) + return(0); + + /* If short enough, and no newlines, show it on a single line.*/ + if (sb.st_size <= LINE_LEN - strlen(header) - 5) { + nr = read(fd, tbuf, sizeof(tbuf)); + if (nr <= 0) { + (void)close(fd); + return(0); + } + for (p = tbuf, cnt = nr; cnt--; ++p) + if (*p == '\n') + break; + if (cnt <= 1) { + if (*header != '\0') + (void)printf("%s: ", header); + for (p = tbuf, cnt = nr; cnt--; ++p) + if (*p != '\r') + vputc(lastc = *p); + if (lastc != '\n') + (void)putchar('\n'); + (void)close(fd); + return(1); + } + else + (void)lseek(fd, 0L, SEEK_SET); + } + if ((fp = fdopen(fd, "r")) == NULL) + return(0); + if (*header != '\0') + (void)printf("%s:\n", header); + while ((ch = getc(fp)) != EOF) + if (ch != '\r') + vputc(lastc = ch); + if (lastc != '\n') + (void)putchar('\n'); + (void)fclose(fp); + return(1); +} + +static void +vputc(unsigned char ch) +{ + int meta; + + if (!isprint(ch) && !isascii(ch)) { + (void)putchar('M'); + (void)putchar('-'); + ch = toascii(ch); + meta = 1; + } else + meta = 0; + if (isprint(ch) || (!meta && (ch == ' ' || ch == '\t' || ch == '\n'))) + (void)putchar(ch); + else { + (void)putchar('^'); + (void)putchar(ch == '\177' ? '?' : ch | 0100); + } +} diff --git a/adv_cmds/finger/net.c b/adv_cmds/finger/net.c new file mode 100644 index 0000000..cf0699d --- /dev/null +++ b/adv_cmds/finger/net.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)net.c 8.4 (Berkeley) 4/28/95"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/finger/net.c,v 1.23 2004/05/16 22:08:15 stefanf Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "finger.h" + +static void cleanup(int sig); +static int do_protocol(const char *name, const struct addrinfo *ai); +static void trying(const struct addrinfo *ai); + +void +netfinger(char *name) +{ + int error, multi; + char *host; + struct addrinfo *ai, *ai0; + static struct addrinfo hint; + + host = strrchr(name, '@'); + if (host == 0) + return; + *host++ = '\0'; + signal(SIGALRM, cleanup); + alarm(TIME_LIMIT); + + hint.ai_flags = AI_CANONNAME; + hint.ai_family = family; + hint.ai_socktype = SOCK_STREAM; + + error = getaddrinfo(host, "finger", &hint, &ai0); + if (error) { + warnx("%s: %s", host, gai_strerror(error)); + return; + } + + multi = (ai0->ai_next) != 0; + + /* ai_canonname may not be filled in if the user specified an IP. */ + if (ai0->ai_canonname == 0) + printf("[%s]\n", host); + else + printf("[%s]\n", ai0->ai_canonname); + + for (ai = ai0; ai != 0; ai = ai->ai_next) { + if (multi) + trying(ai); + + error = do_protocol(name, ai); + if (!error) + break; + } + alarm(0); + freeaddrinfo(ai0); +} + +static int +do_protocol(const char *name, const struct addrinfo *ai) +{ + int cnt, line_len, s; + FILE *fp; + int c, lastc; + struct iovec iov[3]; + struct msghdr msg; + static char slash_w[] = "/W "; + static char neteol[] = "\r\n"; + + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s < 0) { + warn("socket(%d, %d, %d)", ai->ai_family, ai->ai_socktype, + ai->ai_protocol); + return -1; + } + + msg.msg_name = (void *)ai->ai_addr; + msg.msg_namelen = ai->ai_addrlen; + msg.msg_iov = iov; + msg.msg_iovlen = 0; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + /* -l flag for remote fingerd */ + if (lflag) { + iov[msg.msg_iovlen].iov_base = slash_w; + iov[msg.msg_iovlen++].iov_len = 3; + } + /* send the name followed by */ + iov[msg.msg_iovlen].iov_base = strdup(name); + iov[msg.msg_iovlen++].iov_len = strlen(name); + iov[msg.msg_iovlen].iov_base = neteol; + iov[msg.msg_iovlen++].iov_len = 2; + +#ifdef __APPLE__ + if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { +#else + /* + * -T disables data-on-SYN: compatibility option to finger broken + * hosts. Also, the implicit-open API is broken on IPv6, so do + * the explicit connect there, too. + */ + if ((Tflag || ai->ai_addr->sa_family == AF_INET6) + && connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { +#endif + warn("connect"); + close(s); + return -1; + } + + if (sendmsg(s, &msg, 0) < 0) { + warn("sendmsg"); + close(s); + return -1; + } + + /* + * Read from the remote system; once we're connected, we assume some + * data. If none arrives, we hang until the user interrupts. + * + * If we see a or a with the high bit set, treat it as + * a newline; if followed by a newline character, only output one + * newline. + * + * Otherwise, all high bits are stripped; if it isn't printable and + * it isn't a space, we can simply set the 7th bit. Every ASCII + * character with bit 7 set is printable. + */ + lastc = 0; + if ((fp = fdopen(s, "r")) != NULL) { + cnt = 0; + line_len = 0; + while ((c = getc(fp)) != EOF) { + if (++cnt > OUTPUT_MAX) { + printf("\n\n Output truncated at %d bytes...\n", + cnt - 1); + break; + } + if (c == 0x0d) { + if (lastc == '\r') /* ^M^M - skip dupes */ + continue; + c = '\n'; + lastc = '\r'; + } else { + if (!isprint(c) && !isspace(c)) { + c &= 0x7f; + c |= 0x40; + } + if (lastc != '\r' || c != '\n') + lastc = c; + else { + lastc = '\n'; + continue; + } + } + putchar(c); + if (c != '\n' && ++line_len > _POSIX2_LINE_MAX) { + putchar('\\'); + putchar('\n'); + lastc = '\r'; + } + if (lastc == '\n' || lastc == '\r') + line_len = 0; + } + if (ferror(fp)) { + /* + * Assume that whatever it was set errno... + */ + warn("reading from network"); + } + if (lastc != '\n') + putchar('\n'); + + fclose(fp); + } + return 0; +} + +static void +trying(const struct addrinfo *ai) +{ + char buf[NI_MAXHOST]; + + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, buf, sizeof buf, + (char *)0, 0, NI_NUMERICHOST) != 0) + return; /* XXX can't happen */ + + printf("Trying %s...\n", buf); +} + +void +cleanup(int sig __unused) +{ +#define ERRSTR "Timed out.\n" + write(STDERR_FILENO, ERRSTR, sizeof ERRSTR); + exit(1); +} + diff --git a/adv_cmds/finger/pathnames.h b/adv_cmds/finger/pathnames.h new file mode 100644 index 0000000..160252d --- /dev/null +++ b/adv_cmds/finger/pathnames.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2000 Mark Knight + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/usr.bin/finger/pathnames.h,v 1.5 2001/07/30 16:50:47 yar Exp $ + */ + +#ifndef PATHNAMES_H + +#define _PATH_FORWARD ".forward" +#define _PATH_NOFINGER ".nofinger" +#define _PATH_PLAN ".plan" +#define _PATH_PROJECT ".project" +#define _PATH_PUBKEY ".pubkey" + +#ifndef _PATH_FINGERCONF +#define _PATH_FINGERCONF "/etc/finger.conf" +#endif /* _PATH_FINGERCONF */ + +#endif /* PATHNAMES_H */ diff --git a/adv_cmds/finger/sprint.c b/adv_cmds/finger/sprint.c new file mode 100644 index 0000000..8de1cba --- /dev/null +++ b/adv_cmds/finger/sprint.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)sprint.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/finger/sprint.c,v 1.22 2003/04/02 20:22:29 rwatson Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "finger.h" + +static void stimeprint(WHERE *); + +void +sflag_print(void) +{ + PERSON *pn; + WHERE *w; + int sflag, r, namelen; + char p[80]; + PERSON *tmp; + DBT data, key; + struct tm *lc; + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + /* + * short format -- + * login name + * real name + * terminal name (the XX of ttyXX) + * if terminal writeable (add an '*' to the terminal name + * if not) + * if logged in show idle time and day logged in, else + * show last login date and time. + * If > 6 months, show year instead of time. + * if (-o) + * office location + * office phone + * else + * remote host + */ +#define MAXREALNAME 20 +#define MAXHOSTNAME 17 /* in reality, hosts are never longer than 16 */ + (void)printf("%-*s %-*s%s %s\n", UT_NAMESIZE, "Login", MAXREALNAME, + "Name", " TTY Idle Login Time ", (gflag) ? "" : + oflag ? "Office Phone" : "Where"); + + for (sflag = R_FIRST;; sflag = R_NEXT) { + r = (*db->seq)(db, &key, &data, sflag); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + pn = tmp; + + for (w = pn->whead; w != NULL; w = w->next) { + namelen = MAXREALNAME; + if (w->info == LOGGEDIN && !w->writable) + --namelen; /* leave space before `*' */ + (void)printf("%-*.*s %-*.*s", UT_NAMESIZE, _UTX_USERSIZE, + pn->name, MAXREALNAME, namelen, + pn->realname ? pn->realname : ""); + if (!w->loginat) { + (void)printf(" * * No logins "); + goto office; + } + (void)putchar(w->info == LOGGEDIN && !w->writable ? + '*' : ' '); + if (*w->tty) + (void)printf("%-3.3s ", + (strncmp(w->tty, "tty", 3) + && strncmp(w->tty, "cua", 3)) + ? w->tty : w->tty + 3); + else + (void)printf(" "); + if (w->info == LOGGEDIN) { + stimeprint(w); + (void)printf(" "); + } else + (void)printf(" * "); + lc = localtime(&w->loginat); +#define SECSPERDAY 86400 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 + if (now - w->loginat < SECSPERDAY * (DAYSPERWEEK - 1)) { + (void)strftime(p, sizeof(p), "%a", lc); + } else { + (void)strftime(p, sizeof(p), + d_first ? "%e %b" : "%b %e", lc); + } + (void)printf("%-6.6s", p); + if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) { + (void)strftime(p, sizeof(p), "%Y", lc); + } else { + (void)strftime(p, sizeof(p), "%R", lc); + } + (void)printf(" %-5.5s", p); +office: + if (gflag) + goto no_gecos; + if (oflag) { + if (pn->office) + (void)printf(" %-7.7s", pn->office); + else if (pn->officephone) + (void)printf(" %-7.7s", " "); + if (pn->officephone) + (void)printf(" %-.9s", + prphone(pn->officephone)); + } else + (void)printf(" %.*s", MAXHOSTNAME, w->host); +no_gecos: + putchar('\n'); + } + } +} + +static void +stimeprint(WHERE *w) +{ + struct tm *delta; + + if (w->idletime == -1) { + (void)printf(" "); + return; + } + + delta = gmtime(&w->idletime); + if (!delta->tm_yday) + if (!delta->tm_hour) + if (!delta->tm_min) + (void)printf(" "); + else + (void)printf("%5d", delta->tm_min); + else + (void)printf("%2d:%02d", + delta->tm_hour, delta->tm_min); + else + (void)printf("%4dd", delta->tm_yday); +} diff --git a/adv_cmds/finger/util.c b/adv_cmds/finger/util.c new file mode 100644 index 0000000..6e7c925 --- /dev/null +++ b/adv_cmds/finger/util.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/finger/util.c,v 1.22 2005/09/19 10:11:47 dds Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "finger.h" +#include "pathnames.h" + +static void find_idle_and_ttywrite(WHERE *); +static void userinfo(PERSON *, struct passwd *); +static WHERE *walloc(PERSON *); + +int +match(struct passwd *pw, const char *user) +{ + char *p, *t; + char name[1024]; + + if (!strcasecmp(pw->pw_name, user)) + return(1); + + /* + * XXX + * Why do we skip asterisks!?!? + */ + (void)strncpy(p = tbuf, pw->pw_gecos, sizeof(tbuf)); + tbuf[sizeof(tbuf) - 1] = '\0'; + if (*p == '*') + ++p; + + /* Ampersands get replaced by the login name. */ + if ((p = strtok(p, ",")) == NULL) + return(0); + + for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) { + if (*t == '&') { + (void)strncpy(t, pw->pw_name, + sizeof(name) - (t - name)); + name[sizeof(name) - 1] = '\0'; + while (t < &name[sizeof(name) - 1] && *++t) + continue; + } else { + ++t; + } + } + *t = '\0'; + for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL) + if (!strcasecmp(p, user)) + return(1); + return(0); +} + +void +enter_lastlog(PERSON *pn) +{ + WHERE *w; + struct lastlogx l, *ll; + char doit = 0; + + if ((ll = getlastlogxbyname(pn->name, &l)) == NULL) { + bzero(&l, sizeof(l)); + ll = &l; + } + if ((w = pn->whead) == NULL) + doit = 1; + else if (ll->ll_tv.tv_sec != 0) { + /* if last login is earlier than some current login */ + for (; !doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && w->loginat < ll->ll_tv.tv_sec) + doit = 1; + /* + * and if it's not any of the current logins + * can't use time comparison because there may be a small + * discrepancy since login calls time() twice + */ + for (w = pn->whead; doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && + strncmp(w->tty, ll->ll_line, _UTX_LINESIZE) == 0) + doit = 0; + } + if (doit) { + w = walloc(pn); + w->info = LASTLOG; + bcopy(ll->ll_line, w->tty, _UTX_LINESIZE); + w->tty[_UTX_LINESIZE] = 0; + bcopy(ll->ll_host, w->host, _UTX_HOSTSIZE); + w->host[_UTX_HOSTSIZE] = 0; + w->loginat = ll->ll_tv.tv_sec; + } +} + +void +enter_where(struct utmpx *ut, PERSON *pn) +{ + WHERE *w; + + w = walloc(pn); + w->info = LOGGEDIN; + bcopy(ut->ut_line, w->tty, _UTX_LINESIZE); + w->tty[_UTX_LINESIZE] = 0; + bcopy(ut->ut_host, w->host, _UTX_HOSTSIZE); + w->host[_UTX_HOSTSIZE] = 0; + w->loginat = (time_t)ut->ut_tv.tv_sec; + find_idle_and_ttywrite(w); +} + +PERSON * +enter_person(struct passwd *pw) +{ + DBT data, key; + PERSON *pn; + + if (db == NULL && + (db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL) + err(1, NULL); + + key.data = pw->pw_name; + key.size = strlen(pw->pw_name); + + switch ((*db->get)(db, &key, &data, 0)) { + case 0: + memmove(&pn, data.data, sizeof pn); + return (pn); + default: + case -1: + err(1, "db get"); + /* NOTREACHED */ + case 1: + ++entries; + pn = palloc(); + userinfo(pn, pw); + pn->whead = NULL; + + data.size = sizeof(PERSON *); + data.data = &pn; + if ((*db->put)(db, &key, &data, 0)) + err(1, "db put"); + return (pn); + } +} + +PERSON * +find_person(const char *name) +{ + struct passwd *pw; + + int cnt; + DBT data, key; + PERSON *p; + char buf[_UTX_USERSIZE + 1]; + + if (!db) + return(NULL); + + if ((pw = getpwnam(name)) && hide(pw)) + return(NULL); + + /* Name may be only _UTX_USERSIZE long and not NUL terminated. */ + for (cnt = 0; cnt < _UTX_USERSIZE && *name; ++name, ++cnt) + buf[cnt] = *name; + buf[cnt] = '\0'; + key.data = buf; + key.size = cnt; + + if ((*db->get)(db, &key, &data, 0)) + return (NULL); + memmove(&p, data.data, sizeof p); + return (p); +} + +PERSON * +palloc(void) +{ + PERSON *p; + + if ((p = malloc(sizeof(PERSON))) == NULL) + err(1, NULL); + return(p); +} + +static WHERE * +walloc(PERSON *pn) +{ + WHERE *w; + + if ((w = malloc(sizeof(WHERE))) == NULL) + err(1, NULL); + if (pn->whead == NULL) + pn->whead = pn->wtail = w; + else { + pn->wtail->next = w; + pn->wtail = w; + } + w->next = NULL; + return(w); +} + +char * +prphone(char *num) +{ + char *p; + int len; + static char pbuf[20]; + + /* don't touch anything if the user has their own formatting */ + for (p = num; *p; ++p) + if (!isdigit(*p)) + return(num); + len = p - num; + p = pbuf; + switch(len) { + case 11: /* +0-123-456-7890 */ + *p++ = '+'; + *p++ = *num++; + *p++ = '-'; + /* FALLTHROUGH */ + case 10: /* 012-345-6789 */ + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + *p++ = '-'; + /* FALLTHROUGH */ + case 7: /* 012-3456 */ + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + break; + case 5: /* x0-1234 */ + case 4: /* x1234 */ + *p++ = 'x'; + *p++ = *num++; + break; + default: + return(num); + } + if (len != 4) { + *p++ = '-'; + *p++ = *num++; + } + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + *p = '\0'; + return(pbuf); +} + +static void +find_idle_and_ttywrite(WHERE *w) +{ + struct stat sb; + time_t touched; + int error; + + (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty); + + error = stat(tbuf, &sb); + if (error < 0 && errno == ENOENT) { + /* + * The terminal listed is not actually a terminal (i.e., + * ":0"). This is a failure, so we'll skip printing + * out the idle time, which is non-ideal but better + * than a bogus warning and idle time. + */ + w->idletime = -1; + return; + } else if (error < 0) { + warn("%s", tbuf); + w->idletime = -1; + return; + } + touched = sb.st_atime; + if (touched < w->loginat) { + /* tty untouched since before login */ + touched = w->loginat; + } + w->idletime = now < touched ? 0 : now - touched; + +#define TALKABLE 0220 /* tty is writable if 220 mode */ + w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); +} + +static void +userinfo(PERSON *pn, struct passwd *pw) +{ + char *p, *t; + char *bp, name[1024]; + struct stat sb; + + pn->realname = pn->office = pn->officephone = pn->homephone = NULL; + + pn->uid = pw->pw_uid; + if ((pn->name = strdup(pw->pw_name)) == NULL) + err(1, "strdup failed"); + if ((pn->dir = strdup(pw->pw_dir)) == NULL) + err(1, "strdup failed"); + if ((pn->shell = strdup(pw->pw_shell)) == NULL) + err(1, "strdup failed"); + + /* why do we skip asterisks!?!? */ + (void)strncpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf)); + tbuf[sizeof(tbuf) - 1] = '\0'; + if (*bp == '*') + ++bp; + + /* ampersands get replaced by the login name */ + if (!(p = strsep(&bp, ","))) + return; + for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) { + if (*t == '&') { + (void)strncpy(t, pw->pw_name, + sizeof(name) - (t - name)); + name[sizeof(name) - 1] = '\0'; + if (islower(*t)) + *t = toupper(*t); + while (t < &name[sizeof(name) - 1] && *++t) + continue; + } else { + ++t; + } + } + *t = '\0'; + if ((pn->realname = strdup(name)) == NULL) + err(1, "strdup failed"); + pn->office = ((p = strsep(&bp, ",")) && *p) ? + strdup(p) : NULL; + pn->officephone = ((p = strsep(&bp, ",")) && *p) ? + strdup(p) : NULL; + pn->homephone = ((p = strsep(&bp, ",")) && *p) ? + strdup(p) : NULL; + (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pw->pw_name); + pn->mailrecv = -1; /* -1 == not_valid */ + if (stat(tbuf, &sb) < 0) { + if (errno != ENOENT) { + warn("%s", tbuf); + return; + } + } else if (sb.st_size != 0) { + pn->mailrecv = sb.st_mtime; + pn->mailread = sb.st_atime; + } +} + +/* + * Is this user hiding from finger? + * If ~/.nofinger exists, return 1 (hide), else return 0 (nohide). + * Nobody can hide from root. + */ + +int +hide(struct passwd *pw) +{ + struct stat st; + char buf[MAXPATHLEN]; + + if (invoker_root || !pw->pw_dir) + return 0; + + snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, _PATH_NOFINGER); + + if (stat(buf, &st) == 0) + return 1; + + return 0; +} diff --git a/adv_cmds/gencat/gencat.1 b/adv_cmds/gencat/gencat.1 new file mode 100644 index 0000000..bcead36 --- /dev/null +++ b/adv_cmds/gencat/gencat.1 @@ -0,0 +1,177 @@ +.\" $OpenBSD: gencat.1,v 1.3 1997/06/11 15:39:54 kstailey Exp $ +.\" +.\" Copyright (c) 1997 Ken Stailey +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD: src/usr.bin/gencat/gencat.1,v 1.9 2001/11/23 14:37:27 dd Exp $ +.\" +.Dd June 11, 1997 +.Dt GENCAT 1 +.Os +.Sh NAME +.Nm gencat +.Nd NLS catalog compiler +.Sh SYNOPSIS +.Nm +.Ar "output-file" +.Ar "input-files..." +.Sh DESCRIPTION +The +.Nm +utility merges the text NLS input files +.Ar "input-files..." +into a formatted message catalog file +.Ar "output-file" . +The file +.Ar "output-file" +will be created if it does not already exist. If +.Ar "output-file" +does exist, its messages will be included in the new +.Ar "output-file" . +If set and message numbers collide, the new message text defined in +.Ar "input-files..." +will replace the old message text currently contained in +.Ar "output-file" . +.Sh INPUT FILES +The format of a message text source file is defined below. Note that +the fields of a message text source line are separated by a single space +character: any other space characters are considered to be part of the +field contents. +.Pp +.Bl -tag -width 3n +.It Li $set Ar n comment +This line specifies the set identifier of the following messages until +the next +.Li $set +or end-of-file appears. The argument +.Ar n +is the set identifier which is defined as a number in the range +[1, (NL_SETMAX)]. Set identifiers must occur in ascending order within +a single source file, but need not be contiguous. Any string following +a space following the set identifier is treated as a comment. If no +.Li $set +directive is specified in a given source file, all messages will +be located in the default message set NL_SETD. +.It Li $del Ar n comment +This line deletes messages from set +.Ar n +from a message catalog. The +.Ar n +specifies a set number. Any string following a space following the set +number is treated as a comment. +.It Li $ Ar comment +A line beginning with +.Li $ +followed by a space is treated as a comment. +.It Ar m message-text +A message line consists of a message identifier +.Ar m +in the range [1, (NL_MSGMAX)]. The +.Ar message-text +is stored in the message catalog with the set identifier specified by +the last +.Li $set +directive, and the message identifier +.Ar m . +If the +.Ar message-text +is empty, and there is a space character following the message identifier, +an empty string is stored in the message catalog. If the +.Ar message-text +is empty, and if there is no space character following the message +identifier, then the existing message in the current set with the +specified message identifier is deleted from the catalog. Message +identifiers must be in ascending order within a single set, but +need not be contiguous. The +.Ar message-text +length must be in the range [0, (NL_TEXTMAX)]. +.It Li $quote Ar c +This line specifies an optional quote character +.Ar c +which can be used to surround +.Ar message-text +so that trailing space or empty messages are visible in message +source files. By default, or if an empty +.Li $quote +directive is specified, no quoting of +.Ar message-text +will be recognized. +.El +.Pp +Empty lines in message source files are ignored. The effect of lines +beginning with any character other than those described above is +undefined. +.Pp +Text strings can contain the following special characters and escape +sequences. In addition, if a quote character is defined, it may be +escaped as well to embed a literal quote character. +.Pp +.Bl -tag -width "\eooo" -offset indent -compact +.It Li \en +line feed +.It Li \et +horizontal tab +.It Li \ev +vertical tab +.It Li \eb +backspace +.It Li \er +carriage return +.It Li \ef +form feed +.It Li \e\e +backslash +.It Li \eooo +octal number in the range [000, 377] +.El +.Pp +A backslash character immediately before the end of the line in a file +is used to continue the line onto the next line, e.g.: +.Pp +.Dl 1 This line is continued \e +.Dl on this line. +.Pp +If the character following the backslash is not one of those specified, +the backslash is ignored. +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr catclose 3 , +.Xr catgets 3 , +.Xr catopen 3 +.Sh STANDARDS +The +.Nm +utility is compliant with the +.St -xpg4 +standard. +.Sh AUTHORS +.An -nosplit +This manual page was originally written by +.An Ken Stailey +and later revised by +.An Terry Lambert . +.Sh BUGS +A message catalog file created from a blank input file cannot be revised; +it must be deleted and recreated. diff --git a/adv_cmds/gencat/gencat.c b/adv_cmds/gencat/gencat.c new file mode 100644 index 0000000..e0d00e3 --- /dev/null +++ b/adv_cmds/gencat/gencat.c @@ -0,0 +1,199 @@ +/*********************************************************** +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 +__FBSDID("$FreeBSD: src/usr.bin/gencat/gencat.c,v 1.9 2002/05/29 14:23:10 tjr Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include "gencat.h" + +/* + * The spec says the syntax is "gencat catfile msgfile...". + * We extend it to: + * gencat [-lang C|C++|ANSIC] catfile msgfile [-h ]... + * Flags are order dependent, we'll take whatever lang was most recently chosen + * and use it to generate the next header file. The header files are generated + * at the point in the command line they are listed. Thus the sequence: + * gencat -lang C foo.cat foo.mcs -h foo.h -lang C++ bar.mcs -h bar.H + * will put constants from foo.mcs into foo.h and constants from bar.mcs into + * bar.h. Constants are not saved in the catalog file, so nothing will come + * from that, even if things have been defined before. The constants in foo.h + * will be in C syntax, in bar.H in C++ syntax. + */ + +static void writeIfChanged(char *, int, int); + +static void +usage(void) +{ + fprintf(stderr, "usage: gencat [-new] [-or] [-lang C|C++|ANSIC]\n" + " catfile msgfile [-h ]...\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int ofd = -1, ifd, i; + char *catfile = NULL; + char *input = NULL; + int lang = MCLangC; + int new = FALSE; + int orConsts = FALSE; + + for (i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-lang") == 0) { + ++i; + if (strcmp(argv[i], "C") == 0) lang = MCLangC; + else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus; + else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC; + else { + errx(1, "unrecognized language: %s", argv[i]); + } + } else if (strcmp(argv[i], "-h") == 0) { + if (!input) + errx(1, "can't write to a header before reading something"); + ++i; + writeIfChanged(argv[i], lang, orConsts); + } else if (strcmp(argv[i], "-new") == 0) { + if (catfile) + errx(1, "you must specify -new before the catalog file name"); + new = TRUE; + } else if (strcmp(argv[i], "-or") == 0) { + orConsts = ~orConsts; + } else { + usage(); + } + } else { + if (!catfile) { + catfile = argv[i]; + if (new) { + if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) + errx(1, "unable to create a new %s", catfile); + } else if ((ofd = open(catfile, O_RDONLY)) < 0) { + if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) + errx(1, "unable to create %s", catfile); + } else { + MCReadCat(ofd); + close(ofd); + if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) + errx(1, "unable to truncate %s", catfile); + } + } else { + input = argv[i]; + if ((ifd = open(input, O_RDONLY)) < 0) + errx(1, "unable to read %s", input); + MCParse(ifd); + close(ifd); + } + } + } + if (catfile) { + MCWriteCat(ofd); + exit(0); + } else { + usage(); + } + return 0; +} + +static void +writeIfChanged(char *fname, int lang, int orConsts) +{ + char tmpname[] = _PATH_TMP"/gencat.XXXXXX"; + char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr; + int fd, tfd; + int diff = FALSE; + int len, tlen; + struct stat sbuf; + + /* If it doesn't exist, just create it */ + if (stat(fname, &sbuf)) { + if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) + errx(1, "unable to create header file %s", fname); + MCWriteConst(fd, lang, orConsts); + close(fd); + return; + } + + /* If it does exist, create a temp file for now */ + if ((tfd = mkstemp(tmpname)) < 0) + err(1, "mkstemp"); + unlink(tmpname); + + /* Write to the temp file and rewind */ + MCWriteConst(tfd, lang, orConsts); + + /* Open the real header file */ + if ((fd = open(fname, O_RDONLY)) < 0) + errx(1, "unable to read header file: %s", fname); + + /* Backup to the start of the temp file */ + if (lseek(tfd, (off_t)0, L_SET) < 0) + errx(1, "unable to seek in tempfile: %s", tmpname); + + /* Now compare them */ + while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) { + if ((len = read(fd, buf, BUFSIZ)) != tlen) { + diff = TRUE; + goto done; + } + for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) { + if (*tptr != *cptr) { + diff = TRUE; + goto done; + } + } + } +done: + if (diff) { + if (lseek(tfd, (off_t)0, L_SET) < 0) + errx(1, "unable to seek in tempfile: %s", tmpname); + close(fd); + if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) + errx(1, "unable to truncate header file: %s", fname); + while ((len = read(tfd, buf, BUFSIZ)) > 0) { + if (write(fd, buf, (size_t)len) != len) + warnx("error writing to header file: %s", fname); + } + } + close(fd); + close(tfd); +} diff --git a/adv_cmds/gencat/gencat.h b/adv_cmds/gencat/gencat.h new file mode 100644 index 0000000..5e7e459 --- /dev/null +++ b/adv_cmds/gencat/gencat.h @@ -0,0 +1,87 @@ +/* $FreeBSD: src/usr.bin/gencat/gencat.h,v 1.4 2002/03/26 12:39:08 charnier Exp $ */ + +#ifndef GENCAT_H +#define GENCAT_H + +/*********************************************************** +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 + +******************************************************************/ + +/* + * $set n comment + * My extension: If the comment begins with # treat the next string + * as a constant identifier. + * $delset n comment + * n goes from 1 to NL_SETMAX + * Deletes a set from the MC + * $ comment + * My extension: If comment begins with # treat the next string as + * a constant identifier for the next message. + * m message-text + * m goes from 1 to NL_MSGMAX + * If message-text is empty, and a space or tab is present, put + * empty string in catalog. + * If message-text is empty, delete the message. + * Length of text is 0 to NL_TEXTMAX + * My extension: If '#' is used instead of a number, the number + * is generated automatically. A # followed by anything is an empty message. + * $quote c + * Optional quote character which can surround message-text to + * show where spaces are. + * + * Escape Characters + * \n (newline), \t (horiz tab), \v (vert tab), \b (backspace), + * \r (carriage return), \f (formfeed), \\ (backslash), \ddd (bitpattern + * in octal). + * Also, \ at end of line is a continuation. + * + */ + +#define MCLangC 0 +#define MCLangCPlusPlus 1 +#define MCLangANSIC 2 + +#define MAXTOKEN 1024 + +#define TRUE 1 +#define FALSE 0 + +extern void MCAddSet(int, char *); +extern void MCDelSet(int); +extern void MCAddMsg(int, const char *, char *); +extern void MCDelMsg(int); +extern void MCParse(int); +extern void MCReadCat(int); +extern void MCWriteConst(int, int, int); +extern void MCWriteCat(int); +extern long MCGetByteOrder(void); + +#endif /* GENCAT_H */ diff --git a/adv_cmds/gencat/genlib.c b/adv_cmds/gencat/genlib.c new file mode 100644 index 0000000..42b7ae2 --- /dev/null +++ b/adv_cmds/gencat/genlib.c @@ -0,0 +1,836 @@ +/*********************************************************** +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 +__FBSDID("$FreeBSD: src/usr.bin/gencat/genlib.c,v 1.13 2002/12/24 07:40:10 davidxu Exp $"); + +#include +#include +#include +#include +#include +#include +#include "msgcat.h" +#include "gencat.h" +#include +/* libkern/OSByteOrder is needed for the 64 bit byte swap */ +#include + +#ifndef htonll +#define htonll(x) OSSwapHostToBigInt64(x) +#define ntohll(x) OSSwapBigToHostInt64(x) +#endif + +static char *curline = NULL; +static long lineno = 0; + +static void +warning(char *cptr, const char *msg) +{ + warnx("%s on line %ld\n%s", msg, lineno, (curline == NULL ? "" : curline) ); + if (cptr) { + char *tptr; + for (tptr = curline; tptr < cptr; ++tptr) putc(' ', stderr); + fprintf(stderr, "^\n"); + } +} + +static void +error(char *cptr, const char *msg) +{ + warning(cptr, msg); + exit(1); +} + +static void +corrupt(void) { + error(NULL, "corrupt message catalog"); +} + +static void +nomem(void) { + error(NULL, "out of memory"); +} + +static char * +gencat_getline(int fd) +{ + static size_t curlen = BUFSIZ; + static char buf[BUFSIZ], *bptr = buf, *bend = buf; + char *cptr, *cend; + long buflen; + + if (!curline) { + curline = (char *) malloc(curlen); + if (!curline) nomem(); + } + ++lineno; + + cptr = curline; + cend = curline + curlen; + while (TRUE) { + for (; bptr < bend && cptr < cend; ++cptr, ++bptr) { + if (*bptr == '\n') { + *cptr = '\0'; + ++bptr; + return(curline); + } else *cptr = *bptr; + } + if (bptr == bend) { + buflen = read(fd, buf, BUFSIZ); + if (buflen <= 0) { + if (cptr > curline) { + *cptr = '\0'; + return(curline); + } + return(NULL); + } + bend = buf + buflen; + bptr = buf; + } + if (cptr == cend) { + cptr = curline = (char *) realloc(curline, curlen *= 2); + if (!curline) nomem(); + cend = curline + curlen; + } + } +} + +static char * +token(char *cptr) +{ + static char tok[MAXTOKEN+1]; + char *tptr = tok; + + while (*cptr && isspace((unsigned char)*cptr)) ++cptr; + while (*cptr && !isspace((unsigned char)*cptr)) *tptr++ = *cptr++; + *tptr = '\0'; + return(tok); +} + +static char * +wskip(char *cptr) +{ + if (!*cptr || !isspace((unsigned char)*cptr)) { + warning(cptr, "expected a space"); + return(cptr); + } + while (*cptr && isspace((unsigned char)*cptr)) ++cptr; + return(cptr); +} + +static char * +cskip(char *cptr) +{ + if (!*cptr || isspace((unsigned char)*cptr)) { + warning(cptr, "wasn't expecting a space"); + return(cptr); + } + while (*cptr && !isspace((unsigned char)*cptr)) ++cptr; + return(cptr); +} + +static char * +getmsg(int fd, char *cptr, char quote) +{ + static char *msg = NULL; + static size_t msglen = 0; + size_t clen, i; + char *tptr; + int needq; + + if (quote && *cptr == quote) { + needq = TRUE; + ++cptr; + } else needq = FALSE; + + clen = strlen(cptr) + 1; + if (clen > msglen) { + if (msglen) msg = (char *) realloc(msg, clen); + else msg = (char *) malloc(clen); + if (!msg) nomem(); + msglen = clen; + } + tptr = msg; + + while (*cptr) { + if (quote && *cptr == quote) { + char *tmp; + tmp = cptr+1; + if (*tmp && (!isspace((unsigned char)*tmp) || *wskip(tmp))) { + warning(cptr, "unexpected quote character, ignoring"); + *tptr++ = *cptr++; + } else { + *cptr = '\0'; + } + } else if (*cptr == '\\') { + ++cptr; + switch (*cptr) { + case '\0': + cptr = gencat_getline(fd); + if (!cptr) error(NULL, "premature end of file"); + msglen += strlen(cptr); + i = tptr - msg; + msg = (char *) realloc(msg, msglen); + if (!msg) nomem(); + tptr = msg + i; + break; + +#define CASEOF(CS, CH) \ + case CS: \ + *tptr++ = CH; \ + ++cptr; \ + break; + + CASEOF('n', '\n') + CASEOF('t', '\t') + CASEOF('v', '\v') + CASEOF('b', '\b') + CASEOF('r', '\r') + CASEOF('f', '\f') + CASEOF('"', '"') + CASEOF('\'', '\'') + CASEOF('\\', '\\') + + default: + if (isdigit((unsigned char)*cptr)) { + *tptr = 0; + for (i = 0; i < 3; ++i) { + if (!isdigit((unsigned char)*cptr)) break; + if (*cptr > '7') warning(cptr, "octal number greater than 7?!"); + *tptr *= 8; + *tptr += (*cptr - '0'); + ++cptr; + } + ++tptr; + } else { + warning(cptr, "unrecognized escape sequence"); + } + } + } else { + *tptr++ = *cptr++; + } + } + *tptr = '\0'; + return(msg); +} + +static char * +dupstr(const char *ostr) +{ + char *nstr; + + nstr = strdup(ostr); + if (!nstr) error(NULL, "unable to allocate storage"); + return(nstr); +} + +/* + * The Global Stuff + */ + +typedef struct _msgT { + long msgId; + char *str; + char *hconst; + long offset; + struct _msgT *prev, *next; +} msgT; + +typedef struct _setT { + long setId; + char *hconst; + msgT *first, *last; + struct _setT *prev, *next; +} setT; + +typedef struct { + setT *first, *last; +} catT; + +static setT *curSet; +static catT *cat; + +/* + * Find the current byte order. There are of course some others, but + * this will do for now. Note that all we care about is "long". + */ +long +MCGetByteOrder(void) { + long l = 0x00010203; + char *cptr = (char *) &l; + + if (cptr[0] == 0 && cptr[1] == 1 && cptr[2] == 2 && cptr[3] == 3) + return MC68KByteOrder; + else return MCn86ByteOrder; +} + +void +MCParse(int fd) +{ + char *cptr, *str; + int setid = 1, msgid = 0; + char hconst[MAXTOKEN+1]; + char quote = 0; + + if (!cat) { + cat = (catT *) malloc(sizeof(catT)); + if (!cat) nomem(); + bzero(cat, sizeof(catT)); + } + + hconst[0] = '\0'; + + while ((cptr = gencat_getline(fd)) != NULL) { + if (*cptr == '$') { + ++cptr; + if (strncmp(cptr, "set", 3) == 0) { + cptr += 3; + cptr = wskip(cptr); + setid = atoi(cptr); + cptr = cskip(cptr); + if (*cptr) cptr = wskip(cptr); + if (*cptr == '#') { + ++cptr; + MCAddSet(setid, token(cptr)); + } else MCAddSet(setid, NULL); + msgid = 0; + } else if (strncmp(cptr, "delset", 6) == 0) { + cptr += 6; + cptr = wskip(cptr); + setid = atoi(cptr); + MCDelSet(setid); + } else if (strncmp(cptr, "quote", 5) == 0) { + cptr += 5; + if (!*cptr) quote = 0; + else { + cptr = wskip(cptr); + if (!*cptr) quote = 0; + else quote = *cptr; + } + } else if (isspace((unsigned char)*cptr)) { + cptr = wskip(cptr); + if (*cptr == '#') { + ++cptr; + strcpy(hconst, token(cptr)); + } + } else { + if (*cptr) { + cptr = wskip(cptr); + if (*cptr) warning(cptr, "unrecognized line"); + } + } + } else { + if (!curSet) MCAddSet(setid, NULL); + if (isdigit((unsigned char)*cptr) || *cptr == '#') { + if (*cptr == '#') { + ++msgid; + ++cptr; + if (!*cptr) { + MCAddMsg(msgid, "", hconst); + hconst[0] = '\0'; + continue; + } + if (!isspace((unsigned char)*cptr)) warning(cptr, "expected a space"); + ++cptr; + if (!*cptr) { + MCAddMsg(msgid, "", hconst); + hconst[0] = '\0'; + continue; + } + } else { + msgid = atoi(cptr); + cptr = cskip(cptr); + if (isspace(*cptr)) + cptr++; + /* if (*cptr) ++cptr; */ + } + if (!*cptr) { + if (isspace(cptr[-1])) { + MCAddMsg(msgid, "", hconst); + hconst[0] = '\0'; + } else { + MCDelMsg(msgid); + } + } else { + str = getmsg(fd, cptr, quote); + MCAddMsg(msgid, str, hconst); + hconst[0] = '\0'; + } + } + } + } +} + +void +MCReadCat(int fd) +{ + MCHeaderT mcHead; + MCMsgT mcMsg; + MCSetT mcSet; + msgT *msg; + setT *set; + int i; + char *data; + + cat = (catT *) malloc(sizeof(catT)); + if (!cat) nomem(); + bzero(cat, sizeof(catT)); + + /* While we deal with read/write this in network byte order we do NOT + deal with struct member padding issues, or even sizeof(long) issues, + those are left for a future genneration to curse either me, or the + original author for */ + + if (read(fd, &mcHead, sizeof(mcHead)) != sizeof(mcHead)) corrupt(); + if (strncmp(mcHead.magic, MCMagic, MCMagicLen) != 0) corrupt(); + if (ntohl(mcHead.majorVer) != MCMajorVer) error(NULL, "unrecognized catalog version"); + if ((ntohl(mcHead.flags) & MC68KByteOrder) == 0) error(NULL, "wrong byte order"); + + if (lseek(fd, ntohll(mcHead.firstSet), L_SET) == -1) corrupt(); + + while (TRUE) { + if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) corrupt(); + if (mcSet.invalid) continue; + + set = (setT *) malloc(sizeof(setT)); + if (!set) nomem(); + bzero(set, sizeof(*set)); + if (cat->first) { + cat->last->next = set; + set->prev = cat->last; + cat->last = set; + } else cat->first = cat->last = set; + + set->setId = ntohl(mcSet.setId); + + /* Get the data */ + if (mcSet.dataLen) { + data = (char *) malloc((size_t)ntohl(mcSet.dataLen)); + if (!data) nomem(); + if (lseek(fd, ntohll(mcSet.data.off), L_SET) == -1) corrupt(); + if (read(fd, data, (size_t)ntohl(mcSet.dataLen)) != ntohl(mcSet.dataLen)) corrupt(); + if (lseek(fd, ntohll(mcSet.u.firstMsg), L_SET) == -1) corrupt(); + + for (i = 0; i < ntohl(mcSet.numMsgs); ++i) { + if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) corrupt(); + if (mcMsg.invalid) { + --i; + continue; + } + + msg = (msgT *) malloc(sizeof(msgT)); + if (!msg) nomem(); + bzero(msg, sizeof(*msg)); + if (set->first) { + set->last->next = msg; + msg->prev = set->last; + set->last = msg; + } else set->first = set->last = msg; + + msg->msgId = ntohl(mcMsg.msgId); + msg->str = dupstr((char *) (data + ntohll(mcMsg.msg.off))); + } + free(data); + } + if (!mcSet.nextSet) break; + if (lseek(fd, ntohll(mcSet.nextSet), L_SET) == -1) corrupt(); + } +} + + +static void +printS(int fd, const char *str) +{ + if (str) + write(fd, str, strlen(str)); +} + +static void +printL(int fd, long l) +{ + char buf[32]; + sprintf(buf, "%ld", l); + write(fd, buf, strlen(buf)); +} + +static void +printLX(int fd, long l) +{ + char buf[32]; + sprintf(buf, "%lx", l); + write(fd, buf, strlen(buf)); +} + +static void +genconst(int fd, int type, char *setConst, char *msgConst, long val) +{ + switch (type) { + case MCLangC: + if (!msgConst) { + printS(fd, "\n#define "); + printS(fd, setConst); + printS(fd, "Set"); + } else { + printS(fd, "#define "); + printS(fd, setConst); + printS(fd, msgConst); + } + printS(fd, "\t0x"); + printLX(fd, val); + printS(fd, "\n"); + break; + case MCLangCPlusPlus: + case MCLangANSIC: + if (!msgConst) { + printS(fd, "\nconst long "); + printS(fd, setConst); + printS(fd, "Set"); + } else { + printS(fd, "const long "); + printS(fd, setConst); + printS(fd, msgConst); + } + printS(fd, "\t= "); + printL(fd, val); + printS(fd, ";\n"); + break; + default: + error(NULL, "not a recognized (programming) language type"); + } +} + +void +MCWriteConst(int fd, int type, int orConsts) +{ + msgT *msg; + setT *set; + long id; + + if (orConsts && (type == MCLangC || type == MCLangCPlusPlus || type == MCLangANSIC)) { + printS(fd, "/* Use these Macros to compose and decompose setId's and msgId's */\n"); + printS(fd, "#ifndef MCMakeId\n"); + printS(fd, "# define MCMakeId(s,m)\t(unsigned long)(((unsigned short)s<<(sizeof(short)*8))\\\n"); + printS(fd, "\t\t\t\t\t|(unsigned short)m)\n"); + printS(fd, "# define MCSetId(id)\t(unsigned int) (id >> (sizeof(short) * 8))\n"); + printS(fd, "# define MCMsgId(id)\t(unsigned int) ((id << (sizeof(short) * 8))\\\n"); + printS(fd, "\t\t\t\t\t>> (sizeof(short) * 8))\n"); + printS(fd, "#endif\n"); + } + + for (set = cat->first; set; set = set->next) { + if (set->hconst) genconst(fd, type, set->hconst, NULL, set->setId); + + for (msg = set->first; msg; msg = msg->next) { + if (msg->hconst) { + if (orConsts) id = MCMakeId(set->setId, msg->msgId); + else id = msg->msgId; + genconst(fd, type, set->hconst, msg->hconst, id); + free(msg->hconst); + msg->hconst = NULL; + } + } + if (set->hconst) { + free(set->hconst); + set->hconst = NULL; + } + } +} + +void +MCWriteCat(int fd) +{ + MCHeaderT mcHead; + int cnt; + setT *set; + msgT *msg; + MCSetT mcSet; + MCMsgT mcMsg; + off_t pos; + + bcopy(MCMagic, mcHead.magic, MCMagicLen); + mcHead.majorVer = htonl(MCMajorVer); + mcHead.minorVer = htonl(MCMinorVer); + mcHead.flags = htonl(MC68KByteOrder); + mcHead.firstSet = 0; /* We'll be back to set this in a minute */ + + if (cat == NULL) + error(NULL, "cannot write empty catalog set"); + + for (cnt = 0, set = cat->first; set; set = set->next) ++cnt; + mcHead.numSets = htonl(cnt); + + /* I'm not inclined to mess with it, but it looks odd that we write + the header twice...and that we get the firstSet value from another + lseek rather then just 'sizeof(mcHead)' */ + + /* Also, this code doesn't seem to check returns from write! */ + + lseek(fd, (off_t)0L, L_SET); + write(fd, &mcHead, sizeof(mcHead)); + mcHead.firstSet = htonll(lseek(fd, (off_t)0L, L_INCR)); + lseek(fd, (off_t)0L, L_SET); + write(fd, &mcHead, sizeof(mcHead)); + + for (set = cat->first; set; set = set->next) { + bzero(&mcSet, sizeof(mcSet)); + + mcSet.setId = htonl(set->setId); + mcSet.invalid = FALSE; + + /* The rest we'll have to come back and change in a moment */ + pos = lseek(fd, (off_t)0L, L_INCR); + write(fd, &mcSet, sizeof(mcSet)); + + /* Now write all the string data */ + mcSet.data.off = htonll(lseek(fd, (off_t)0L, L_INCR)); + cnt = 0; + for (msg = set->first; msg; msg = msg->next) { + msg->offset = lseek(fd, (off_t)0L, L_INCR) - ntohll(mcSet.data.off); + mcSet.dataLen += write(fd, msg->str, strlen(msg->str) + 1); + ++cnt; + } + mcSet.u.firstMsg = htonll(lseek(fd, (off_t)0L, L_INCR)); + mcSet.numMsgs = htonl(cnt); + mcSet.dataLen = htonl(mcSet.dataLen); + + /* Now write the message headers */ + for (msg = set->first; msg; msg = msg->next) { + mcMsg.msgId = htonl(msg->msgId); + mcMsg.msg.off = htonll(msg->offset); + mcMsg.invalid = FALSE; + write(fd, &mcMsg, sizeof(mcMsg)); + } + + /* Go back and fix things up */ + + if (set == cat->last) { + mcSet.nextSet = 0; + lseek(fd, pos, L_SET); + write(fd, &mcSet, sizeof(mcSet)); + } else { + mcSet.nextSet = htonll(lseek(fd, (off_t)0L, L_INCR)); + lseek(fd, pos, L_SET); + write(fd, &mcSet, sizeof(mcSet)); + lseek(fd, ntohll(mcSet.nextSet), L_SET); + } + } +} + +void +MCAddSet(int setId, char *hconst) +{ + setT *set; + + if (setId <= 0) { + error(NULL, "setId's must be greater than zero"); + return; + } + + if (hconst && !*hconst) hconst = NULL; + for (set = cat->first; set; set = set->next) { + if (set->setId == setId) { + if (set->hconst && hconst) free(set->hconst); + set->hconst = NULL; + break; + } else if (set->setId > setId) { + setT *newSet; + + newSet = (setT *) malloc(sizeof(setT)); + if (!newSet) nomem(); + bzero(newSet, sizeof(setT)); + newSet->prev = set->prev; + newSet->next = set; + if (set->prev) set->prev->next = newSet; + else cat->first = newSet; + set->prev = newSet; + set = newSet; + break; + } + } + if (!set) { + set = (setT *) malloc(sizeof(setT)); + if (!set) nomem(); + bzero(set, sizeof(setT)); + + if (cat->first) { + set->prev = cat->last; + set->next = NULL; + cat->last->next = set; + cat->last = set; + } else { + set->prev = set->next = NULL; + cat->first = cat->last = set; + } + } + set->setId = setId; + if (hconst) set->hconst = dupstr(hconst); + curSet = set; +} + +void +MCAddMsg(int msgId, const char *str, char *hconst) +{ + msgT *msg; + + if (!curSet) + error(NULL, "can't specify a message when no set exists"); + + if (msgId <= 0) { + error(NULL, "msgId's must be greater than zero"); + return; + } + + if (hconst && !*hconst) hconst = NULL; + for (msg = curSet->first; msg; msg = msg->next) { + if (msg->msgId == msgId) { + if (msg->hconst && hconst) free(msg->hconst); + if (msg->str) free(msg->str); + msg->hconst = msg->str = NULL; + break; + } else if (msg->msgId > msgId) { + msgT *newMsg; + + newMsg = (msgT *) malloc(sizeof(msgT)); + if (!newMsg) nomem(); + bzero(newMsg, sizeof(msgT)); + newMsg->prev = msg->prev; + newMsg->next = msg; + if (msg->prev) msg->prev->next = newMsg; + else curSet->first = newMsg; + msg->prev = newMsg; + msg = newMsg; + break; + } + } + if (!msg) { + msg = (msgT *) malloc(sizeof(msgT)); + if (!msg) nomem(); + bzero(msg, sizeof(msgT)); + + if (curSet->first) { + msg->prev = curSet->last; + msg->next = NULL; + curSet->last->next = msg; + curSet->last = msg; + } else { + msg->prev = msg->next = NULL; + curSet->first = curSet->last = msg; + } + } + msg->msgId = msgId; + if (hconst) msg->hconst = dupstr(hconst); + msg->str = dupstr(str); +} + +void +MCDelSet(int setId) +{ + setT *set; + msgT *msg; + + for (set = cat->first; set; set = set->next) { + if (set->setId == setId) { + for (msg = set->first; msg; msg = msg->next) { + if (msg->hconst) free(msg->hconst); + if (msg->str) free(msg->str); + free(msg); + } + if (set->hconst) free(set->hconst); + + if (set->prev) set->prev->next = set->next; + else cat->first = set->next; + + if (set->next) set->next->prev = set->prev; + else cat->last = set->prev; + + free(set); + return; + } else if (set->setId > setId) break; + } + warning(NULL, "specified set doesn't exist"); +} + +void +MCDelMsg(int msgId) +{ + msgT *msg; + + if (!curSet) + error(NULL, "you can't delete a message before defining the set"); + + for (msg = curSet->first; msg; msg = msg->next) { + if (msg->msgId == msgId) { + if (msg->hconst) free(msg->hconst); + if (msg->str) free(msg->str); + + if (msg->prev) msg->prev->next = msg->next; + else curSet->first = msg->next; + + if (msg->next) msg->next->prev = msg->prev; + else curSet->last = msg->prev; + + free(msg); + return; + } else if (msg->msgId > msgId) break; + } + warning(NULL, "specified msg doesn't exist"); +} + +#if 0 /* this function is unsed and looks like debug thing */ + +void +MCDumpcat(fp) +FILE *fp; +{ + msgT *msg; + setT *set; + + if (!cat) + errx(1, "no catalog open"); + + for (set = cat->first; set; set = set->next) { + fprintf(fp, "$set %ld", set->setId); + if (set->hconst) + fprintf(fp, " # %s", set->hconst); + fprintf(fp, "\n\n"); + + for (msg = set->first; msg; msg = msg->next) { + if (msg->hconst) + fprintf(fp, "# %s\n", msg->hconst); + fprintf(fp, "%ld\t%s\n", msg->msgId, msg->str); + } + fprintf(fp, "\n"); + } + +} +#endif /* 0 */ diff --git a/adv_cmds/last/last.1 b/adv_cmds/last/last.1 new file mode 100644 index 0000000..8ffd49d --- /dev/null +++ b/adv_cmds/last/last.1 @@ -0,0 +1,111 @@ +.\" Copyright (c) 1980, 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. +.\" +.\" @(#)last.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt LAST 1 +.Os BSD 4 +.Sh NAME +.Nm last +.Nd indicate last logins of users and ttys +.Sh SYNOPSIS +.Nm +.Op Fl Ns Ar n +.Op Fl h Ar host +.Op Fl t Ar tty +.Op user ... +.Sh DESCRIPTION +.Nm Last +will list the sessions of specified +.Ar users , +.Ar ttys , +and +.Ar hosts , +in reverse time order. Each line of output contains +the user name, the tty from which the session was conducted, any +hostname, the start and stop times for the session, and the duration +of the session. If the session is still continuing or was cut short by +a crash or shutdown, +.Nm +will so indicate. +.Pp +.Bl -tag -width indent-two +.It Fl Ns Ar n +Limits the report to +.Ar n +lines. +.It Fl h Ar host +.Ar Host +names may be names or internet numbers. +.It Fl t Ar tty +Specify the +.Ar tty . +Tty names may be given fully or abbreviated, for example, +.Dq Li "last -t 03" +is +equivalent to +.Dq Li "last -t tty03" . +.El +.Pp +If +multiple arguments are given, the information which applies to any of the +arguments is printed, e.g., +.Dq Li "last root -t console" +would list all of +.Dq Li root Ns 's +sessions as well as all sessions on the console terminal. If no +users, hostnames or terminals are specified, +.Nm +prints a record of +all logins and logouts. +.Pp +The pseudo-user +.Ar reboot +logs in at reboots of the system, thus +.Dq Li last reboot +will give an indication of mean time between reboot. +.Pp +If +.Nm +is interrupted, it indicates to what date the search has +progressed. If interrupted with a quit signal +.Nm +indicates how +far the search has progressed and then continues. +.Sh SEE ALSO +.Xr lastcomm 1 , +.Xr utmpx 5 , +.Xr ac 8 +.Sh HISTORY +.Nm Last +appeared in +.Bx 3.0 . diff --git a/adv_cmds/last/last.c b/adv_cmds/last/last.c new file mode 100644 index 0000000..6439dd1 --- /dev/null +++ b/adv_cmds/last/last.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved + * + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * The NEXTSTEP Software License Agreement specifies the terms + * and conditions for redistribution. + * + * @(#)last.c 8.2 (Berkeley) 4/2/94 + */ + + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1987, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NO 0 /* false/no */ +#define YES 1 /* true/yes */ + +static const struct utmpx *prev; /* previous utmpx structure */ + +/* values from utmp.h, used for print formatting */ +#define UT_NAMESIZE 8 /* old utmp.h value */ +#define UT_LINESIZE 8 +#define UT_HOSTSIZE 16 + +typedef struct arg { + const char *name; /* argument */ +#define HOST_TYPE -2 +#define TTY_TYPE -3 +#define USER_TYPE -4 + int type; /* type of arg */ + struct arg *next; /* linked list pointer */ +} ARG; +ARG *arglist; /* head of linked list */ + +typedef struct ttytab { + long logout; /* log out time */ + char id[_UTX_IDSIZE]; /* terminal id */ + pid_t pid; + struct ttytab *next; /* linked list pointer */ +} TTY; +TTY *ttylist; /* head of linked list */ + +static const char *crmsg; /* cause of last reboot */ +static long currentout, /* current logout value */ + maxrec; /* records to display */ +time_t now; + +void addarg __P((int, const char *)); +TTY *addtty __P((const char *, pid_t)); +void hostconv __P((const char *)); +void onintr __P((int)); +const char *ttyconv __P((const char *)); +int want __P((struct utmpx *, int)); +void wtmp __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + int ch; + char *p; + char *myname = *argv; + + if ((p = strrchr(myname, '/')) != NULL) + myname = p + 1; + maxrec = -1; + while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF) + switch (ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* + * kludge: last was originally designed to take + * a number after a dash. + */ + if (maxrec == -1) { + p = argv[optind - 1]; + if (p[0] == '-' && p[1] == ch && !p[2]) + maxrec = atol(++p); + else + maxrec = atol(argv[optind] + 1); + if (!maxrec) + exit(0); + } + break; + case 'h': + hostconv(optarg); + addarg(HOST_TYPE, optarg); + break; + case 't': + addarg(TTY_TYPE, ttyconv(optarg)); + break; + case 'f': + warnx("-f is unsupported"); + break; + case '?': + default: + (void)fprintf(stderr, + "usage: last [-#] [-t tty] [-h hostname] [user ...]\n"); + exit(1); + } + + if (argc) { + setlinebuf(stdout); + for (argv += optind; *argv; ++argv) { +#define COMPATIBILITY +#ifdef COMPATIBILITY + /* code to allow "last p5" to work */ + addarg(TTY_TYPE, ttyconv(*argv)); +#endif + addarg(USER_TYPE, *argv); + } + } + wtmp(); + exit(0); +} + +/* + * wtmp -- + * read through the wtmp file + */ + +void +wtmp() +{ + + struct utmpx *bp; /* current structure */ + TTY *T; /* tty list entry */ + long delta; /* time difference */ + char *ct; + + (void)time(&now); + (void)signal(SIGINT, onintr); + (void)signal(SIGQUIT, onintr); + + setutxent_wtmp(0); /* zero means reverse chronological order */ + while ((bp = getutxent_wtmp()) != NULL) { + prev = bp; + switch(bp->ut_type) { + case BOOT_TIME: + case SHUTDOWN_TIME: + /* everybody just logged out */ + for (T = ttylist; T; T = T->next) + T->logout = -bp->ut_tv.tv_sec; + currentout = -bp->ut_tv.tv_sec; + crmsg = bp->ut_type == BOOT_TIME ? "crash" : "shutdown"; + if (want(bp, NO)) { + ct = ctime(&bp->ut_tv.tv_sec); + printf("%-*s %-*s %-*.*s %10.10s %5.5s \n", + UT_NAMESIZE, bp->ut_type == BOOT_TIME ? "reboot" : "shutdown", + UT_LINESIZE, "~", + UT_HOSTSIZE, _UTX_HOSTSIZE, + bp->ut_host, ct, ct + 11); + if (maxrec != -1 && !--maxrec) + return; + } + continue; + case OLD_TIME: + case NEW_TIME: + if (want(bp, NO)) { + ct = ctime(&bp->ut_tv.tv_sec); + printf("%-*s %-*s %-*.*s %10.10s %5.5s \n", + UT_NAMESIZE, "date", + UT_LINESIZE, bp->ut_type == OLD_TIME ? "|" : "{", + UT_HOSTSIZE, _UTX_HOSTSIZE, bp->ut_host, + ct, ct + 11); + if (maxrec && !--maxrec) + return; + } + continue; + case USER_PROCESS: + case DEAD_PROCESS: + /* find associated tty */ + for (T = ttylist;; T = T->next) { + if (!T) { + /* add new one */ + T = addtty(bp->ut_id, bp->ut_pid); + break; + } + if (!memcmp(T->id, bp->ut_id, _UTX_IDSIZE) && T->pid == bp->ut_pid) + break; + } + if (bp->ut_type != DEAD_PROCESS && want(bp, YES)) { + ct = ctime(&bp->ut_tv.tv_sec); + printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", + UT_NAMESIZE, _UTX_USERSIZE, bp->ut_user, + UT_LINESIZE, _UTX_LINESIZE, bp->ut_line, + UT_HOSTSIZE, _UTX_HOSTSIZE, bp->ut_host, + ct, ct + 11); + if (!T->logout) + puts(" still logged in"); + else { + if (T->logout < 0) { + T->logout = -T->logout; + printf("- %s", crmsg); + } + else + printf("- %5.5s", + ctime(&T->logout)+11); + delta = T->logout - bp->ut_tv.tv_sec; + if (delta < SECSPERDAY) + printf(" (%5.5s)\n", + asctime(gmtime(&delta))+11); + else + printf(" (%ld+%5.5s)\n", + delta / SECSPERDAY, + asctime(gmtime(&delta))+11); + } + if (maxrec != -1 && !--maxrec) + return; + } + T->logout = bp->ut_tv.tv_sec; + continue; + } + } + endutxent_wtmp(); + ct = ctime(prev ? &prev->ut_tv.tv_sec : &now); + printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); +} + +/* + * want -- + * see if want this entry + */ +int +want(bp, check) + struct utmpx *bp; + int check; +{ + ARG *step; + + if (!arglist) + return (YES); + + for (step = arglist; step; step = step->next) + switch(step->type) { + case HOST_TYPE: + if (!strncasecmp(step->name, bp->ut_host, _UTX_HOSTSIZE)) + return (YES); + break; + case TTY_TYPE: + { + char *line = bp->ut_line; + if (check) { + /* + * when uucp and ftp log in over a network, the entry in + * the utmpx file is the name plus their process id. See + * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information. + */ + if (!strncmp(line, "ftp", sizeof("ftp") - 1)) + line = "ftp"; + else if (!strncmp(line, "uucp", sizeof("uucp") - 1)) + line = "uucp"; + } + if (!strncmp(step->name, line, _UTX_LINESIZE)) + return (YES); + break; + } + case USER_TYPE: + if (bp->ut_type == BOOT_TIME && !strncmp(step->name, "reboot", _UTX_USERSIZE)) + return (YES); + if (bp->ut_type == SHUTDOWN_TIME && !strncmp(step->name, "shutdown", _UTX_USERSIZE)) + return (YES); + if (!strncmp(step->name, bp->ut_user, _UTX_USERSIZE)) + return (YES); + break; + } + return (NO); +} + +/* + * addarg -- + * add an entry to a linked list of arguments + */ +void +addarg(type, arg) + int type; + const char *arg; +{ + ARG *cur; + + if (!(cur = (ARG *)malloc((u_int)sizeof(ARG)))) + err(1, "malloc failure"); + cur->next = arglist; + cur->type = type; + cur->name = arg; + arglist = cur; +} + +/* + * addtty -- + * add an entry to a linked list of ttys + */ +TTY * +addtty(id, pid) + const char *id; + pid_t pid; +{ + TTY *cur; + + if (!(cur = (TTY *)malloc((u_int)sizeof(TTY)))) + err(1, "malloc failure"); + cur->next = ttylist; + cur->logout = currentout; + memmove(cur->id, id, _UTX_IDSIZE); + cur->pid = pid; + return (ttylist = cur); +} + +/* + * hostconv -- + * convert the hostname to search pattern; if the supplied host name + * has a domain attached that is the same as the current domain, rip + * off the domain suffix since that's what login(1) does. + */ +void +hostconv(arg) + const char *arg; +{ + static int first = 1; + static char *hostdot, name[MAXHOSTNAMELEN]; + char *argdot; + + if (!(argdot = strchr(arg, '.'))) + return; + if (first) { + first = 0; + if (gethostname(name, sizeof(name))) + err(1, "gethostname"); + hostdot = strchr(name, '.'); + } + if (hostdot && !strcasecmp(hostdot, argdot)) + *argdot = '\0'; +} + +/* + * ttyconv -- + * convert tty to correct name. + */ +const char * +ttyconv(arg) + const char *arg; +{ + char *mval; + int kludge = 0; + int len = strlen(arg); + + /* + * kludge -- we assume that most tty's end with + * a two character suffix. + */ + if (len == 2) + kludge = 8; /* either 6 for "ttyxx" or 8 for "console"; use largest */ + /* + * kludge -- we assume cloning ptys names are "ttys" followed by + * more than one digit + */ + else if (len > 2 && *arg == 's') { + const char *cp = arg + 1; + while(*cp && isdigit(*cp)) + cp++; + if (*cp == 0) + kludge = len + sizeof("tty"); + } + if (kludge) { + if (!(mval = malloc(kludge))) + err(1, "malloc failure"); + if (!strcmp(arg, "co")) + (void)strcpy(mval, "console"); + else { + (void)strcpy(mval, "tty"); + (void)strcpy(mval + sizeof("tty") - 1, arg); + } + return (mval); + } + if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1)) + return (arg + sizeof(_PATH_DEV) - 1); + return (arg); +} + +/* + * onintr -- + * on interrupt, we inform the user how far we've gotten + */ +void +onintr(signo) + int signo; +{ + char *ct; + + ct = ctime(prev ? &prev->ut_tv.tv_sec : &now); + printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); + if (signo == SIGINT) + exit(1); + (void)fflush(stdout); /* fix required for rsh */ +} diff --git a/adv_cmds/locale/locale.1 b/adv_cmds/locale/locale.1 new file mode 100644 index 0000000..e4df365 --- /dev/null +++ b/adv_cmds/locale/locale.1 @@ -0,0 +1,101 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd August 27, 2004 +.Dt LOCALE 1 +.Os Darwin +.Sh NAME +.Nm locale +.Nd display locale settings +.Sh SYNOPSIS +.Nm +.Op Fl a|m +.Nm +.Op Fl ck +.Ar name +.Op ... +.Sh DESCRIPTION +.Nm +displays information about the current locale, or a list of all available +locales. +.Pp +When +.Nm +is run with no arguments, +it will display the current source of each locale category. +.Pp +When +.Nm +is given the name of a category, +it acts as if it had been given each keyword in that category. +For each keyword it is given, the current value +is displayed. +.Sh OPTIONS +.Bl -tag -width -indent +.It Fl a +Lists all public locales. +.It Fl c Ar name ... +Lists the category name before each keyword, +unless it is the same category as the previously displayed keyword. +.It Fl k Ar name ... +Displays the name of each keyword prior to its value. +.It Fl m +Lists all available public charmaps. +Darwin locales do not support charmaps, so list all CODESETs instead. +.El +.Pp +.Sh OPERANDS +The following operand is supported: +.Pp +.Ar name +is the name of a keyword or category to display. A list of all keywords +and categories can be shown with the following command: +.Bd -literal +locale -ck LC_ALL +.Ed +.Pp +.Sh ENVIRONMENT +.Bl -tag -width "LC_MESSAGES" +.It Ev LANG +Used as a substitute for any unset +.Ev LC_* +variable. If +.Ev LANG +is unset, it will act as if set to "C". If any of +.Ev LANG +or +.Ev LC_* +are set to invalid values, +.Nm +acts as if they are all unset. +.It Ev LC_ALL +Will override the setting of all other +.Ev LC_* +variables. +.It Ev LC_COLLATE +Sets the locale for the LC_COLLATE category. +.It Ev LC_CTYPE +Sets the locale for the LC_CTYPE category. +.It Ev LC_MESSAGES +Sets the locale for the LC_MESSAGES category. +.It Ev LC_MONETARY +Sets the locale for the LC_MONETARY category. +.It Ev LC_NUMERIC +Sets the locale for the LC_NUMERIC category. +.It Ev LC_TIME +Sets the locale for the LC_TIME category. +.El +.Sh SEE ALSO +.Xr localedef 1 , +.Xr localeconv 3 , +.Xr nl_langinfo 3 , +.Xr setlocale 3 +.Sh STANDARDS +The +.Nm +utility conforms to IEEE Std 1003.1-2001 (``POSIX.1''). +.Sh HISTORY +.Nm +appeared in Mac OS X 10.4 diff --git a/adv_cmds/locale/locale.cc b/adv_cmds/locale/locale.cc new file mode 100644 index 0000000..88c7784 --- /dev/null +++ b/adv_cmds/locale/locale.cc @@ -0,0 +1,428 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define LAST(array) array + (sizeof(array) / sizeof(*array)) + +#define LC_SPECIAL (LC_COLLATE+LC_CTYPE+LC_MESSAGES+LC_MONETARY+LC_NUMERIC+LC_TIME) + +using namespace std; + +enum vtype { + V_STR, V_NUM +}; + +template string tostr(T val) { + ostringstream ss; + ss << val; + return ss.str(); +} + +string quote(string s) { + return '"' + s + '"'; +} + +class keyword { + public: + virtual string get_category() const { return category; } + virtual string get_keyword() const { return kword; } + virtual string get_value(bool show_quotes) const { + return (show_quotes && t == V_STR) ? quote(value) : value; } + + virtual ~keyword() { } + protected: + keyword(int category_, string kword, string value, vtype t) + : kword(kword), value(value), t(t) { + switch(category_) { + case LC_COLLATE: + category = "LC_COLLATE"; + break; + case LC_CTYPE: + category = "LC_CTYPE"; + break; + case LC_MESSAGES: + category = "LC_MESSAGES"; + break; + case LC_MONETARY: + category = "LC_MONETARY"; + break; + case LC_NUMERIC: + category = "LC_NUMERIC"; + break; + case LC_TIME: + category = "LC_TIME"; + break; + case LC_SPECIAL: + category = "LC_SPECIAL"; + break; + default: + { + ostringstream lc; + lc << "LC_" << category_; + category = lc.str(); + } + break; + } + } + + string category, kword, value; + vtype t; +}; + +struct keyword_cmp { + bool operator()(const keyword *a, const keyword *b) const { + return a->get_category() < b->get_category(); + } +}; + +class li_keyword : public keyword { + public: + li_keyword(int category, string kword, int itemnum, vtype t = V_STR) + : keyword(category, kword, nl_langinfo(itemnum), t) { } +}; + +class lia_keyword : public keyword { + protected: + vector values; + public: + virtual string get_value(bool show_quotes) const { + ostringstream ss; + vector::const_iterator s(values.begin()), e(values.end()), i(s); + + for(; i < e; ++i) { + if (i != s) { + ss << ';'; + } + if (show_quotes && t == V_STR) { + ss << quote(*i); + } else { + ss << *i; + } + } + + return ss.str(); + } + + lia_keyword(int category, string kword, int *s, int *e, vtype t = V_STR) + : keyword(category, kword, "", t) { + for(; s < e; ++s) { + values.push_back(nl_langinfo(*s)); + } + } +}; + +class lc_keyword : public keyword { + public: + lc_keyword(int category, string kword, string value, vtype t = V_STR) + : keyword(category, kword, value, t) { } +}; + +void usage(char *argv0) { + clog << "usage: " << argv0 << "[-a|-m]\n or: " + << argv0 << " [-cCk] name..." << endl; +} + +void list_all_valid_locales() { + string locale_dir("/usr/share/locale"); + bool found_C = false, found_POSIX = false; + DIR *d = opendir(locale_dir.c_str()); + struct dirent *de; + static string expected[] = { "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", + "LC_NUMERIC", "LC_TIME" }; + + for(de = readdir(d); de; de = readdir(d)) { + string lname(de->d_name, de->d_namlen); + string ldir(locale_dir + "/" + lname); + int cnt = 0; + DIR *ld = opendir(ldir.c_str()); + if (ld) { + struct dirent *lde; + for(lde = readdir(ld); lde; lde = readdir(ld)) { + string fname(lde->d_name, lde->d_namlen); + if (LAST(expected) != find(expected, LAST(expected), fname)) { + cnt++; + } + } + closedir(ld); + + if (cnt == LAST(expected) - expected) { + cout << lname << endl; + if (lname == "C") { + found_C = true; + } + if (lname == "POSIX") { + found_POSIX = true; + } + } + } + } + closedir(d); + if (!found_C) { + cout << "C" << endl; + } + if (!found_POSIX) { + cout << "POSIX" << endl; + } +} + +void show_all_unique_codesets() { + string locale_dir("/usr/share/locale"); + DIR *d = opendir(locale_dir.c_str()); + struct dirent *de; + static string expected[] = { "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", + "LC_NUMERIC", "LC_TIME" }; + set codesets; + for(de = readdir(d); de; de = readdir(d)) { + string lname(de->d_name, de->d_namlen); + string ldir(locale_dir + "/" + lname); + int cnt = 0; + DIR *ld = opendir(ldir.c_str()); + if (ld) { + struct dirent *lde; + for(lde = readdir(ld); lde; lde = readdir(ld)) { + string fname(lde->d_name, lde->d_namlen); + if (LAST(expected) != find(expected, LAST(expected), fname)) { + cnt++; + } + } + closedir(ld); + + if (cnt == LAST(expected) - expected) { + locale_t xloc = newlocale(LC_ALL_MASK, lname.c_str(), NULL); + if (xloc) { + char *cs = nl_langinfo_l(CODESET, xloc); + if (cs && *cs && (codesets.find(cs) == codesets.end())) { + cout << cs << endl; + codesets.insert(cs); + } + freelocale(xloc); + } + } + } + } + closedir(d); +} + +typedef map keywords_t; +keywords_t keywords; + +typedef map > catorgies_t; +catorgies_t catoriges; + +void add_kw(keyword *k) { + keywords.insert(make_pair(k->get_keyword(), k)); + catorgies_t::iterator c = catoriges.find(k->get_category()); + if (c != catoriges.end()) { + c->second.push_back(k); + } else { + vector v; + v.push_back(k); + catoriges.insert(make_pair(k->get_category(), v)); + } +} + +string grouping(char *g) { + ostringstream ss; + if (*g == 0) { + ss << "0"; + } else { + ss << static_cast(*g); + while(*++g) { + ss << ";" << static_cast(*g); + } + } + return ss.str(); +} + +void init_keywords() { + struct lconv *lc = localeconv(); + if (lc) { + add_kw(new lc_keyword(LC_NUMERIC, "decimal_point", lc->decimal_point)); + add_kw(new lc_keyword(LC_NUMERIC, "thousands_sep", lc->thousands_sep)); + add_kw(new lc_keyword(LC_NUMERIC, "grouping", grouping(lc->grouping))); + add_kw(new lc_keyword(LC_MONETARY, "int_curr_symbol", lc->int_curr_symbol)); + add_kw(new lc_keyword(LC_MONETARY, "currency_symbol", lc->currency_symbol)); + add_kw(new lc_keyword(LC_MONETARY, "mon_decimal_point", lc->mon_decimal_point)); + add_kw(new lc_keyword(LC_MONETARY, "mon_thousands_sep", lc->mon_thousands_sep)); + add_kw(new lc_keyword(LC_MONETARY, "mon_grouping", grouping(lc->mon_grouping))); + add_kw(new lc_keyword(LC_MONETARY, "positive_sign", lc->positive_sign)); + add_kw(new lc_keyword(LC_MONETARY, "negative_sign", lc->negative_sign)); + add_kw(new lc_keyword(LC_MONETARY, "int_frac_digits", tostr((int)lc->int_frac_digits), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "frac_digits", tostr((int)lc->frac_digits), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "p_cs_precedes", tostr((int)lc->p_cs_precedes), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "p_sep_by_space", tostr((int)lc->p_sep_by_space), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "n_cs_precedes", tostr((int)lc->n_cs_precedes), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "n_sep_by_space", tostr((int)lc->n_sep_by_space), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "p_sign_posn", tostr((int)lc->p_sign_posn), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "n_sign_posn", tostr((int)lc->n_sign_posn), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_p_cs_precedes", tostr((int)lc->int_p_cs_precedes), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_n_cs_precedes", tostr((int)lc->int_n_cs_precedes), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_p_sep_by_space", tostr((int)lc->int_p_sep_by_space), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_n_sep_by_space", tostr((int)lc->int_n_sep_by_space), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_p_sign_posn", tostr((int)lc->int_p_sign_posn), V_NUM)); + add_kw(new lc_keyword(LC_MONETARY, "int_n_sign_posn", tostr((int)lc->int_n_sign_posn), V_NUM)); + } + + int abdays[] = {ABDAY_1, ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7}; + add_kw(new lia_keyword(LC_TIME, "ab_day", abdays, LAST(abdays))); + add_kw(new lia_keyword(LC_TIME, "abday", abdays, LAST(abdays))); + + int days[] = {DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7}; + add_kw(new lia_keyword(LC_TIME, "day", days, LAST(days))); + + int abmons[] = {ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12}; + add_kw(new lia_keyword(LC_TIME, "abmon", abmons, LAST(abmons))); + + int mons[] = {MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12}; + add_kw(new lia_keyword(LC_TIME, "mon", mons, LAST(mons))); + + int am_pms[] = {AM_STR, PM_STR}; + add_kw(new lia_keyword(LC_TIME, "am_pm", am_pms, LAST(am_pms))); + + add_kw(new li_keyword(LC_TIME, "t_fmt_ampm", T_FMT_AMPM)); + add_kw(new li_keyword(LC_TIME, "era", ERA)); + add_kw(new li_keyword(LC_TIME, "era_d_fmt", ERA_D_FMT)); + add_kw(new li_keyword(LC_TIME, "era_t_fmt", ERA_T_FMT)); + add_kw(new li_keyword(LC_TIME, "era_d_t_fmt", ERA_D_T_FMT)); + add_kw(new li_keyword(LC_TIME, "alt_digits", ALT_DIGITS)); + + add_kw(new li_keyword(LC_TIME, "d_t_fmt", D_T_FMT)); + add_kw(new li_keyword(LC_TIME, "d_fmt", D_FMT)); + add_kw(new li_keyword(LC_TIME, "t_fmt", T_FMT)); + + add_kw(new li_keyword(LC_MESSAGES, "yesexpr", YESEXPR)); + add_kw(new li_keyword(LC_MESSAGES, "noexpr", NOEXPR)); + add_kw(new li_keyword(LC_MESSAGES, "yesstr", YESSTR)); + add_kw(new li_keyword(LC_MESSAGES, "nostr", NOSTR)); + + add_kw(new li_keyword(LC_CTYPE, "charmap", CODESET)); + add_kw(new lc_keyword(LC_SPECIAL, "categories", "LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME")); + + // add_kw: CRNCYSTR D_MD_ORDER CODESET RADIXCHAR THOUSEP +} + +void show_keyword(string &last_cat, bool sw_categories, bool sw_keywords, + keyword *k) { + if (sw_categories && last_cat != k->get_category()) { + last_cat = k->get_category(); + cout << last_cat << endl; + } + if (sw_keywords) { + cout << k->get_keyword() << "="; + } + cout << k->get_value(sw_keywords) << endl; +} + +int main(int argc, char *argv[]) { + int sw; + bool sw_all_locales = false, sw_categories = false, sw_keywords = false, + sw_charmaps = false; + + while(-1 != (sw = getopt(argc, argv, "ackm"))) { + switch(sw) { + case 'a': + sw_all_locales = true; + break; + case 'c': + sw_categories = true; + break; + case 'k': + sw_keywords = true; + break; + case 'm': + sw_charmaps = true; + break; + default: + usage(argv[0]); + exit(1); + } + } + + if ((sw_all_locales && sw_charmaps) + || ((sw_all_locales || sw_charmaps) && (sw_keywords || sw_categories)) + ) { + usage(argv[0]); + exit(1); + } + + setlocale(LC_ALL, ""); + + if (!(sw_all_locales || sw_categories || sw_keywords || sw_charmaps) + && argc == optind) { + char *lang = getenv("LANG"); + cout << "LANG=" << quote(lang ? lang : "") << endl; + cout << "LC_COLLATE=" << quote(setlocale(LC_COLLATE, NULL)) << endl; + cout << "LC_CTYPE=" << quote(setlocale(LC_CTYPE, NULL)) << endl; + cout << "LC_MESSAGES=" << quote(setlocale(LC_MESSAGES, NULL)) << endl; + cout << "LC_MONETARY=" << quote(setlocale(LC_MONETARY, NULL)) << endl; + cout << "LC_NUMERIC=" << quote(setlocale(LC_NUMERIC, NULL)) << endl; + cout << "LC_TIME=" << quote(setlocale(LC_TIME, NULL)) << endl; + if (getenv("LC_ALL")) { + cout << "LC_ALL=" << quote(setlocale(LC_ALL, NULL)) << endl; + } else { + cout << "LC_ALL=" << endl; + } + + return 0; + } + + if (sw_all_locales) { + list_all_valid_locales(); + return 0; + } + + if (sw_charmaps) { + show_all_unique_codesets(); + return 0; + } + + init_keywords(); + string last_cat(""); + int exit_val = 0; + for(int i = optind; i < argc; ++i) { + keywords_t::iterator ki = keywords.find(argv[i]); + if (ki != keywords.end()) { + show_keyword(last_cat, sw_categories, sw_keywords, ki->second); + } else { + catorgies_t::iterator ci = catoriges.find(argv[i]); + if (ci != catoriges.end()) { + vector::iterator vi(ci->second.begin()), + ve(ci->second.end()); + for(; vi != ve; ++vi) { + show_keyword(last_cat, sw_categories, sw_keywords, *vi); + } + } else if (argv[i] == string("LC_ALL")) { + ki = keywords.begin(); + keywords_t::iterator ke = keywords.end(); + for(; ki != ke; ++ki) { + show_keyword(last_cat, sw_categories, sw_keywords, ki->second); + } + } else { + if (argv[i] == string("LC_CTYPE") + || argv[i] == string("LC_COLLATE")) { + // It would be nice to print a warning, + // but we aren't allowed (locale.ex test#14) + if (sw_categories) { + cout << argv[i] << endl; + } + } else { + clog << "unknown keyword " + << argv[i] << endl; + exit_val = 1; + } + } + } + } + + return exit_val; +} diff --git a/adv_cmds/localedef/charmap.p-1 b/adv_cmds/localedef/charmap.p-1 new file mode 100644 index 0000000..3901dd9 --- /dev/null +++ b/adv_cmds/localedef/charmap.p-1 @@ -0,0 +1,23 @@ +CHARMAP + \x20 + \x24 + \101 + \141 + \346 + \365 + \300 + \366 + \142 + \102 + \103 + \143 + \347 + \x64 + \x65 + \110 + \150 + \xb7 + \x73 + \x7a + \x65 +END CHARMAP diff --git a/adv_cmds/localedef/charmap.p-2 b/adv_cmds/localedef/charmap.p-2 new file mode 100644 index 0000000..75a3fdf --- /dev/null +++ b/adv_cmds/localedef/charmap.p-2 @@ -0,0 +1,115 @@ +CHARMAP + \000 + \007 + \010 + \011 + \012 + \013 + \014 + \015 + \040 + \041 + \042 + \043 + \044 + \045 + \046 + \047 + \050 + \051 + \052 + \053 + \054 + \055 + \055 + \056 + \056 + \057 + \057 + \060 + \061 + \062 + \063 + \064 + \065 + \066 + \067 + \070 + \071 + \072 + \073 + \074 + \075 + \076 + \077 + \100 + \101 + \102 + \103 + \104 + \105 + \106 + \107 + \110 + \111 + \112 + \113 + \114 + \115 + \116 + \117 +

\160 + \161 + \162 + \163 + \164 + \165 + \166 + \167 + \170 + \171 + \172 + \173 + \173 + \174 + \175 + \175 + \176 + \177 +END CHARMAP diff --git a/adv_cmds/localedef/charmap.test b/adv_cmds/localedef/charmap.test new file mode 100644 index 0000000..fd40463 --- /dev/null +++ b/adv_cmds/localedef/charmap.test @@ -0,0 +1,38 @@ +CHARMAP + 2 + 2 + + \047 + \140 + + \x41 + \102 + C + \104 + "E" + \d70 + + \\ + "" + + \x60\x41 + \x27\x41 + \x60\x61 + \x27\x61 + +... \x12\x34 +END CHARMAP + +WIDTH +... 1 +... 2 + 27 + + 2 + 2 + 2 + 2 + +WIDTH_DEFAULT 1 + +END WIDTH diff --git a/adv_cmds/localedef/def.a55 b/adv_cmds/localedef/def.a55 new file mode 100644 index 0000000..386e1c1 --- /dev/null +++ b/adv_cmds/localedef/def.a55 @@ -0,0 +1,6 @@ +LC_COLLATE +order_start forward +order_start forward;forward;forward + +order_end +END LC_COLLATE diff --git a/adv_cmds/localedef/def.p-1 b/adv_cmds/localedef/def.p-1 new file mode 100644 index 0000000..adef476 --- /dev/null +++ b/adv_cmds/localedef/def.p-1 @@ -0,0 +1,157 @@ +# +LC_CTYPE +lower ;;;;;...; +upper A;B;C;C;...;Z +space \x20;\x09;\x0a;\x0b;\x0c;\x0d +blank \040;\011 +toupper (,);(b,B);(c,C);(c,C);(d,D);(z,Z) +digit 3;2 +END LC_CTYPE +# +LC_COLLATE +# +# The following example of collation is based on the proposed +# Canadian standard Z243.4.1-1990, "Canadian Alphanumeric +# Ordering Standard For Character sets of CSA Z234.4 Standard". +# (Other parts of this example locale definition file do not +# purport to relate to Canada, or to any other real culture.) +# The proposed standard defines a 4-weight collation, such that +# in the first pass, characters are compared without regard to +# case or accents; in second pass, backwards compare without +# regard to case; in the third pass, forward compare without +# regard to diacriticals. In the 3 first passes, non-alphabetic +# characters are ignored; in the fourth pass, only special +# characters are considered, such that "The string that has a +# special character in the lowest position comes first. If two +# strings have a special character in the same position, the +# collation value of the special character determines ordering. +# +# Only a subset of the character set is used here; mostly to +# illustrate the set-up. +# +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# Further collating-symbols follow. +# +# Properly, the standard does not include any multi-character +# collating elements; the one below is added for completeness. +# +collating_element from "" +collating_element from "" +collating_element from "" +collating_element from "" +collating_element from "" +# +order_start forward;backward;forward;forward,position +# +# Collating symbols are specified first in the sequence to allocate +# basic collation values to them, lower than that of any character. + + + + + + + + + + + + + +# Further collating symbols are given a basic collating value here. +# +# Here follow special characters. + IGNORE;IGNORE;IGNORE; +# Other special characters follow here. +# +# Here follow the regular characters. + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";\ + "";IGNORE + "";"";\ + "";IGNORE + ;;;IGNORE +... ...;;;IGNORE + ...;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +# +# As an example, the strings "Bach" and "bach" could be encoded (for +# compare purposes) as: +# "Bach" ;;;;;;\ +# ;;;;; +# "bach" ;;;;;;\ +# ;;;;; +# +# The two strings are equal in pass 1 and 2, but differ in pass 3. +# +# Further characters follow. +# +UNDEFINED IGNORE;IGNORE;IGNORE;IGNORE +# +order_end +# +END LC_COLLATE +# +LC_MONETARY +int_curr_symbol "USD " +currency_symbol "$" +mon_decimal_point "." +mon_grouping 3;0 +positive_sign "" +negative_sign "-" +p_cs_precedes 1 +n_sign_posn 0 +END LC_MONETARY +# +LC_NUMERIC +copy "US_en.ASCII" +decimal_point . +thousands_sep \, +grouping 3;3 +END LC_NUMERIC +# +LC_TIME +abday "Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat" +# +day "Sunday";"Monday";"Tuesday";"Wednesday";\ + "Thursday";"Friday";"Saturday" +# +abmon "Jan";"Feb";"Mar";"Apr";"May";"Jun";\ + "Jul";"Aug";"Sep";"Oct";"Nov";"Dec" +# +mon "January";"February";"March";"April";\ + "May";"June";"July";"August";"September";\ + "October";"November";"December" +# +d_t_fmt "%a %b %d %T %Z %Y\n" +am_pm "Am";"Pm" +END LC_TIME +# +LC_MESSAGES +yesexpr "^([yY][[:alpha:]]*)|(OK)" +# +noexpr "^[nN][[:alpha:]]*" +END LC_MESSAGES diff --git a/adv_cmds/localedef/def.p-2 b/adv_cmds/localedef/def.p-2 new file mode 100644 index 0000000..9b6ee15 --- /dev/null +++ b/adv_cmds/localedef/def.p-2 @@ -0,0 +1,280 @@ +LC_CTYPE +# The following is the POSIX locale LC_CTYPE. +# "alpha" is by default "upper" and "lower" +# "alnum" is by definition "alpha" and "digit" +# "print" is by default "alnum", "punct" and the character +# "graph" is by default "alnum" and "punct" +# +upper ;;;;;;;;;;;;;\ + ;;

;;;;;;;;;; +# +lower ;;;;;;;;;;;;;\ + ;;

;;;;;;;;;; +# +digit ;;;;;;;\ + ;; +# +space ;;;;\ + ; +# +cntrl ;;;;;\ + ;;\ + ;;;;;;;;\ + ;;;;;;;;\ + ;;;;;;;;\ + ; +# +punct ;;;\ + ;;;;\ + ;;;\ + ;;;;;\ + ;;;;\ + ;;;\ + ;;;\ + ;;;;\ + ;; +# +xdigit ;;;;;;;;\ + ;;;;;;;;;;;;; +# +blank ; +# +toupper (,);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);\ + (

,

);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);(,) +# +tolower (,);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);\ + (

,

);(,);(,);(,);(,);\ + (,);(,);(,);(,);(,);(,) +END LC_CTYPE +LC_COLLATE +# This is the POSIX locale definition for the LC_COLLATE category. +# The order is the same as in the ASCII codeset. +order_start forward + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + +order_end +# +END LC_COLLATE +LC_MONETARY +# This is the POSIX locale definition for +# the LC_MONETARY category. +# +int_curr_symbol "" +currency_symbol "" +mon_decimal_point "" +mon_thousands_sep "" +mon_grouping -1 +positive_sign "" +negative_sign "" +int_frac_digits -1 +p_cs_precedes -1 +p_sep_by_space -1 +n_cs_precedes -1 +n_sep_by_space -1 +p_sign_posn -1 +n_sign_posn -1 +# +END LC_MONETARY +LC_NUMERIC +# This is the POSIX locale definition for +# the LC_NUMERIC category. +# +decimal_point "" +thousands_sep "" +grouping -1 +# +END LC_NUMERIC +LC_TIME +# This is the POSIX locale definition for +# the LC_TIME category. +# +# Abbreviated weekday names (%a) +abday "";"";"";"";\ + "";"";"" +# +# Full weekday names (%A) +day "";"";\ + "";"";\ + "";"";\ + "" +# +# Abbreviated month names (%b) +abmon "";"";"";\ + "

";"";"";\ + "";"";"

";\ + "";"";"" +# +# Full month names (%B) +mon "";"";\ + "";"

";\ + "";"";\ + "";"";\ + "

";"";\ + "";"" +# +# Equivalent of AM/PM (%p) "AM";"PM" +am_pm "";"

" +# +# Appropriate date and time representation (%c) +# "%a %b %e %H:%M:%S %Y" +d_t_fmt "\ + \ + \ + " +# +# Appropriate date representation (%x) "%m/%d/%y" +d_fmt "\ + " +# +# Appropriate time representation (%X) "%H:%M:%S" +t_fmt "\ + " +# +# Appropriate 12-hour time representation (%r) "%I:%M:%S %p" +t_fmt_ampm "\ +

" +# +END LC_TIME +LC_MESSAGES +# This is the POSIX locale definition for +# the LC_MESSAGES category. +# +yesexpr "" +# +noexpr "" +# +yesstr "yes" +nostr "no" +END LC_MESSAGES + diff --git a/adv_cmds/localedef/localedef.1 b/adv_cmds/localedef/localedef.1 new file mode 100644 index 0000000..c8f3907 --- /dev/null +++ b/adv_cmds/localedef/localedef.1 @@ -0,0 +1,122 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.Dd September 9, 2004 +.Dt LOCALEDEF 1 +.Os Darwin +.Sh NAME +.Nm localedef +.Nd define locale environment +.Sh SYNOPSIS +.Nm +.Op Fl c +.Op Fl f Ar charmap +.Op Fl i Ar sourcefile +.Ar name +." localedef [-c][-f charmap][-i sourcefile] name +.Sh DESCRIPTION +The +.Nm +utility reads source definitions for one or more locale categories +belonging to the same locale from the file named in the +.Fl i +option (if specified) or from standard input. +.Pp +The +.Ar name +operand identifies the target locale. The +.Nm +utility supports +the creation of public, or generally accessible locales, as well +as private, or restricted-access locales. +.Pp +Each category source definition is identified by the corresponding +environment variable name and terminated by an END category-name +statement. +.Pp +.Bl -tag -width "LC_MONETARY" -compact -offset indent +.It LC_CTYPE +Defines character classification and case conversion. +.It LC_COLLATE +Defines collation rules. +.It LC_MONETARY +Defines the format and symbols used in formatting of monetary information. +.It LC_NUMERIC +Defines the decimal delimiter, grouping, and grouping symbol for non-monetary numeric editing. +.It LC_TIME +Defines the format and content of date and time information. +.It LC_MESSAGES +Defines the format and values of affirmative and negative responses. +.El +.Sh OPTIONS +The following options are supported: +.Pp +.Bl -tag -width -indent +.It Fl c +Create permanent output even if warning messages have been issued. +.It Fl f Ar charmap +Specify the pathname of a file containing a mapping of character symbols and collating element symbols to actual character encodings. +.It Fl i Ar sourcefile +The pathname of a file containing the source definitions. If this option is not present, source definitions will be read from standard input. +.El +.Sh OPERANDS +The following operand is supported: +.Bl -tag -width -indent +.It Ar name +Identifies the locale. +If the name contains one or more slash characters, +.Ar name +will be interpreted as a pathname +where the created locale definitions will be stored. +If +.Ar name +does not contain any slash characters, +the locale will be public. +This capability is restricted to users with appropriate privileges. +(As a consequence of specifying one name, +although several categories can be processed in one execution, +only categories belonging to the same locale can be processed.) +.El +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm : +.Bl -tag -width "LC_COLLATE" +.It Ev LANG +Provide a default value for the internationalization variables +that are unset or null. +If LANG is unset or null, +the corresponding value from the implementation-dependent default locale +will be used. +If any of the internationalization variables contains an invalid setting, +the utility will behave as if none of the variables had been defined. +.It Ev LC_ALL +If set to a non-empty string value, override the values of all the other internationalization variables. +.It Ev LC_COLLATE +(This variable has no effect on +.Nm ; +the POSIX locale will be used for this category.) +.It Ev LC_CTYPE +Determine the locale for the interpretation of sequences of bytes +of text data as characters +(for example, single- as opposed to multi-byte characters +in arguments and input files). +This variable has no effect on the processing of +.Nm +input data; +the POSIX locale is used for this purpose, +regardless of the value of this variable. +.It Ev LC_MESSAGES +Determine the locale that should be used to affect the format and contents of diagnostic messages written to standard error. +.It Ev NLSPATH +Determine the location of message catalogues for the processing of LC_MESSAGES. +.El +.Sh EXIT STATUS +The following exit values are returned: +.Bl -tag -width -indent +.It 0 +No errors occurred and the locales were successfully created. +.It 1 +Warnings occurred and the locales were successfully created. +.It 2 +The locale specification exceeded implementation limits or the coded character set or sets used were not supported by the implementation, and no locale was created. +.It >2 +Warnings or errors occurred and no output was created. +.El diff --git a/adv_cmds/localedef/localedef.pl b/adv_cmds/localedef/localedef.pl new file mode 100644 index 0000000..222eda0 --- /dev/null +++ b/adv_cmds/localedef/localedef.pl @@ -0,0 +1,1166 @@ +#!/usr/bin/perl -w + +use strict; +use Getopt::Std; +use Fcntl qw(O_TRUNC O_CREAT O_WRONLY SEEK_SET); +use File::Temp qw(tempfile); +use IO::File; + +my %opt; +getopts("cf:u:i:", \%opt); + +my $comment_char = "#"; +my $escape_char = "\\"; +my $val_match = undef; # set in set_escape +my %sym = (); +my %width = (); +my %ctype_classes = ( + # there are the charactors that get automagically included, there is no + # standard way to avoid them. XXX even if you have a charset without + # some of these charactors defined! + + # They are accessable in a regex via [:classname:], and libc has a + # isX() for most of these. + upper => {map { ($_, 1); } qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)}, + lower => {map { ($_, 1); } qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)}, + alpha => {}, + #alnum => {}, + digit => {map { ($_, 1); } qw(0 1 2 3 4 5 6 7 8 9)}, + space => {}, + cntrl => {}, + punct => {}, + graph => {}, + print => {}, + xdigit => {map { ($_, 1); } qw(0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f)}, + blank => {" " => 1, "\t" => 1}, + + toupper => {map { ($_, "\U$_"); } qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)}, + tolower => {map { ($_, "\L$_"); } qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)}, +); + +my %cele = ( + # collating-elements -- these are a lot like %sym that only works + # in LC_COLLATE, can also be accessed in a regex via [.element.] +); + +my %csym = ( + # collating-symbols -- these are used to define a set of charactors + # that compare as equals (in one or more passes), can also be accessed + # in a regex via [=symbol=] +); + +my @corder = (); # collating order +my @corder_weights = (); # collating directions (forward, backward, position) + +my @colldef = (); + +my(%monetary, %numeric, %time, %messages); + +# This is the default charmap, unlike %ctype_classes you _can_ avoid this +# merely by having your own charmap definition file +my $default_charmap = < \\000 + \\007 + \\010 + \\011 + \\012 + \\013 + \\014 + \\015 + \\040 + \\041 + \\042 + \\043 + \\044 + \\045 + \\046 + \\047 + \\050 + \\051 + \\052 + \\053 + \\054 + \\055 + \\055 + \\056 + \\056 + \\057 + \\057 + \\060 + \\061 + \\062 + \\063 + \\064 + \\065 + \\066 + \\067 + \\070 + \\071 + \\072 + \\073 + \\074 + \\074 + \\075 + \\076 + \\076 + \\077 + \\100 + \\101 + \\102 + \\103 + \\104 + \\105 + \\106 + \\107 + \\110 + \\111 + \\112 + \\113 + \\114 + \\115 + \\116 + \\117 +

\\120 + \\121 + \\122 + \\123 + \\124 + \\125 + \\126 + \\127 + \\130 + \\131 + \\132 + \\133 + \\134 + \\134 + \\135 + \\136 + \\136 + \\137 + \\137 + \\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 + \\173 + \\174 + \\175 + \\175 + \\176 + \\177 + + \\x01 + \\x02 + \\x03 + \\x04 + \\x05 + \\x06 + \\x07 + \\x08 + \\x09 + \\x0a + \\x0b + \\x0c + \\x0d + \\x0e + \\x0f + \\x10 + \\x11 + \\x12 + \\x13 + \\x14 + \\x15 + \\x16 + \\x17 + \\x18 + \\x19 + \\x1a + \\x1b + \\x1c + \\x1c + \\x1d + \\x1d + \\x1e + \\x1e + \\x1f + \\x1f +END CHARMAP +EOT + +&set_escape($escape_char); + +use strict qw(vars); + +if (@ARGV != 1) { + &exit(4, "usage: $0 [-c] [-f charmap-file] [-u codesetname] [-i localdef-file] LOCALENAME\n"); +} + +my $locale_dir = $ARGV[0]; +$locale_dir = "/usr/share/locale/$locale_dir" unless ($locale_dir =~ m{/}); + +my $CMAP; +if (defined($opt{'f'})) { + # Using new IO::File $opt{'f'}, "r" runs into problems with long path names + sysopen(CMAP_KLUDGE, $opt{'f'}, O_RDONLY) || &exit(4, "Can't open $opt{f}: $!\n"); + $CMAP = new IO::Handle; + $CMAP->fdopen(fileno(CMAP_KLUDGE), "r") || &exit(4, "Can't fdopen $opt{f}: $!\n"); +} else { + # er, not everyone gets IO::Scalar, so use an unamed tmp file + # $CMAP = new IO::Scalar \$default_charmap; + $CMAP = new_tmpfile IO::File; + print $CMAP $default_charmap; + seek $CMAP, 0, SEEK_SET; +} + +while(<$CMAP>) { + if (m/^\s*CHARMAP\s*$/) { + &parse_charmaps(); + } elsif (m/^\s*WIDTH\s*$/) { + &parse_widths(); + } elsif (m/^\s*($comment_char.*)?$/) { + } else { + chomp; + &exit(4, "syntax error on line $. ($_)"); + } +} +&parse_widths() if (0 == %width); + +if (defined($opt{'i'})) { + sysopen(STDIN, $opt{'i'}, 0) || &exit(4, "Can't open localdef file $opt{i}: $!"); +} else { + $opt{'i'} = "/dev/stdin"; +} + +my %LC_parsers = ( + NONE => [\&parse_LC_NONE, qr/^\s*((escape|comment)_char\s+$val_match\s*)?$/], + CTYPE => [\&parse_LC_CTYPE, qr/^\s*(\S+)\s+(\S+.*?)\s*$/], + COLLATE => [\&parse_LC_COLLATE, qr/^\s*(<[^>\s]+>|order_end|END|(\S*)\s+(\S+.*?)|collating[_-]element\s*<[^>]+>\s+from\s+$val_match)\s*$/, 1], + TIME => [\&parse_LC_TIME, qr/^\s*(ab_?day|day|abmon|mon|d_t_fmt|d_fmt|t_fmt|am_pm|t_fmt_ampm|era|era_d_fmt|era_t_fmt|era_d_t_fmt|alt_digits|copy|END)\s+(\S+.*?)\s*$/], + NUMERIC => [\&parse_LC_NUMERIC, qr/^\s*(decimal_point|thousands_sep|grouping|END|copy)\s+(\S+.*?)\s*$/], + MONETARY => [\&parse_LC_MONETARY, qr/^\s*(int_curr_symbol|currency_symbol|mon_decimal_point|mon_thousands_sep|mon_grouping|positive_sign|negative_sign|int_frac_digits|frac_digits|p_cs_precedes|p_sep_by_space|n_cs_precedes|n_sep_by_space|p_sign_posn|n_sign_posn|int_p_cs_precedes|int_n_cs_precedes|int_p_sep_by_space|int_n_sep_by_space|int_p_sign_posn|int_n_sign_posn|copy|END)\s+(\S+.*?)\s*$/], + MESSAGES => [\&parse_LC_MESSAGES, qr/^\s*(END|yesexpr|noexpr|yesstr|nostr|copy)\s+(\S+.*?)\s*$/], + "COLLATE order" => [\&parse_collate_order, qr/^\s*(order_end|(<[^>\s]+>|UNDEFINED|\Q...\E)(\s+\S+.*)?)\s*$/], +); +my($current_LC, $parse_func, $validate_line, $call_parse_on_END) + = ("NONE", $LC_parsers{"NONE"}->[0], $LC_parsers{"NONE"}->[1], undef); + +while() { + next if (m/^\s*($comment_char.*)?\s*$/); + if (m/\Q$escape_char\E$/) { + chomp; + chop; + my $tmp = ; + if (!defined($tmp)) { + &exit(4, "Syntax error, last line ($.) of $opt{i} is marked as a continued line\n"); + } + $tmp =~ s/^\s*//; + $_ .= $tmp; + redo; + } + + if ($current_LC eq "NONE" && m/^\s*LC_([A-Z]+)\s*$/) { + &set_parser($1); + next; + } + + unless (m/$validate_line/) { + &exit(4, "Syntax error on line $. of $opt{i}\n"); + } + + my($action, $args); + if (m/^\s*(\S*)(\s+(\S+.*?))?\s*$/) { + ($action, $args) = ($1, $3); + } else { + $action = $_; + chomp $action; + } + + if ($action eq "END") { + if ($args ne "LC_$current_LC" || $current_LC eq "NONE") { + &exit(4, "Syntax error on line $. of $opt{i} attempting to end $args when LC_$current_LC is open\n"); + } + if ($call_parse_on_END) { + &{$parse_func}($action, $args); + } + &set_parser("NONE"); + } else { + &{$parse_func}($action, $args); + } +} + +mkdir($locale_dir); +&run_mklocale(); +&write_lc_money(); +&write_lc_time(); +&write_lc_messages(); +&write_lc_numeric(); +&write_lc_collate(); +exit 0; + +sub parse_charmaps { + while(<$CMAP>) { + # XXX need to parse out , , , + # , and before the generic " val" + if (m/^\s*<([\w\-]+)>\s+($val_match+)\s*$/) { + my($sym, $val) = ($1, $2); + $val = &parse_value_double_backwhack($val); + $sym{$sym} = $val; + } elsif (m/^\s*<([\w\-]*\d)>\s*\Q...\E\s*<([\w\-]*\d)>\s+($val_match+)\s*$/) { + # We don't deal with $se < $ss, or overflow of the last byte of $vs + # then again the standard doesn't say anything in particular needs + # to happen for those cases + my($ss, $se, $vs) = ($1, $2, $3); + $vs = &parse_value_double_backwhack($vs); + my $vlast = length($vs) -1; + for(my($s, $v) = ($ss, $vs); $s cmp $se; $s++) { + $sym{$s} = $v; + substr($v, $vlast) = chr(ord(substr($v, $vlast)) +1) + } + } elsif (m/^\s*END\s+CHARMAP\s*$/) { + return; + } elsif (m/^\s*($comment_char.*)?$/) { + } else { + &exit(4, "syntax error on line $."); + } + } +} + +sub parse_widths { + my $default = 1; + my @syms; + + while(<$CMAP>) { + if (m/^\s*<([\w\-]+)>\s+(\d+)\s*$/) { + my($sym, $w) = ($1, $2); + print "$sym width $w\n"; + if (!defined($sym{$sym})) { + warn "localedef: can't set width of unknown symbol $sym on line $.\n"; + } else { + $width{$sym} = $w; + } + } elsif (m/^\s*<([\w\-]+)>\s*\Q...\E\s*<([\w\-]+)>\s+(\d+)\s*$/) { + my($ss, $se, $w) = ($1, $2, $3); + if (!@syms) { + @syms = sort { $a cmp $b } keys(%sym); + } + + # Yes, we could do a binary search for find $ss in @syms + foreach my $s (@syms) { + if (($s cmp $ss) >= 0) { + last if (($s cmp $se) > 0); + } + } + } elsif (m/^\s*WIDTH_DEFAULT\s+(\d+)\s*$/) { + $default = $1; + } elsif (m/^\s*END\s+WIDTH\s*$/) { + last; + } elsif (m/^\s*($comment_char.*)?$/) { + } else { + &exit(4, "syntax error on line $."); + } + } + + foreach my $s (keys(%sym)) { + if (!defined($width{$s})) { + $width{$s} = $default; + } + } +} + +# This parses a single value in any of the 7 forms it can appear in, +# returns [0] the parsed value and [1] the remander of the string +sub parse_value_return_extra { + my $val = ""; + local($_) = $_[0]; + + while(1) { + $val .= &unsym($1), next + if (m/\G"((?:[^"\Q$escape_char\E]+|\Q$escape_char\E.)*)"/gc); + $val .= chr(oct($1)), next + if (m/\G\Q$escape_char\E([0-7]+)/gc); + $val .= chr(0+$1), next + if (m/\G\Q$escape_char\Ed([0-9]+)/gc); + $val .= pack("H*", $1), next + if (m/\G\Q$escape_char\Ex([0-9a-fA-F]+)/gc); + $val .= $1, next + if (m/\G([^,;<>\s\Q$escape_char()\E])/gc); + $val .= $1 + if (m/\G(?:\Q$escape_char\E)([,;<>\Q$escape_char()\E])/gc); + $val .= &unsym($1), next + if (m/\G(<[^>]+>)/gc); + + m/\G(.*)$/; + + return ($val, $1); + } +} + +# Parse one value, if there is more then one value alert the media +sub parse_value { + my ($ret, $err) = &parse_value_return_extra($_[0]); + if ($err ne "") { + &exit(4, "Syntax error, unexpected '$err' in value (after '$ret') on line $.\n"); + } + + return $ret; +} + +sub parse_value_double_backwhack { + my($val) = @_; + + my ($ret, $err) = &parse_value_return_extra($val); + return $ret if ($err eq ""); + + $val =~ s{\\\\}{\\}g; + ($ret, $err) = &parse_value_return_extra($val); + if ($err ne "") { + &exit(4, "Syntax error, unexpected '$err' in value (after '$ret') on line $.\n"); + } + + return $ret; +} +# $values is the string to parse, $dot_expand is a function ref that will +# return an array to insert when "X;...;Y" is parsed (undef means that +# construct is a syntax error), $nest is true if parens indicate a nested +# value string should be parsed and put in an array ref, $return_extra +# is true if any unparsable trailing junk should be returned as the last +# element (otherwise it is a syntax error). Any text matching the regex +# $specials is returned as an hash. +sub parse_values { + my($values, $sep, $dot_expand, $nest, $return_extra, $specials) = @_; + my(@ret, $live_dots); + + while($values ne "") { + if (defined($specials) && $values =~ s/^($specials)($sep|$)//) { + push(@ret, { $1, undef }); + next; + } + if ($nest && $values =~ s/^\(//) { + my @subret = &parse_values($values, ',', $dot_expand, $nest, 1, $specials); + $values = pop(@subret); + push(@ret, [@subret]); + unless ($values =~ s/^\)($sep)?//) { + &exit(4, "Syntax error, unmatched open paren on line $. of $opt{i}\n"); + } + next; + } + + my($v, $l) = &parse_value_return_extra($values); + $values = $l; + + if ($live_dots) { + splice(@ret, -1, 1, &{$dot_expand}($ret[$#ret], $v)); + $live_dots = 0; + } else { + push(@ret, $v); + } + + if (defined($dot_expand) && $values =~ s/^$sep\Q...\E$sep//) { + $live_dots = 1; + } elsif($values =~ s/^$sep//) { + # Normal case + } elsif($values =~ m/^$/) { + last; + } else { + last if ($return_extra); + &exit(4, "Syntax error parsing arguments on line $. of $opt{i}\n"); + } + } + + if ($live_dots) { + splice(@ret, -1, 1, &{$dot_expand}($ret[$#ret], undef)); + } + if ($return_extra) { + push(@ret, $values); + } + + return @ret; +} + +sub parse_LC_NONE { + my($cmd, $arg) = @_; + + if ($cmd eq "comment_char") { + $comment_char = &parse_value($arg); + } elsif($cmd eq "escape_char") { + &set_escape_char(&parse_value($arg)); + } elsif($cmd eq "") { + } else { + &exit(4, "Syntax error on line $. of $opt{i}\n"); + } +} + +sub parse_LC_CTYPE { + my($cmd, $arg) = @_; + + my $ctype_classes = join("|", keys(%ctype_classes)); + if ($cmd eq "copy") { + # XXX -- the locale command line utility doesn't currently + # output any LC_CTYPE info, so there isn't much of a way + # to implent copy yet + &exit(2, "copy not supported on line $. of $opt{i}\n"); + } elsif($cmd eq "charclass") { + my $cc = &parse_value($arg); + if (!defined($ctype_classes{$cc})) { + $ctype_classes{$cc} = []; + } else { + warn "charclass $cc defined more then once\n"; + } + } elsif($cmd =~ m/^to(upper|lower)$/) { + my @arg = &parse_values($arg, ';', undef, 1); + foreach my $p (@arg) { + &exit(4, "Syntax error on line $. of $opt{i} ${cmd}'s arguments must be character pairs like (a,A);(b,B)\n") if ("ARRAY" ne ref $p || 2 != @$p); + } + foreach my $pair (@arg) { + $ctype_classes{$cmd}{$pair->[0]} = $pair->[1]; + } + } elsif($cmd =~ m/^($ctype_classes)$/) { + my @arg = &parse_values($arg, ';', \&dot_expand, 0); + foreach my $c (@arg) { + $ctype_classes{$1}->{$c} = 1; + } + } elsif($cmd =~ "END") { + &add_to_ctype_class('alpha', keys(%{$ctype_classes{'lower'}})); + &add_to_ctype_class('alpha', keys(%{$ctype_classes{'upper'}})); + foreach my $c (qw(alpha lower upper)) { + foreach my $d (qw(cntrl digit punct space)) { + &deny_in_ctype_class($c, $d, keys(%{$ctype_classes{$d}})); + } + } + + &add_to_ctype_class('space', keys(%{$ctype_classes{'blank'}})); + foreach my $d (qw(upper lower alpha digit graph xdigit)) { + &deny_in_ctype_class('space', $d, keys(%{$ctype_classes{$d}})); + } + + foreach my $d (qw(upper lower alpha digit punct graph print xdigit)) { + &deny_in_ctype_class('cntrl', $d, keys(%{$ctype_classes{$d}})); + } + + foreach my $d (qw(upper lower alpha digit cntrl xdigit space)) { + &deny_in_ctype_class('punct', $d, keys(%{$ctype_classes{$d}})); + } + + foreach my $c (qw(graph print)) { + foreach my $a (qw(upper lower alpha digit xdigit punct)) { + &add_to_ctype_class($c, keys(%{$ctype_classes{$a}})); + } + foreach my $d (qw(cntrl)) { + &deny_in_ctype_class($c, $d, keys(%{$ctype_classes{$d}})); + } + } + &add_to_ctype_class('print', keys(%{$ctype_classes{'space'}})); + + # Yes, this is a requirment of the standard + &exit(2, "The digit class must have exactly 10 elements\n") if (10 != values(%{$ctype_classes{'digit'}})); + foreach my $d (values %{$ctype_classes{'digit'}}) { + if (!defined $ctype_classes{'xdigits'}->{$d}) { + &exit(4, "$d isn't in class xdigits, but all digits must appaer in xdigits\n"); + } + } + + $ctype_classes{'alnum'} = {} unless defined $ctype_classes{'alnum'}; + foreach my $a (qw(alpha digit)) { + &add_to_ctype_class('alnum', keys(%{$ctype_classes{$a}})); + } + + } else { + &exit(4, "Syntax error on line $. of $opt{i}\n"); + } +} + +sub parse_LC_COLLATE { + my ($cmd, $arg) = @_; + if (defined($arg) && $arg ne "") { + push(@colldef, "$cmd $arg"); + } else { + push(@colldef, "$cmd"); + } +} + +sub parse_collate_order { + my($cmd, $arg) = @_; + + if ($cmd =~ m/order[-_]end/) { + # restore the parent parser + &set_parser("COLLATE"); + my $undef_at; + for(my $i = 0; $i <= $#corder; ++$i) { + next unless "ARRAY" eq ref($corder[$i]); + # If ... appears as the "key" for a order entry it means the + # rest of the line is duplicated once for everything in the + # open ended range (key-pev-line, key-next-line). Any ... + # in the weight fields are delt with by &fixup_collate_order_args + if ($corder[$i]->[0] eq "...") { + my(@sym, $from, $to); + + my @charset = sort { $sym{$a} cmp $sym{$b} } keys(%sym); + if ($i != 0) { + $from = $corder[$i -1]->[0]; + } else { + $from = $charset[0]; + } + if ($i != $#corder) { + $to = $corder[$i +1]->[0]; + } else { + $to = $charset[$#charset]; + } + + my @expand; + my($s, $e) = (&parse_value($from), &parse_value($to)); + foreach my $c (@charset) { + if (($sym{$c} cmp $s) > 0) { + last if (($sym{$c} cmp $e) >= 0); + my @entry = @{$corder[$i]}; + $entry[0] = "<$c>"; + push(@expand, \@entry); + } + } + splice(@corder, $i, 1, @expand); + } elsif($corder[$i]->[0] eq "UNDEFINED") { + $undef_at = $i; + next; + } + &fixup_collate_order_args($corder[$i]); + } + + if ($undef_at) { + my @insert; + my %cused = map { ("ARRAY" eq ref $_) ? ($_->[0], undef) : () } @corder; + foreach my $s (keys(%sym)) { + next if (exists $cused{"<$s>"}); + my @entry = @{$corder[$undef_at]}; + $entry[0] = "<$s>"; + &fixup_collate_order_args(\@entry); + push(@insert, \@entry); + } + splice(@corder, $undef_at, 1, @insert); + } + } elsif((!defined $arg) || $arg eq "") { + if (!exists($csym{$cmd})) { + my($decode, $was_sym) = &unsym_with_check($cmd); + if ($was_sym) { + my %dots = ( "..." => undef ); + my @dots = (\%dots) x (0+@corder_weights); + push(@corder, [$cmd, @dots]); + } else { + warn "Undefined collation symbol $cmd used on line $. of $opt{i}\n"; + } + } else { + push(@corder, $cmd); + } + } else { + unless (defined($cele{$cmd} || defined $sym{$cmd})) { + warn "Undefined collation element or charset sym $cmd used on line $. of $opt{i}\n"; + } else { + # This expands all the symbols (but not colating elements), which + # makes life easier for dealing with ..., but harder for + # outputing the actual table at the end where we end up + # converting literal sequences back into symbols in some cases + my @args = &parse_values($arg, ';', undef, 0, 0, + qr/IGNORE|\Q...\E/); + + if (@args != @corder_weights) { + if (@args < @corder_weights) { + &exit(4, "Only " . (0 + @args) + . " weights supplied on line $. of $opt{i}, needed " + . (0 + @corder_weights) + . "\n"); + } else { + &exit(4, "Too many weights supplied on line $. of $opt{i}," + . " wanted " . (0 + @corder_weights) . " but had " + . (0 + @args) + . "\n"); + } + } + + push(@corder, [$cmd, @args]); + } + } +} + +sub parse_LC_MONETARY { + my($cmd, $arg) = @_; + + if ($cmd eq "copy") { + &do_copy(&parse_value($arg)); + } elsif($cmd eq "END") { + } elsif($cmd eq "mon_grouping") { + my @v = &parse_values($arg, ';', undef, 0); + $monetary{$cmd} = \@v; + } else { + my $v = &parse_value($arg); + $monetary{$cmd} = $v; + } +} + +sub parse_LC_MESSAGES { + my($cmd, $arg) = @_; + + if ($cmd eq "copy") { + &do_copy(&parse_value($arg)); + } elsif($cmd eq "END") { + } else { + my $v = &parse_value($arg); + $messages{$cmd} = $v; + } +} + +sub parse_LC_NUMERIC { + my($cmd, $arg) = @_; + + if ($cmd eq "copy") { + &do_copy(&parse_value($arg)); + } elsif($cmd eq "END") { + } elsif($cmd eq "grouping") { + my @v = &parse_values($arg, ';', undef, 0); + $numeric{$cmd} = \@v; + } else { + my $v = &parse_value($arg); + $numeric{$cmd} = $v; + } +} + +sub parse_LC_TIME { + my($cmd, $arg) = @_; + + $cmd =~ s/^ab_day$/abday/; + + if ($cmd eq "copy") { + &do_copy(&parse_value($arg)); + } elsif($cmd eq "END") { + } elsif($cmd =~ m/abday|day|mon|abmon|am_pm|alt_digits/) { + my @v = &parse_values($arg, ';', undef, 0); + $time{$cmd} = \@v; + } elsif($cmd eq "era") { + my @v = &parse_values($arg, ':', undef, 0); + $time{$cmd} = \@v; + } else { + my $v = &parse_value($arg); + $time{$cmd} = $v; + } +} + + +############################################################################### + +sub run_mklocale { + my $L = (new IO::File "|/usr/bin/mklocale -o $locale_dir/LC_CTYPE") || &exit(5, "$0: Can't start mklocale $!\n"); + if (defined($opt{'u'})) { + $L->print(qq{ENCODING "$opt{u}"\n}); + } else { + if ($ARGV[0] =~ m/(big5|euc|gb18030|gb2312|gbk|mskanji|utf-8)/i) { + my $enc = uc($1); + $L->print(qq{ENCODING "$enc"\n}); + } elsif($ARGV[0] =~ m/utf8/) { + $L->print(qq{ENCODING "UTF-8"\n}); + } else { + $L->print(qq{ENCODING "NONE"\n}); + } + } + foreach my $class (keys(%ctype_classes)) { + unless ($class =~ m/^(tolower|toupper|alpha|control|digit|grah|lower|space|upper|xdigit|blank|print|ideogram|special|phonogram)$/) { + $L->print("# skipping $class\n"); + next; + } + + if (!%{$ctype_classes{$class}}) { + $L->print("# Nothing in \U$class\n"); + next; + } + + if ($class =~ m/^to/) { + my $t = $class; + $t =~ s/^to/map/; + $L->print("\U$t "); + + foreach my $from (keys(%{$ctype_classes{$class}})) { + $L->print("[", &hexchars($from), " ", + &hexchars($ctype_classes{$class}->{$from}), "] "); + } + } else { + $L->print("\U$class "); + + foreach my $rune (keys(%{$ctype_classes{$class}})) { + $L->print(&hexchars($rune), " "); + } + } + $L->print("\n"); + } + + my @width; + foreach my $s (keys(%width)) { + my $w = $width{$s}; + $w = 3 if ($w > 3); + push(@{$width[$w]}, &hexchars($sym{$s})); + } + for(my $w = 0; $w <= $#width; ++$w) { + next if (!defined $width[$w]); + next if (0 == @{$width[$w]}); + $L->print("SWIDTH$w ", join(" ", @{$width[$w]}), "\n"); + } + + if (!$L->close()) { + if (0 == $!) { + &exit(5, "Bad return from mklocale $?"); + } else { + &exit(5, "Couldn't close mklocale pipe: $!"); + } + } +} + +############################################################################### + +sub hexchars { + my($str) = $_[0]; + my($ret); + + $ret = unpack "H*", $str; + &exit(2, "Rune >4 bytes ($ret; for $str)") if (length($ret) > 8); + + return "0x" . $ret; +} + +sub hexseq { + my($str) = $_[0]; + my($ret); + + $ret = unpack "H*", $str; + $ret =~ s/(..)/\\x$1/g; + + return $ret; +} + +# dot_expand in the target charset +sub dot_expand { + my($s, $e) = @_; + my(@ret); + + my @charset = sort { $a cmp $b } values(%sym); + foreach my $c (@charset) { + if (($c cmp $s) >= 0) { + last if (($c cmp $e) > 0); + push(@ret, $c); + } + } + + return @ret; +} + +# Convert symbols into literal values +sub unsym { + my @ret = &unsym_with_check(@_); + return $ret[0]; +} + +# Convert symbols into literal values (return[0]), and a count of how +# many symbols were converted (return[1]). +sub unsym_with_check { + my($str) = $_[0]; + + my $rx = join("|", keys(%sym)); + return ($str, 0) if ($rx eq ""); + my $found = $str =~ s/<($rx)>/$sym{$1}/eg; + + return ($str, $found); +} + +# Convert a string of literals back into symbols. It is an error +# for there to be literal values that can't be mapped back. The +# converter uses a gredy algo. It is likely this could be done +# more efficently with a regex ctrated at runtime. It would also be +# a good idea to only create %rsym if %sym changes, but that isn't +# the simplest thing to do in perl5. +sub resym { + my($str) = $_[0]; + my(%rsym, $k, $v); + my $max_len = 0; + my $ret = ""; + + while(($k, $v) = each(%sym)) { + # Collisions in $v are ok, we merely need a mapping, not the + # identical mapping + $rsym{$v} = $k; + $max_len = length($v) if (length($v) > $max_len); + } + + SYM: while("" ne $str) { + foreach my $l ($max_len .. 1) { + next if ($l > length($str)); + my $s = substr($str, 0, $l); + if (defined($rsym{$s})) { + $ret .= "<" . $rsym{$s} . ">"; + substr($str, 0, $l) = ""; + next SYM; + } + } + &exit(4, "Can't convert $str ($_[0]) back into symbolic form\n"); + } + + return $ret; +} + +sub set_escape { + $escape_char = $_[0]; + $val_match = qr/"(?:[^"\Q$escape_char\E]+|\Q$escape_char\E")+"|(?:\Q$escape_char\E(?:[0-7]+|d[0-9]+|x[0-9a-fA-F]+))|[^,;<>\s\Q$escape_char\E]|(?:\Q$escape_char\E)[,;<>\Q$escape_char\E]/; +} + +sub set_parser { + my $section = $_[0]; + ($current_LC, $parse_func, $validate_line, $call_parse_on_END) + = ($section, $LC_parsers{$section}->[0], $LC_parsers{$section}->[1], + $LC_parsers{$section}->[2]); + unless (defined $parse_func) { + &exit(4, "Unknown section name LC_$section on line $. of $opt{i}\n"); + } +} + +sub do_copy { + my($from) = @_; + local($ENV{LC_ALL}) = $from; + + my $C = (new IO::File "/usr/bin/locale -k LC_$current_LC |") || &exit(5, "can't fork locale during copy of LC_$current_LC"); + while(<$C>) { + if (s/=\s*$/ ""/ || s/=/ /) { + if (m/$validate_line/ && m/^\s*(\S*)(\s+(\S+.*?))?\s*$/) { + my($action, $args) = ($1, $3); + &{$parse_func}($action, $args); + } else { + &exit(4, "Syntax error on line $. of locale -k output" + . " during copy $current_LC\n"); + } + } else { + &exit(4, "Ill-formed line $. from locale -k during copy $current_LC\n"); + } + } + $C->close() || &exit(5, "copying LC_$current_LC from $from failed"); +} + +sub fixup_collate_order_args { + my $co = $_[0]; + + foreach my $s (@{$co}[1..$#{$co}]) { + if ("HASH" eq ref($s) && exists($s->{"..."})) { + $s = $co->[0]; + } + } +} + +sub add_to_ctype_class { + my($class, @runes) = @_; + + my $c = $ctype_classes{$class}; + foreach my $r (@runes) { + $c->{$r} = 2 unless exists $c->{$r}; + } +} + +sub deny_in_ctype_class { + my($class, $deny_reason, @runes) = @_; + + my $c = $ctype_classes{$class}; + foreach my $r (@runes) { + next unless exists $c->{$r}; + $deny_reason =~ s/^(\S+)$/can't belong in class $class and in class $1 at the same time/; + &exit(4, &hexchars($r) . " " . $deny_reason . "\n"); + } +} + +# write_lc_{money,time,messages} all use the existing Libc format, which +# is raw text with each record terminated by a newline, and records +# in a predetermined order. + +sub write_lc_money { + my $F = (new IO::File "$locale_dir/LC_MONETARY", O_TRUNC|O_WRONLY|O_CREAT, 0666) || &exit(4, "$0 can't create $locale_dir/LC_MONETARY: $!"); + foreach my $s (qw(int_curr_symbol currency_symbol mon_decimal_point mon_thousands_sep mon_grouping positive_sign negative_sign int_frac_digits frac_digits p_cs_precedes p_sep_by_space n_cs_precedes n_sep_by_space p_sign_posn n_sign_posn int_p_cs_precedes int_n_cs_precedes int_p_sep_by_space int_n_sep_by_space int_p_sign_posn int_n_sign_posn)) { + if (exists $monetary{$s}) { + my $v = $monetary{$s}; + if ("ARRAY" eq ref $v) { + $F->print(join(";", @$v), "\n"); + } else { + $F->print("$v\n"); + } + } else { + if ($s =~ m/^(int_curr_symbol|currency_symbol|mon_decimal_point|mon_thousands_sep|positive_sign|negative_sign)$/) { + $F->print("\n"); + } else { + $F->print("-1\n"); + } + } + } +} + +sub write_lc_time { + my $F = (new IO::File "$locale_dir/LC_TIME", O_TRUNC|O_WRONLY|O_CREAT, 0666) || &exit(4, "$0 can't create $locale_dir/LC_TIME: $!"); + my %array_cnt = (abmon => 12, mon => 12, abday => 7, day => 7, alt_month => 12, am_pm => 2); + + $time{"md_order"} = "md" unless defined $time{"md_order"}; + + foreach my $s (qw(abmon mon abday day t_fmt d_fmt d_t_fmt am_pm d_t_fmt mon md_order t_fmt_ampm)) { + my $cnt = $array_cnt{$s}; + my $v = $time{$s}; + + if (defined $v) { + if (defined $cnt) { + my @a = @{$v}; + &exit(4, "$0: $s has " . (0 + @a) + . " elements, it needs to have exactly $cnt\n") + unless (@a == $cnt); + $F->print(join("\n", @a), "\n"); + } else { + $F->print("$v\n"); + } + } else { + $cnt = 1 if !defined $cnt; + $F->print("\n" x $cnt); + } + } +} + +sub write_lc_messages { + mkdir("$locale_dir/LC_MESSAGES"); + my $F = (new IO::File "$locale_dir/LC_MESSAGES/LC_MESSAGES", O_TRUNC|O_WRONLY|O_CREAT, 0666) || &exit(4, "$0 can't create $locale_dir/LC_MESSAGES/LC_MESSAGES: $!"); + + foreach my $s (qw(yesexpr noexpr yesstr nostr)) { + my $v = $messages{$s}; + + if (defined $v) { + $F->print("$v\n"); + } else { + $F->print("\n"); + } + } +} + +sub write_lc_numeric { + my $F = (new IO::File "$locale_dir/LC_NUMERIC", O_TRUNC|O_WRONLY|O_CREAT, 0666) || &exit(4, "$0 can't create $locale_dir/LC_NUMERIC: $!"); + + foreach my $s (qw(decimal_point thousands_sep grouping)) { + if (exists $numeric{$s}) { + my $v = $numeric{$s}; + if ("ARRAY" eq ref $v) { + $F->print(join(";", @$v), "\n"); + } else { + $F->print("$v\n"); + } + } else { + $F->print("\n"); + } + } +} + +sub bylenval { + return 0 if ("ARRAY" ne ref $a || "ARRAY" ne ref $b); + + my($aval, $af) = &unsym_with_check($a->[0]); + $aval = $cele{$a->[0]} unless $af; + my($bval, $bf) = &unsym_with_check($b->[0]); + $bval = $cele{$b->[0]} unless $bf; + + my $r = length($aval) - length($bval); + return $r if $r; + return $aval cmp $bval; +} + +sub write_lc_collate { + return unless @colldef; + + # colldef doesn't parse the whole glory of SuSv3 charmaps, and we + # already have, so we cna spit out a simplifyed one; unfortunitly + # it doesn't like "/dev/fd/N" so we need a named tmp file + my($CMAP, $cmapname) = tempfile(DIR => "/tmp"); + foreach my $s (keys(%sym)) { + $CMAP->print("<$s>\t", sprintf "\\x%02x\n", ord($sym{$s})); + } + $CMAP->flush(); + unshift(@colldef, qq{charmap $cmapname}); + unshift(@colldef, "LC_COLLATE"); + $colldef[$#colldef] = "END LC_COLLATE"; + + # Can't just use /dev/stdin, colldef appears to use seek, + # and even seems to need a named temp file (re-open?) + my($COL, $colname) = tempfile(DIR => "/tmp"); + $COL->print(join("\n", @colldef), "\n"); + $COL->flush(); + + my $rc = system( + "/usr/bin/colldef -o $locale_dir/LC_COLLATE $colname"); + unlink $colname, $cmapname; + if ($rc) { + &exit(1, "Bad return from colldef $rc"); + } +} + +# Pack an int of unknown size into a series of bytes, each of which +# contains 7 bits of data, and the top bit is clear on the last +# byte of data. Also works on arrays -- does not encode the size of +# the array. This format is great for data that tends to have fewer +# then 21 bits. +sub pack_p_int { + if (@_ > 1) { + my $ret = ""; + foreach my $v (@_) { + $ret .= &pack_p_int($v); + } + + return $ret; + } + + my $v = $_[0]; + my $b; + + &exit(4, "pack_p_int only works on positive values") if ($v < 0); + if ($v < 128) { + $b = chr($v); + } else { + $b = chr(($v & 0x7f) | 0x80); + $b .= pack_p_int($v >> 7); + } + return $b; +} + +sub strip_angles { + my $s = $_[0]; + $s =~ s/^<(.*)>$/$1/; + return $s; +} + +# For localedef +# xc=0 "no warnings, locale defined" +# xc=1 "warnings, locale defined" +# xc=2 "implmentation limits or unsupported charactor sets, no locale defined" +# xc=3 "can't create new locales" +# xc=4+ "wornings or errors, no locale defined" +sub exit { + my($xc, $message) = @_; + + print STDERR $message; + exit $xc; +} diff --git a/adv_cmds/lsvfs/lsvfs.1 b/adv_cmds/lsvfs/lsvfs.1 new file mode 100644 index 0000000..411ea17 --- /dev/null +++ b/adv_cmds/lsvfs/lsvfs.1 @@ -0,0 +1,67 @@ +.\" Copyright (c) 1998-2003 Apple Computer, Inc. All rights reserved. +.\" +.\" @APPLE_LICENSE_HEADER_START@ +.\" +.\" The contents of this file constitute Original Code as defined in and +.\" are subject to the Apple Public Source License Version 1.1 (the +.\" "License"). You may not use this file except in compliance with the +.\" License. Please obtain a copy of the License at +.\" http://www.apple.com/publicsource and read it before using this file. +.\" +.\" This Original Code and all software distributed under the License are +.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the +.\" License for the specific language governing rights and limitations +.\" under the License. +.\" +.\" @APPLE_LICENSE_HEADER_END@ +.\" +.Dd January 4, 2003 +.Dt LSVFS 1 +.Os +.Sh NAME +.Nm lsvfs +.Nd list known virtual file systems +.Sh SYNOPSIS +.Nm +.Op Ar vfsname Ar ... +.Sh DESCRIPTION +The +.Nm +command lists information about the currently loaded virtual filesystem +modules. +When +.Ar vfsname +arguments are given, +.Nm +lists information about the specified VFS modules. +Otherwise, +.Nm +lists all currently loaded modules. +The information is as follows: +.Pp +.Bl -tag -compact -width Filesystem +.It Filesystem +the name of the filesystem, as would be used in the +.Ar type +parameter to +.Xr mount 2 +and the +.Fl t +option to +.Xr mount 8 +.It Refs +the number of references to this VFS; i.e., the number of currently +mounted filesystems of this type +.It Flags +flag bits +.El +.Sh SEE ALSO +.Xr mount 2 , +.Xr mount 8 +.Sh HISTORY +The command from which this tool was derived, as well as this manual, +originally appeared in +.Fx 2.0 . diff --git a/adv_cmds/lsvfs/lsvfs.c b/adv_cmds/lsvfs/lsvfs.c new file mode 100644 index 0000000..73f4135 --- /dev/null +++ b/adv_cmds/lsvfs/lsvfs.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1998-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + +#include +#include +#include +#include + +#define FMT "%-32.32s %5d %s\n" +#define HDRFMT "%-32.32s %5.5s %s\n" +#define DASHES "-------------------------------- ----- ---------------\n" + +static const char *fmt_flags(int flags); + +int +main(int argc, char *argv[]) +{ + struct vfsconf vfc; + int mib[4], max, x; + size_t len; + + printf(HDRFMT, "Filesystem", "Refs", "Flags"); + fputs(DASHES, stdout); + + if (argc > 1) { + for (x = 1; x < argc; x++) + if (getvfsbyname(argv[x], &vfc) == 0) + printf(FMT, vfc.vfc_name, vfc.vfc_refcount, + fmt_flags(vfc.vfc_flags)); + else + warnx("VFS %s unknown or not loaded", argv[x]); + } else { + mib[0] = CTL_VFS; + mib[1] = VFS_GENERIC; + mib[2] = VFS_MAXTYPENUM; + len = sizeof(int); + if (sysctl(mib, 3, &max, &len, NULL, 0) != 0) + errx(1, "sysctl"); + mib[2] = VFS_CONF; + + len = sizeof(vfc); + for (x = 0; x < max; x++) { + mib[3] = x; + if (sysctl(mib, 4, &vfc, &len, NULL, 0) != 0) { + if (errno != ENOTSUP) + errx(1, "sysctl"); + } else { + printf(FMT, vfc.vfc_name, vfc.vfc_refcount, + fmt_flags(vfc.vfc_flags)); + } + } + } + + return 0; +} + +static const char * +fmt_flags(int flags) +{ + static char buf[sizeof "local, dovolfs"]; + int comma = 0; + + buf[0] = '\0'; + + if(flags & MNT_LOCAL) { + if(comma++) strcat(buf, ", "); + strcat(buf, "local"); + } + + if(flags & MNT_DOVOLFS) { + if(comma++) strcat(buf, ", "); + strcat(buf, "dovolfs"); + } + + return buf; +} diff --git a/adv_cmds/mklocale/extern.h b/adv_cmds/mklocale/extern.h new file mode 100644 index 0000000..f2037dd --- /dev/null +++ b/adv_cmds/mklocale/extern.h @@ -0,0 +1,40 @@ +/*- + * 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. + * + * $FreeBSD: src/usr.bin/mklocale/extern.h,v 1.1 2002/04/28 12:34:54 markm Exp $ + */ + +int yylex(void); +int yyparse(void); diff --git a/adv_cmds/mklocale/ldef.h b/adv_cmds/mklocale/ldef.h new file mode 100644 index 0000000..da9e015 --- /dev/null +++ b/adv_cmds/mklocale/ldef.h @@ -0,0 +1,68 @@ +/*- + * 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. + * + * @(#)ldef.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/mklocale/ldef.h,v 1.5 2007/11/07 14:46:22 rafan Exp $ + */ + +#include +#ifdef __APPLE__ +#include +#include +#endif /* __APPLE__ */ +#include "runefile.h" + +/* + * This should look a LOT like a _RuneEntry + */ +typedef struct rune_list { + int32_t min; + int32_t max; + int32_t map; + uint32_t *types; + struct rune_list *next; +} rune_list; + +typedef struct rune_map { + uint32_t map[_CACHED_RUNES]; + rune_list *root; +} rune_map; + +#ifdef __APPLE__ +typedef struct { + char name[CHARCLASS_NAME_MAX]; + uint32_t mask; +} rune_charclass; +#endif /* __APPLE__ */ diff --git a/adv_cmds/mklocale/lex.l b/adv_cmds/mklocale/lex.l new file mode 100644 index 0000000..9ffbaca --- /dev/null +++ b/adv_cmds/mklocale/lex.l @@ -0,0 +1,179 @@ +%{ +/*- + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lex.l 8.1 (Berkeley) 6/6/93"; +#endif +#endif /* not lint */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/mklocale/lex.l,v 1.9 2005/02/26 21:47:54 ru Exp $"); + +#include +#include +#include + +#include "ldef.h" +#include "y.tab.h" +#include "extern.h" +%} + +ODIGIT [0-7] +DIGIT [0-9] +XDIGIT [0-9a-fA-F] +W [\t\n\r ] + +%% +\'.\' { yylval.rune = (unsigned char)yytext[1]; + return(RUNE); } + +'\\a' { yylval.rune = '\a'; + return(RUNE); } +'\\b' { yylval.rune = '\b'; + return(RUNE); } +'\\f' { yylval.rune = '\f'; + return(RUNE); } +'\\n' { yylval.rune = '\n'; + return(RUNE); } +'\\r' { yylval.rune = '\r'; + return(RUNE); } +'\\t' { yylval.rune = '\t'; + return(RUNE); } +'\\v' { yylval.rune = '\v'; + return(RUNE); } + +0x{XDIGIT}+ { yylval.rune = strtol(yytext, 0, 16); + return(RUNE); } +0{ODIGIT}+ { yylval.rune = strtol(yytext, 0, 8); + return(RUNE); } +{DIGIT}+ { yylval.rune = strtol(yytext, 0, 10); + return(RUNE); } + + +MAPLOWER { return(MAPLOWER); } +MAPUPPER { return(MAPUPPER); } +TODIGIT { return(DIGITMAP); } +INVALID { return(INVALID); } + +ALPHA { yylval.i = _CTYPE_A|_CTYPE_R|_CTYPE_G; + return(LIST); } +CONTROL { yylval.i = _CTYPE_C; + return(LIST); } +DIGIT { yylval.i = _CTYPE_D|_CTYPE_R|_CTYPE_G; + return(LIST); } +GRAPH { yylval.i = _CTYPE_G|_CTYPE_R; + return(LIST); } +LOWER { yylval.i = _CTYPE_L|_CTYPE_R|_CTYPE_G; + return(LIST); } +PUNCT { yylval.i = _CTYPE_P|_CTYPE_R|_CTYPE_G; + return(LIST); } +SPACE { yylval.i = _CTYPE_S; + return(LIST); } +UPPER { yylval.i = _CTYPE_U|_CTYPE_R|_CTYPE_G; + return(LIST); } +XDIGIT { yylval.i = _CTYPE_X|_CTYPE_R|_CTYPE_G; + return(LIST); } +BLANK { yylval.i = _CTYPE_B; + return(LIST); } +PRINT { yylval.i = _CTYPE_R; + return(LIST); } +IDEOGRAM { yylval.i = _CTYPE_I|_CTYPE_R|_CTYPE_G; + return(LIST); } +SPECIAL { yylval.i = _CTYPE_T|_CTYPE_R|_CTYPE_G; + return(LIST); } +PHONOGRAM { yylval.i = _CTYPE_Q|_CTYPE_R|_CTYPE_G; + return(LIST); } +SWIDTH0 { yylval.i = _CTYPE_SW0; return(LIST); } +SWIDTH1 { yylval.i = _CTYPE_SW1; return(LIST); } +SWIDTH2 { yylval.i = _CTYPE_SW2; return(LIST); } +SWIDTH3 { yylval.i = _CTYPE_SW3; return(LIST); } + +VARIABLE[\t ] { static char vbuf[1024]; + char *v = vbuf; + while ((*v = input()) && *v != '\n') + ++v; + if (*v) { + unput(*v); + *v = 0; + } + yylval.str = vbuf; + return(VARIABLE); + } + +ENCODING { return(ENCODING); } + +CHARCLASS { return(CHARCLASS); } + +\".*\" { char *e = yytext + 1; + yylval.str = e; + while (*e && *e != '"') + ++e; + *e = 0; + return(STRING); } + +\<|\(|\[ { return(LBRK); } + +\>|\)|\] { return(RBRK); } + +\- { return(THRU); } +\.\.\. { return(THRU); } + +\: { return(':'); } + +{W}+ ; + +^\#.*\n ; +\/\* { char lc = 0; + do { + while ((lc) != '*') + if ((lc = input()) == 0) + break; + } while((lc = input()) != '/'); + } + +\\$ ; +. { printf("Lex is skipping '%s'\n", yytext); } +%% + +#if !defined(yywrap) +int +yywrap() +{ + return(1); +} +#endif diff --git a/adv_cmds/mklocale/mklocale.1 b/adv_cmds/mklocale/mklocale.1 new file mode 100644 index 0000000..8f2ec0e --- /dev/null +++ b/adv_cmds/mklocale/mklocale.1 @@ -0,0 +1,308 @@ +.\" Copyright (c) 1993, 1994 +.\" 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. +.\" +.\" @(#)mklocale.1 8.2 (Berkeley) 4/18/94 +.\" $FreeBSD: src/usr.bin/mklocale/mklocale.1,v 1.28 2008/01/22 00:04:50 ache Exp $ +.\" +.Dd October 17, 2004 +.Dt MKLOCALE 1 +.Os +.Sh NAME +.Nm mklocale +.Nd make LC_CTYPE locale files +.Sh SYNOPSIS +.Nm +.Op Fl d +.Ar "< src-file" +.Ar "> language/LC_CTYPE" +.Nm +.Op Fl d +.Fl o +.Ar language/LC_CTYPE +.Ar src-file +.Sh DESCRIPTION +The +.Nm +utility reads a +.Dv LC_CTYPE +source file from standard input and produces a +.Dv LC_CTYPE +binary file on standard output suitable for placement in +.Pa /usr/share/locale/ Ns Ar language Ns Pa /LC_CTYPE . +.Pp +The format of +.Ar src-file +is quite simple. +It consists of a series of lines which start with a keyword and have +associated data following. +C style comments are used +to place comments in the file. +.Pp +Following options are available: +.Bl -tag -width indent +.It Fl d +Turns on debugging messages. +.It Fl o +Specify output file. +.El +.Pp +Besides the keywords which will be listed below, +the following are valid tokens in +.Ar src-file : +.Bl -tag -width ".Ar literal" +.It Dv RUNE +A +.Dv RUNE +may be any of the following: +.Bl -tag -width ".Ar 0x[0-9a-z]*" +.It Ar 'x' +The ASCII character +.Ar x . +.It Ar '\ex' +The ANSI C character +.Ar \ex +where +.Ar \ex +is one of +.Dv \ea , +.Dv \eb , +.Dv \ef , +.Dv \en , +.Dv \er , +.Dv \et , +or +.Dv \ev . +.It Ar 0x[0-9a-z]* +A hexadecimal number representing a rune code. +.It Ar 0[0-7]* +An octal number representing a rune code. +.It Ar [1-9][0-9]* +A decimal number representing a rune code. +.El +.It Dv STRING +A string enclosed in double quotes ("). +.It Dv THRU +Either +.Dv ... +or +.Dv - . +Used to indicate ranges. +.It Ar literal +The follow characters are taken literally: +.Bl -tag -width ".Dv <\|\|(\|\|[" +.It Dv "<\|(\|[" +Used to start a mapping. +All are equivalent. +.It Dv ">\|\^)\|]" +Used to end a mapping. +All are equivalent. +.It Dv : +Used as a delimiter in mappings. +.El +.El +.Pp +Key words which should only appear once are: +.Bl -tag -width ".Dv PHONOGRAM" +.It Dv ENCODING +Followed by a +.Dv STRING +which indicates the encoding mechanism to be used for this locale. +The current encodings are: +.Bl -tag -width ".Dv MSKanji" +.It Dv ASCII +American Standard Code for Information Interchange. +.It Dv BIG5 +The +.Dq Big5 +encoding of Chinese. +.It Dv EUC +.Dv EUC +encoding as used by several +vendors of +.Ux +systems. +.It Dv GB18030 +PRC national standard for encoding of Chinese text. +.It Dv GB2312 +Older PRC national standard for encoding Chinese text. +.It Dv GBK +A widely used encoding method for Chinese text, +backwards compatible with GB\ 2312-1980. +.It Dv MSKanji +The method of encoding Japanese used by Microsoft, +loosely based on JIS. +Also known as +.Dq "Shift JIS" +and +.Dq SJIS . +.It Dv NONE +No translation and the default. +.It Dv UTF-8 +The +.Dv UTF-8 +transformation format of +.Tn ISO +10646 +as defined by RFC 2279. +.El +.It Dv VARIABLE +This keyword must be followed by a single tab or space character, +after which encoding specific data is placed. +Currently only the +.Dv "EUC" +encoding requires variable data. +See +.Xr euc 5 +for further details. +.It Dv INVALID +(obsolete) +A single +.Dv RUNE +follows and is used as the invalid rune for this locale. +.El +.Pp +The following keywords may appear multiple times and have the following +format for data: +.Bl -tag -width ".Dv " -offset indent +.It Dv +.Dv RUNE1 +is mapped to +.Dv RUNE2 . +.It Dv +Runes +.Dv RUNE1 +through +.Dv RUNEn +are mapped to +.Dv RUNE2 +through +.Dv RUNE2 ++ n-1. +.El +.Bl -tag -width ".Dv PHONOGRAM" +.It Dv MAPLOWER +Defines the tolower mappings. +.Dv RUNE2 +is the lower case representation of +.Dv RUNE1 . +.It Dv MAPUPPER +Defines the toupper mappings. +.Dv RUNE2 +is the upper case representation of +.Dv RUNE1 . +.It Dv TODIGIT +Defines a map from runes to their digit value. +.Dv RUNE2 +is the integer value represented by +.Dv RUNE1 . +For example, the ASCII character +.Ql 0 +would map to the decimal value 0. +Only values up to 255 +are allowed. +.El +.Pp +The following keywords may appear multiple times and have the following +format for data: +.Bl -tag -width ".Dv RUNE1 THRU RUNEn" -offset indent +.It Dv RUNE +This rune has the property defined by the keyword. +.It Dv "RUNE1 THRU RUNEn" +All the runes between and including +.Dv RUNE1 +and +.Dv RUNEn +have the property defined by the keyword. +.El +.Bl -tag -width ".Dv PHONOGRAM" +.It Dv ALPHA +Defines runes which are alphabetic, printable and graphic. +.It Dv CONTROL +Defines runes which are control characters. +.It Dv DIGIT +Defines runes which are decimal digits, printable and graphic. +.It Dv GRAPH +Defines runes which are graphic and printable. +.It Dv LOWER +Defines runes which are lower case, printable and graphic. +.It Dv PUNCT +Defines runes which are punctuation, printable and graphic. +.It Dv SPACE +Defines runes which are spaces. +.It Dv UPPER +Defines runes which are upper case, printable and graphic. +.It Dv XDIGIT +Defines runes which are hexadecimal digits, printable and graphic. +.It Dv BLANK +Defines runes which are blank. +.It Dv PRINT +Defines runes which are printable. +.It Dv IDEOGRAM +Defines runes which are ideograms, printable and graphic. +.It Dv SPECIAL +Defines runes which are special characters, printable and graphic. +.It Dv PHONOGRAM +Defines runes which are phonograms, printable and graphic. +.It Dv SWIDTH0 +Defines runes with display width 0. +.It Dv SWIDTH1 +Defines runes with display width 1. +.It Dv SWIDTH2 +Defines runes with display width 2. +.It Dv SWIDTH3 +Defines runes with display width 3. +.El +.Pp +If no display width explicitly defined, width 1 assumed +for printable runes by default. +.Sh SEE ALSO +.Xr colldef 1 , +.Xr setlocale 3 , +.Xr wcwidth 3 , +.Xr big5 5 , +.Xr euc 5 , +.Xr gb18030 5 , +.Xr gb2312 5 , +.Xr gbk 5 , +.Xr mskanji 5 , +.Xr utf8 5 +.Sh HISTORY +The +.Nm +utility first appeared in +.Bx 4.4 . +.Sh BUGS +The +.Nm +utility is overly simplistic. diff --git a/adv_cmds/mklocale/runefile.h b/adv_cmds/mklocale/runefile.h new file mode 100644 index 0000000..6b3f9f7 --- /dev/null +++ b/adv_cmds/mklocale/runefile.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2005 Ruslan Ermilov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/locale/runefile.h,v 1.1 2005/05/16 09:32:41 ru Exp $ + */ + +#ifndef _RUNEFILE_H_ +#define _RUNEFILE_H_ + +#include + +#ifndef _CACHED_RUNES +#define _CACHED_RUNES (1 << 8) +#endif + +typedef struct { + int32_t min; + int32_t max; + int32_t map; +#ifdef __APPLE__ + int32_t __types_fake; +#endif /* __APPLE__ */ +} _FileRuneEntry; + +typedef struct { + char magic[8]; + char encoding[32]; + +#ifdef __APPLE__ + int32_t __sgetrune_fake; + int32_t __sputrune_fake; + int32_t __invalid_rune; +#endif /* __APPLE__ */ + + uint32_t runetype[_CACHED_RUNES]; + int32_t maplower[_CACHED_RUNES]; + int32_t mapupper[_CACHED_RUNES]; + + int32_t runetype_ext_nranges; +#ifdef __APPLE__ + int32_t __runetype_ext_ranges_fake; +#endif /* __APPLE__ */ + int32_t maplower_ext_nranges; +#ifdef __APPLE__ + int32_t __maplower_ext_ranges_fake; +#endif /* __APPLE__ */ + int32_t mapupper_ext_nranges; +#ifdef __APPLE__ + int32_t __mapupper_ext_ranges_fake; +#endif /* __APPLE__ */ + +#ifdef __APPLE__ + int32_t __variable_fake; +#endif /* __APPLE__ */ + int32_t variable_len; + +#ifdef __APPLE__ + int32_t ncharclasses; + int32_t __charclasses_fake; +#endif /* __APPLE__ */ +} _FileRuneLocale; + +#define _FILE_RUNE_MAGIC_1 "RuneMag1" + +#endif /* !_RUNEFILE_H_ */ diff --git a/adv_cmds/mklocale/yacc.y b/adv_cmds/mklocale/yacc.y new file mode 100644 index 0000000..f76498d --- /dev/null +++ b/adv_cmds/mklocale/yacc.y @@ -0,0 +1,929 @@ +%{ +/*- + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)yacc.y 8.1 (Berkeley) 6/6/93"; +#endif /* 0 */ +#endif /* not lint */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/mklocale/yacc.y,v 1.28 2008/01/22 00:04:50 ache Exp $"); + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ldef.h" +#include "extern.h" +#include "runefile.h" + +#define MAX_CHARCLASS 4 +#define CHARCLASSBIT 4 + +static void *xmalloc(unsigned int sz); +static uint32_t *xlalloc(unsigned int sz); +void yyerror(const char *s); +static uint32_t *xrelalloc(uint32_t *old, unsigned int sz); +static void dump_tables(void); +static void cleanout(void); + +const char *locale_file = ""; + +rune_map maplower = { { 0 }, NULL }; +rune_map mapupper = { { 0 }, NULL }; +rune_map types = { { 0 }, NULL }; + +_FileRuneLocale new_locale = { "", "", 0, 0, 0, {}, {}, {}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +char *variable = NULL; + +rune_charclass charclasses[MAX_CHARCLASS]; +int charclass_index = 0; + +void set_map(rune_map *, rune_list *, uint32_t); +void set_digitmap(rune_map *, rune_list *); +void add_map(rune_map *, rune_list *, uint32_t); +static void usage(void); +%} + +%union { + int32_t rune; + int i; + char *str; + + rune_list *list; +} + +%token RUNE +%token LBRK +%token RBRK +%token THRU +%token MAPLOWER +%token MAPUPPER +%token DIGITMAP +%token CHARCLASS +%token LIST +%token VARIABLE +%token ENCODING +%token INVALID +%token STRING + +%type list +%type map + + +%% + +locale : /* empty */ + | table + { dump_tables(); } + ; + +table : entry + | table entry + ; + +entry : ENCODING STRING + { if (strcmp($2, "NONE") && + strcmp($2, "ASCII") && + strcmp($2, "UTF-8") && + strcmp($2, "EUC") && + strcmp($2, "GBK") && + strcmp($2, "GB18030") && + strcmp($2, "GB2312") && + strcmp($2, "BIG5") && + strcmp($2, "MSKanji") && + strcmp($2, "UTF2")) + warnx("ENCODING %s is not supported by libc", $2); + strncpy(new_locale.encoding, $2, + sizeof(new_locale.encoding)); } + | VARIABLE + { new_locale.variable_len = strlen($1) + 1; + variable = xmalloc(new_locale.variable_len); + strcpy(variable, $1); + } + | INVALID RUNE + { warnx("the INVALID keyword is deprecated"); } + | LIST list + { set_map(&types, $2, $1); } + | MAPLOWER map + { set_map(&maplower, $2, 0); } + | MAPUPPER map + { set_map(&mapupper, $2, 0); } + | DIGITMAP map + { + if (($2->map >= 0) && ($2->map <= 255)) { /* Data corruption otherwise */ + set_digitmap(&types, $2); + } + } + | CHARCLASS STRING list + { + int i; + if (strlen($2) > CHARCLASS_NAME_MAX) + errx(1, "Exceeded maximum charclass name size (%d) \"%s\"", CHARCLASS_NAME_MAX, $2); + for(i = 0; i < charclass_index; i++) + if (strncmp(charclasses[i].name, $2, CHARCLASS_NAME_MAX) == 0) + break; + if (i >= charclass_index) { + if (charclass_index >= MAX_CHARCLASS) + errx(1, "Exceeded maximum number of charclasses (%d)", MAX_CHARCLASS); + strncpy(charclasses[charclass_index].name, $2, CHARCLASS_NAME_MAX); + charclasses[charclass_index].mask = (1 << (charclass_index + CHARCLASSBIT)); + charclass_index++; + } + set_map(&types, $3, charclasses[i].mask); + } + ; + +list : RUNE + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $1; + $$->max = $1; + $$->next = 0; + } + | RUNE THRU RUNE + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $1; + $$->max = $3; + $$->next = 0; + } + | list RUNE + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $2; + $$->max = $2; + $$->next = $1; + } + | list RUNE THRU RUNE + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $2; + $$->max = $4; + $$->next = $1; + } + ; + +map : LBRK RUNE RUNE RBRK + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $2; + $$->max = $2; + $$->map = $3; + $$->next = 0; + } + | map LBRK RUNE RUNE RBRK + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $3; + $$->max = $3; + $$->map = $4; + $$->next = $1; + } + | LBRK RUNE THRU RUNE ':' RUNE RBRK + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $2; + $$->max = $4; + $$->map = $6; + $$->next = 0; + } + | map LBRK RUNE THRU RUNE ':' RUNE RBRK + { + $$ = (rune_list *)xmalloc(sizeof(rune_list)); + $$->min = $3; + $$->max = $5; + $$->map = $7; + $$->next = $1; + } + ; +%% + +int debug; +FILE *fp; + +static void +cleanout(void) +{ + if (fp != NULL) + unlink(locale_file); +} + +int +main(int ac, char *av[]) +{ + int x; + + fp = stdout; + + while ((x = getopt(ac, av, "do:")) != -1) { + switch(x) { + case 'd': + debug = 1; + break; + case 'o': + locale_file = optarg; + if ((fp = fopen(locale_file, "w")) == NULL) + err(1, "%s: fopen", locale_file); + atexit(cleanout); + break; + default: + usage(); + } + } + + switch (ac - optind) { + case 0: + break; + case 1: + if (freopen(av[optind], "r", stdin) == 0) + err(1, "%s: freopen", av[optind]); + break; + default: + usage(); + } + for (x = 0; x < _CACHED_RUNES; ++x) { + mapupper.map[x] = x; + maplower.map[x] = x; + } + memcpy(new_locale.magic, _RUNE_MAGIC_A, sizeof(new_locale.magic)); + + yyparse(); + + return(0); +} + +static void +usage() +{ + fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n"); + exit(1); +} + +void +yyerror(s) + const char *s; +{ + fprintf(stderr, "%s\n", s); +} + +static void * +xmalloc(sz) + unsigned int sz; +{ + void *r = malloc(sz); + if (!r) + errx(1, "xmalloc"); + return(r); +} + +static uint32_t * +xlalloc(sz) + unsigned int sz; +{ + uint32_t *r = (uint32_t *)malloc(sz * sizeof(uint32_t)); + if (!r) + errx(1, "xlalloc"); + return(r); +} + +static uint32_t * +xrelalloc(old, sz) + uint32_t *old; + unsigned int sz; +{ + uint32_t *r = (uint32_t *)realloc((char *)old, + sz * sizeof(uint32_t)); + if (!r) + errx(1, "xrelalloc"); + return(r); +} + +void +set_map(map, list, flag) + rune_map *map; + rune_list *list; + uint32_t flag; +{ + while (list) { + rune_list *nlist = list->next; + add_map(map, list, flag); + list = nlist; + } +} + +void +set_digitmap(map, list) + rune_map *map; + rune_list *list; +{ + int32_t i; + + while (list) { + rune_list *nlist = list->next; + for (i = list->min; i <= list->max; ++i) { + if (list->map + (i - list->min)) { + rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list)); + tmp->min = i; + tmp->max = i; + add_map(map, tmp, list->map + (i - list->min)); + } + } + free(list); + list = nlist; + } +} + +void +add_map(map, list, flag) + rune_map *map; + rune_list *list; + uint32_t flag; +{ + int32_t i; + rune_list *lr = 0; + rune_list *r; + int32_t run; + + while (list->min < _CACHED_RUNES && list->min <= list->max) { + if (flag) + map->map[list->min++] |= flag; + else + map->map[list->min++] = list->map++; + } + + if (list->min > list->max) { + free(list); + return; + } + + run = list->max - list->min + 1; + + if (!(r = map->root) || (list->max < r->min - 1) + || (!flag && list->max == r->min - 1)) { + if (flag) { + list->types = xlalloc(run); + for (i = 0; i < run; ++i) + list->types[i] = flag; + } + list->next = map->root; + map->root = list; + return; + } + + for (r = map->root; r && r->max + 1 < list->min; r = r->next) + lr = r; + + if (!r) { + /* + * We are off the end. + */ + if (flag) { + list->types = xlalloc(run); + for (i = 0; i < run; ++i) + list->types[i] = flag; + } + list->next = 0; + lr->next = list; + return; + } + + if (list->max < r->min - 1) { + /* + * We come before this range and we do not intersect it. + * We are not before the root node, it was checked before the loop + */ + if (flag) { + list->types = xlalloc(run); + for (i = 0; i < run; ++i) + list->types[i] = flag; + } + list->next = lr->next; + lr->next = list; + return; + } + + /* + * At this point we have found that we at least intersect with + * the range pointed to by `r', we might intersect with one or + * more ranges beyond `r' as well. + */ + + if (!flag && list->map - list->min != r->map - r->min) { + /* + * There are only two cases when we are doing case maps and + * our maps needn't have the same offset. When we are adjoining + * but not intersecting. + */ + if (list->max + 1 == r->min) { + lr->next = list; + list->next = r; + return; + } + if (list->min - 1 == r->max) { + list->next = r->next; + r->next = list; + return; + } + errx(1, "error: conflicting map entries"); + } + + if (list->min >= r->min && list->max <= r->max) { + /* + * Subset case. + */ + + if (flag) { + for (i = list->min; i <= list->max; ++i) + r->types[i - r->min] |= flag; + } + free(list); + return; + } + if (list->min <= r->min && list->max >= r->max) { + /* + * Superset case. Make him big enough to hold us. + * We might need to merge with the guy after him. + */ + if (flag) { + list->types = xlalloc(list->max - list->min + 1); + + for (i = list->min; i <= list->max; ++i) + list->types[i - list->min] = flag; + + for (i = r->min; i <= r->max; ++i) + list->types[i - list->min] |= r->types[i - r->min]; + + free(r->types); + r->types = list->types; + } else { + r->map = list->map; + } + r->min = list->min; + r->max = list->max; + free(list); + } else if (list->min < r->min) { + /* + * Our tail intersects his head. + */ + if (flag) { + list->types = xlalloc(r->max - list->min + 1); + + for (i = r->min; i <= r->max; ++i) + list->types[i - list->min] = r->types[i - r->min]; + + for (i = list->min; i < r->min; ++i) + list->types[i - list->min] = flag; + + for (i = r->min; i <= list->max; ++i) + list->types[i - list->min] |= flag; + + free(r->types); + r->types = list->types; + } else { + r->map = list->map; + } + r->min = list->min; + free(list); + return; + } else { + /* + * Our head intersects his tail. + * We might need to merge with the guy after him. + */ + if (flag) { + r->types = xrelalloc(r->types, list->max - r->min + 1); + + for (i = list->min; i <= r->max; ++i) + r->types[i - r->min] |= flag; + + for (i = r->max+1; i <= list->max; ++i) + r->types[i - r->min] = flag; + } + r->max = list->max; + free(list); + } + + /* + * Okay, check to see if we grew into the next guy(s) + */ + while ((lr = r->next) && r->max >= lr->min) { + if (flag) { + if (r->max >= lr->max) { + /* + * Good, we consumed all of him. + */ + for (i = lr->min; i <= lr->max; ++i) + r->types[i - r->min] |= lr->types[i - lr->min]; + } else { + /* + * "append" him on to the end of us. + */ + r->types = xrelalloc(r->types, lr->max - r->min + 1); + + for (i = lr->min; i <= r->max; ++i) + r->types[i - r->min] |= lr->types[i - lr->min]; + + for (i = r->max+1; i <= lr->max; ++i) + r->types[i - r->min] = lr->types[i - lr->min]; + + r->max = lr->max; + } + } else { + if (lr->max > r->max) + r->max = lr->max; + } + + r->next = lr->next; + + if (flag) + free(lr->types); + free(lr); + } +} + +static void +dump_tables() +{ + int x, first_d, curr_d; + rune_list *list; + + /* + * See if we can compress some of the istype arrays + */ + for(list = types.root; list; list = list->next) { + list->map = list->types[0]; + for (x = 1; x < list->max - list->min + 1; ++x) { + if ((int32_t)list->types[x] != list->map) { + list->map = 0; + break; + } + } + } + + first_d = curr_d = -1; + for (x = 0; x < _CACHED_RUNES; ++x) { + uint32_t r = types.map[x]; + + if (r & _CTYPE_D) { + if (first_d < 0) + first_d = curr_d = x; + else if (x != curr_d + 1) + errx(1, "error: DIGIT range is not contiguous"); + else if (x - first_d > 9) + errx(1, "error: DIGIT range is too big"); + else + curr_d++; + if (!(r & _CTYPE_X)) + errx(1, + "error: DIGIT range is not a subset of XDIGIT range"); + } + } + if (first_d < 0) + errx(1, "error: no DIGIT range defined in the single byte area"); + else if (curr_d - first_d < 9) + errx(1, "error: DIGIT range is too small in the single byte area"); + + new_locale.ncharclasses = htonl(charclass_index); + + /* + * Fill in our tables. Do this in network order so that + * diverse machines have a chance of sharing data. + * (Machines like Crays cannot share with little machines due to + * word size. Sigh. We tried.) + */ + for (x = 0; x < _CACHED_RUNES; ++x) { + new_locale.runetype[x] = htonl(types.map[x]); + new_locale.maplower[x] = htonl(maplower.map[x]); + new_locale.mapupper[x] = htonl(mapupper.map[x]); + } + + /* + * Count up how many ranges we will need for each of the extents. + */ + list = types.root; + + while (list) { + new_locale.runetype_ext_nranges++; + list = list->next; + } + new_locale.runetype_ext_nranges = + htonl(new_locale.runetype_ext_nranges); + + list = maplower.root; + + while (list) { + new_locale.maplower_ext_nranges++; + list = list->next; + } + new_locale.maplower_ext_nranges = + htonl(new_locale.maplower_ext_nranges); + + list = mapupper.root; + + while (list) { + new_locale.mapupper_ext_nranges++; + list = list->next; + } + new_locale.mapupper_ext_nranges = + htonl(new_locale.mapupper_ext_nranges); + + new_locale.variable_len = htonl(new_locale.variable_len); + + /* + * Okay, we are now ready to write the new locale file. + */ + + /* + * PART 1: The _FileRuneLocale structure + */ + if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) { + err(1, "%s: _FileRuneLocale structure", locale_file); + } + /* + * PART 2: The runetype_ext structures (not the actual tables) + */ + list = types.root; + + while (list) { + _FileRuneEntry re; + + re.min = htonl(list->min); + re.max = htonl(list->max); + re.map = htonl(list->map); +#ifdef __APPLE__ + re.__types_fake = 0; +#endif + + if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { + err(1, "%s: runetype_ext structures", locale_file); + } + + list = list->next; + } + /* + * PART 3: The maplower_ext structures + */ + list = maplower.root; + + while (list) { + _FileRuneEntry re; + + re.min = htonl(list->min); + re.max = htonl(list->max); + re.map = htonl(list->map); +#ifdef __APPLE__ + re.__types_fake = 0; +#endif + + if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { + err(1, "%s: maplower_ext structures", locale_file); + } + + list = list->next; + } + /* + * PART 4: The mapupper_ext structures + */ + list = mapupper.root; + + while (list) { + _FileRuneEntry re; + + re.min = htonl(list->min); + re.max = htonl(list->max); + re.map = htonl(list->map); +#ifdef __APPLE__ + re.__types_fake = 0; +#endif + + if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { + err(1, "%s: mapupper_ext structures", locale_file); + } + + list = list->next; + } + /* + * PART 5: The runetype_ext tables + */ + list = types.root; + + while (list) { + for (x = 0; x < list->max - list->min + 1; ++x) + list->types[x] = htonl(list->types[x]); + + if (!list->map) { + if (fwrite((char *)list->types, + (list->max - list->min + 1) * sizeof(uint32_t), + 1, fp) != 1) { + err(1, "%s: runetype_ext tables", locale_file); + } + } + list = list->next; + } + /* + * PART 6: The charclass names table + */ + for (x = 0; x < charclass_index; ++x) { + charclasses[x].mask = ntohl(charclasses[x].mask); + if (fwrite((char *)&charclasses[x], sizeof(rune_charclass), 1, fp) != 1) { + err(1, "%s: charclass names tables", locale_file); + } + } + /* + * PART 7: And finally the variable data + * SUSv3 says fwrite returns zero when either size or nitems is zero. + */ + if (ntohl(new_locale.variable_len) > 0 && fwrite(variable, + ntohl(new_locale.variable_len), 1, fp) != 1) { + err(1, "%s: variable data", locale_file); + } + if (fclose(fp) != 0) { + err(1, "%s: fclose", locale_file); + } + fp = NULL; + + if (!debug) + return; + + if (new_locale.encoding[0]) + fprintf(stderr, "ENCODING %s\n", new_locale.encoding); + if (variable) + fprintf(stderr, "VARIABLE %s\n", variable); + + fprintf(stderr, "\nMAPLOWER:\n\n"); + + for (x = 0; x < _CACHED_RUNES; ++x) { + if (isprint(maplower.map[x])) + fprintf(stderr, " '%c'", (int)maplower.map[x]); + else if (maplower.map[x]) + fprintf(stderr, "%04x", maplower.map[x]); + else + fprintf(stderr, "%4x", 0); + if ((x & 0xf) == 0xf) + fprintf(stderr, "\n"); + else + fprintf(stderr, " "); + } + fprintf(stderr, "\n"); + + for (list = maplower.root; list; list = list->next) + fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); + + fprintf(stderr, "\nMAPUPPER:\n\n"); + + for (x = 0; x < _CACHED_RUNES; ++x) { + if (isprint(mapupper.map[x])) + fprintf(stderr, " '%c'", (int)mapupper.map[x]); + else if (mapupper.map[x]) + fprintf(stderr, "%04x", mapupper.map[x]); + else + fprintf(stderr, "%4x", 0); + if ((x & 0xf) == 0xf) + fprintf(stderr, "\n"); + else + fprintf(stderr, " "); + } + fprintf(stderr, "\n"); + + for (list = mapupper.root; list; list = list->next) + fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); + + + fprintf(stderr, "\nTYPES:\n\n"); + + for (x = 0; x < _CACHED_RUNES; ++x) { + uint32_t r = types.map[x]; + + if (r) { + if (isprint(x)) + fprintf(stderr, " '%c': %2d", x, (int)(r & 0xff)); + else + fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); + + fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); + fprintf(stderr, "\n"); + } + } + + for (list = types.root; list; list = list->next) { + if (list->map && list->min + 3 < list->max) { + uint32_t r = list->map; + + fprintf(stderr, "%04x: %2d", + (uint32_t)list->min, (int)(r & 0xff)); + + fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); + fprintf(stderr, "\n...\n"); + + fprintf(stderr, "%04x: %2d", + (uint32_t)list->max, (int)(r & 0xff)); + + fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); + fprintf(stderr, "\n"); + } else + for (x = list->min; x <= list->max; ++x) { + uint32_t r = ntohl(list->types[x - list->min]); + + if (r) { + fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); + + fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); + fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); + fprintf(stderr, "\n"); + } + } + } +} diff --git a/adv_cmds/pkill/entitlements.plist b/adv_cmds/pkill/entitlements.plist new file mode 100644 index 0000000..b0a6726 --- /dev/null +++ b/adv_cmds/pkill/entitlements.plist @@ -0,0 +1,8 @@ + + + + + com.apple.sysmond.client + + + diff --git a/adv_cmds/pkill/pkill.1 b/adv_cmds/pkill/pkill.1 new file mode 100644 index 0000000..672b185 --- /dev/null +++ b/adv_cmds/pkill/pkill.1 @@ -0,0 +1,232 @@ +.\" $NetBSD: pkill.1,v 1.8 2003/02/14 15:59:18 grant Exp $ +.\" +.\" $FreeBSD: src/bin/pkill/pkill.1,v 1.8 2010/07/12 01:58:46 brian Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Andrew Doran. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 11, 2010 +.Dt PKILL 1 +.Os +.Sh NAME +.Nm pgrep , pkill +.Nd find or signal processes by name +.Sh SYNOPSIS +.Nm pgrep +.Op Fl Lafilnoqvx +.Op Fl F Ar pidfile +.Op Fl G Ar gid +.Op Fl P Ar ppid +.Op Fl U Ar uid +.Op Fl d Ar delim +.Op Fl g Ar pgrp +.Op Fl t Ar tty +.Op Fl u Ar euid +.Ar pattern ... +.Nm pkill +.Op Fl Ar signal +.Op Fl ILafilnovx +.Op Fl F Ar pidfile +.Op Fl G Ar gid +.Op Fl P Ar ppid +.Op Fl U Ar uid +.Op Fl g Ar pgrp +.Op Fl t Ar tty +.Op Fl u Ar euid +.Ar pattern ... +.Sh DESCRIPTION +The +.Nm pgrep +command searches the process table on the running system and prints the +process IDs of all processes that match the criteria given on the command +line. +.Pp +The +.Nm pkill +command searches the process table on the running system and signals all +processes that match the criteria given on the command line. +.Pp +The following options are available: +.Bl -tag -width ".Fl F Ar pidfile" +.It Fl F Ar pidfile +Restrict matches to a process whose PID is stored in the +.Ar pidfile +file. +.It Fl G Ar gid +Restrict matches to processes with a real group ID in the comma-separated +list +.Ar gid . +.It Fl I +Request confirmation before attempting to signal each process. +.It Fl L +The +.Ar pidfile +file given for the +.Fl F +option must be locked with the +.Xr flock 2 +syscall or created with +.Xr pidfile 3 . +.It Fl P Ar ppid +Restrict matches to processes with a parent process ID in the +comma-separated list +.Ar ppid . +.It Fl U Ar uid +Restrict matches to processes with a real user ID in the comma-separated +list +.Ar uid . +.It Fl d Ar delim +Specify a delimiter to be printed between each process ID. +The default is a newline. +This option can only be used with the +.Nm pgrep +command. +.It Fl a +Include process ancestors in the match list. +By default, the current +.Nm pgrep +or +.Nm pkill +process and all of its ancestors are excluded (unless +.Fl v +is used). +.It Fl f +Match against full argument lists. +The default is to match against process names. +.It Fl g Ar pgrp +Restrict matches to processes with a process group ID in the comma-separated +list +.Ar pgrp . +The value zero is taken to mean the process group ID of the running +.Nm pgrep +or +.Nm pkill +command. +.It Fl i +Ignore case distinctions in both the process table and the supplied pattern. +.It Fl l +Long output. +For +.Nm pgrep , +print the process name in addition to the process ID for each matching +process. +If used in conjunction with +.Fl f , +print the process ID and the full argument list for each matching process. +For +.Nm pkill , +display the kill command used for each process killed. +.It Fl n +Select only the newest (most recently started) of the matching processes. +.It Fl o +Select only the oldest (least recently started) of the matching processes. +.It Fl q +Do not write anything to standard output. +.It Fl t Ar tty +Restrict matches to processes associated with a terminal in the +comma-separated list +.Ar tty . +Terminal names may be of the form +.Pa tty Ns Ar xx +or the shortened form +.Ar xx . +A single dash +.Pq Ql - +matches processes not associated with a terminal. +.It Fl u Ar euid +Restrict matches to processes with an effective user ID in the +comma-separated list +.Ar euid . +.It Fl v +Reverse the sense of the matching; display processes that do not match the +given criteria. +.It Fl x +Require an exact match of the process name, or argument list if +.Fl f +is given. +The default is to match any substring. +.It Fl Ns Ar signal +A non-negative decimal number or symbolic signal name specifying the signal +to be sent instead of the default +.Dv TERM . +This option is valid only when given as the first argument to +.Nm pkill . +.El +.Pp +If any +.Ar pattern +operands are specified, they are used as regular expressions to match +the command name or full argument list of each process. +.Pp +Note that a running +.Nm pgrep +or +.Nm pkill +process will never consider itself as +a potential match. +.Sh EXIT STATUS +The +.Nm pgrep +and +.Nm pkill +utilities +return one of the following values upon exit: +.Bl -tag -width indent +.It 0 +One or more processes were matched. +.It 1 +No processes were matched. +.It 2 +Invalid options were specified on the command line. +.It 3 +An internal error occurred. +.El +.Sh SEE ALSO +.Xr kill 1 , +.Xr killall 1 , +.Xr ps 1 , +.Xr flock 2 , +.Xr kill 2 , +.Xr sigaction 2 , +.Xr pidfile 3 , +.Xr re_format 7 +.\" Xr signal 7 +.Sh HISTORY +The +.Nm pkill +and +.Nm pgrep +utilities +first appeared in +.Nx 1.6 . +They are modelled after utilities of the same name that appeared in Sun +Solaris 7. +They made their first appearance in +.Fx 5.3 . +.Sh AUTHORS +.An Andrew Doran +.Aq ad@NetBSD.org diff --git a/adv_cmds/pkill/pkill.c b/adv_cmds/pkill/pkill.c new file mode 100644 index 0000000..668d656 --- /dev/null +++ b/adv_cmds/pkill/pkill.c @@ -0,0 +1,1111 @@ +/* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * Copyright (c) 2005 Pawel Jakub Dawidek + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/bin/pkill/pkill.c,v 1.12 2011/02/04 16:40:50 jilles Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#include +#include +#endif + +#define STATUS_MATCH 0 +#define STATUS_NOMATCH 1 +#define STATUS_BADUSAGE 2 +#define STATUS_ERROR 3 + +#define MIN_PID 5 +#define MAX_PID 99999 + +#ifdef __APPLE__ +/* Ignore system processes and myself. */ +#define PSKIP(kp) ((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)) == mypid || \ + ((xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_FLAGS)) & PROC_FLAG_SYSTEM) != 0)) +#else +/* Ignore system-processes (if '-S' flag is not specified) and myself. */ +#define PSKIP(kp) ((kp)->ki_pid == mypid || \ + (!kthreads && ((kp)->ki_flag & P_KTHREAD) != 0)) +#endif + +enum listtype { + LT_GENERIC, + LT_USER, + LT_GROUP, + LT_TTY, + LT_PGRP, +#ifndef __APPLE__ + LT_JID, +#endif + LT_SID +}; + +struct list { + SLIST_ENTRY(list) li_chain; + long li_number; +}; + +SLIST_HEAD(listhead, list); + +#ifdef __APPLE__ +static sysmon_table_t plist; +#else +static struct kinfo_proc *plist; +#endif +static char *selected; +static const char *delim = "\n"; +static int nproc; +static int pgrep; +static int signum = SIGTERM; +static int newest; +static int oldest; +static int interactive; +static int inverse; +static int longfmt; +static int matchargs; +static int fullmatch; +#ifndef __APPLE__ +static int kthreads; +#endif +static int cflags = REG_EXTENDED; +static int quiet; +#ifndef __APPLE__ +static kvm_t *kd; +#endif +static pid_t mypid; + +static struct listhead euidlist = SLIST_HEAD_INITIALIZER(euidlist); +static struct listhead ruidlist = SLIST_HEAD_INITIALIZER(ruidlist); +static struct listhead rgidlist = SLIST_HEAD_INITIALIZER(rgidlist); +static struct listhead pgrplist = SLIST_HEAD_INITIALIZER(pgrplist); +static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist); +static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist); +#ifndef __APPLE__ +static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist); +static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist); +#endif + +static void usage(void) __attribute__((__noreturn__)); +#ifdef __APPLE__ +static int killact(const sysmon_row_t); +static int grepact(const sysmon_row_t); +#else +static int killact(const struct kinfo_proc *); +static int grepact(const struct kinfo_proc *); +#endif +static void makelist(struct listhead *, enum listtype, char *); +static int takepid(const char *, int); + +#ifdef __APPLE__ +static sysmon_table_t +copy_process_info(void) +{ + dispatch_semaphore_t sema; + sysmon_request_t request; + __block sysmon_table_t result = NULL; + + sema = dispatch_semaphore_create(0); + request = sysmon_request_create_with_error(SYSMON_REQUEST_TYPE_PROCESS, ^(sysmon_table_t table, const char *error_str) { + if (table) { + result = sysmon_retain(table); + } else { + fprintf(stderr, "sysmon request failed with error: %s\n", error_str); + } + dispatch_semaphore_signal(sema); + }); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_PID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_FLAGS); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_UID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_COMM); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_ARGUMENTS); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_RUID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_RGID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_PPID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_PGID); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_TDEV); + sysmon_request_add_attribute(request, SYSMON_ATTR_PROC_START); + sysmon_request_execute(request); + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + dispatch_release(sema); + sysmon_release(request); + + return result; +} +#endif /* __APPLE__ */ + +int +main(int argc, char **argv) +{ +#ifdef __APPLE__ + char buf[_POSIX2_LINE_MAX], *bufp, *mstr, *p, *q, *pidfile; + xpc_object_t pargv; +#else + char buf[_POSIX2_LINE_MAX], *mstr, **pargv, *p, *q, *pidfile; + const char *execf, *coref; +#endif + int ancestors, debug_opt, did_action; + int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock; +#ifdef __APPLE__ + __block size_t jsz; + int (*action)(const sysmon_row_t); + sysmon_row_t kp; +#else + size_t jsz; + int (*action)(const struct kinfo_proc *); + struct kinfo_proc *kp; +#endif + struct list *li; +#ifdef __APPLE__ + int64_t best_tval; +#else + struct timeval best_tval; +#endif + regex_t reg; + regmatch_t regmatch; + pid_t pid; + + setlocale(LC_ALL, ""); + + if (strcmp(getprogname(), "pgrep") == 0) { + action = grepact; + pgrep = 1; + } else { + action = killact; + p = argv[1]; + + if (argc > 1 && p[0] == '-') { + p++; + i = (int)strtol(p, &q, 10); + if (*q == '\0') { + signum = i; + argv++; + argc--; + } else { + if (strncasecmp(p, "SIG", 3) == 0) + p += 3; + for (i = 1; i < NSIG; i++) + if (strcasecmp(sys_signame[i], p) == 0) + break; + if (i != NSIG) { + signum = i; + argv++; + argc--; + } + } + } + } + + ancestors = 0; + criteria = 0; + debug_opt = 0; + pidfile = NULL; + pidfilelock = 0; + quiet = 0; +#ifndef __APPLE__ + execf = NULL; + coref = _PATH_DEVNULL; +#endif + +#ifdef __APPLE__ + while ((ch = getopt(argc, argv, "DF:G:ILP:U:ad:fg:ilnoqt:u:vx")) != -1) +#else + while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ad:fg:ij:lnoqs:t:u:vx")) != -1) +#endif + switch (ch) { + case 'D': + debug_opt++; + break; + case 'F': + pidfile = optarg; + criteria = 1; + break; + case 'G': + makelist(&rgidlist, LT_GROUP, optarg); + criteria = 1; + break; + case 'I': + if (pgrep) + usage(); + interactive = 1; + break; + case 'L': + pidfilelock = 1; + break; +#ifndef __APPLE__ + case 'M': + coref = optarg; + break; + case 'N': + execf = optarg; + break; +#endif + case 'P': + makelist(&ppidlist, LT_GENERIC, optarg); + criteria = 1; + break; +#ifndef __APPLE__ + case 'S': + if (!pgrep) + usage(); + kthreads = 1; + break; +#endif + case 'U': + makelist(&ruidlist, LT_USER, optarg); + criteria = 1; + break; + case 'a': + ancestors++; + break; + case 'd': + if (!pgrep) + usage(); + delim = optarg; + break; + case 'f': + matchargs = 1; + break; + case 'g': + makelist(&pgrplist, LT_PGRP, optarg); + criteria = 1; + break; + case 'i': + cflags |= REG_ICASE; + break; +#ifndef __APPLE__ + case 'j': + makelist(&jidlist, LT_JID, optarg); + criteria = 1; + break; +#endif + case 'l': + longfmt = 1; + break; + case 'n': + newest = 1; + criteria = 1; + break; + case 'o': + oldest = 1; + criteria = 1; + break; + case 'q': + if (!pgrep) + usage(); + quiet = 1; + break; +#ifndef __APPLE__ + case 's': + makelist(&sidlist, LT_SID, optarg); + criteria = 1; + break; +#endif /* !__APPLE__ */ + case 't': + makelist(&tdevlist, LT_TTY, optarg); + criteria = 1; + break; + case 'u': + makelist(&euidlist, LT_USER, optarg); + criteria = 1; + break; + case 'v': + inverse = 1; + break; + case 'x': + fullmatch = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + if (argc != 0) + criteria = 1; + if (!criteria) + usage(); + if (newest && oldest) + errx(STATUS_ERROR, "Options -n and -o are mutually exclusive"); + if (pidfile != NULL) + pidfromfile = takepid(pidfile, pidfilelock); + else { + if (pidfilelock) { + errx(STATUS_ERROR, + "Option -L doesn't make sense without -F"); + } + pidfromfile = -1; + } + + mypid = getpid(); + +#ifdef __APPLE__ + plist = copy_process_info(); + if (plist == NULL) { + errx(STATUS_ERROR, "Cannot get process list"); + } + nproc = sysmon_table_get_count(plist); +#else + /* + * Retrieve the list of running processes from the kernel. + */ + kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf); + if (kd == NULL) + errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf); + + /* + * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we + * just want processes and not individual kernel threads. + */ + plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc); + if (plist == NULL) { + errx(STATUS_ERROR, "Cannot get process list (%s)", + kvm_geterr(kd)); + } +#endif + + /* + * Allocate memory which will be used to keep track of the + * selection. + */ + if ((selected = malloc(nproc)) == NULL) { + err(STATUS_ERROR, "Cannot allocate memory for %d processes", + nproc); + } + memset(selected, 0, nproc); + + /* + * Refine the selection. + */ + for (; *argv != NULL; argv++) { + if ((rv = regcomp(®, *argv, cflags)) != 0) { + regerror(rv, ®, buf, sizeof(buf)); + errx(STATUS_BADUSAGE, + "Cannot compile regular expression `%s' (%s)", + *argv, buf); + } + +#ifdef __APPLE__ + for (i = 0; i < nproc; i++) { + kp = sysmon_table_get_row(plist, i); +#else + for (i = 0, kp = plist; i < nproc; i++, kp++) { +#endif + if (PSKIP(kp)) { + if (debug_opt > 0) + fprintf(stderr, "* Skipped %5d %3d %s\n", +#ifdef __APPLE__ + (pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)), + (uid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_UID)), + xpc_string_get_string_ptr(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_COMM))); +#else + kp->ki_pid, kp->ki_uid, kp->ki_comm); +#endif + continue; + } + +#ifdef __APPLE__ + if (matchargs && + (pargv = sysmon_row_get_value(kp, SYSMON_ATTR_PROC_ARGUMENTS)) != NULL) { + jsz = 0; + os_assert(sizeof(buf) == _POSIX2_LINE_MAX); + bufp = buf; + xpc_array_apply(pargv, ^(size_t index, xpc_object_t value) { + if (jsz >= _POSIX2_LINE_MAX) { + return (bool)false; + } + jsz += snprintf(bufp + jsz, + _POSIX2_LINE_MAX - jsz, + index < xpc_array_get_count(pargv) - 1 ? "%s " : "%s", + xpc_string_get_string_ptr(value)); + return (bool)true; + }); +#else + if (matchargs && + (pargv = kvm_getargv(kd, kp, 0)) != NULL) { + jsz = 0; + while (jsz < sizeof(buf) && *pargv != NULL) { + jsz += snprintf(buf + jsz, + sizeof(buf) - jsz, + pargv[1] != NULL ? "%s " : "%s", + pargv[0]); + pargv++; + } +#endif + mstr = buf; + } else +#ifdef __APPLE__ + { + /* + * comm is limited to 15 bytes (MAXCOMLEN - 1). + * Try to use argv[0] (trimmed) if available. + */ + mstr = NULL; + pargv = sysmon_row_get_value(kp, SYSMON_ATTR_PROC_ARGUMENTS); + if (pargv != NULL && xpc_array_get_count(pargv) > 0) { + const char *tmp = xpc_array_get_string(pargv, 0); + if (tmp != NULL) { + mstr = strrchr(tmp, '/'); + if (mstr != NULL) { + mstr++; + } else { + mstr = (char *)tmp; + } + } + } + + /* Fall back to "comm" if we failed to get argv[0]. */ + if (mstr == NULL || *mstr == '\0') { + mstr = (char *)xpc_string_get_string_ptr(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_COMM)); + } + + /* Couldn't find process name, it probably exited. */ + if (mstr == NULL) { + continue; + } + } +#else + mstr = kp->ki_comm; +#endif + + rv = regexec(®, mstr, 1, ®match, 0); + if (rv == 0) { + if (fullmatch) { + if (regmatch.rm_so == 0 && + regmatch.rm_eo == + (off_t)strlen(mstr)) + selected[i] = 1; + } else + selected[i] = 1; + } else if (rv != REG_NOMATCH) { + regerror(rv, ®, buf, sizeof(buf)); + errx(STATUS_ERROR, + "Regular expression evaluation error (%s)", + buf); + } + if (debug_opt > 1) { + const char *rv_res = "NoMatch"; + if (selected[i]) + rv_res = "Matched"; + fprintf(stderr, "* %s %5d %3d %s\n", rv_res, +#ifdef __APPLE__ + (pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)), + (uid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_UID)), + mstr); +#else + kp->ki_pid, kp->ki_uid, mstr); +#endif + } + } + + regfree(®); + } + +#ifdef __APPLE__ + for (i = 0; i < nproc; i++) { + kp = sysmon_table_get_row(plist, i); +#else + for (i = 0, kp = plist; i < nproc; i++, kp++) { +#endif + if (PSKIP(kp)) + continue; + +#ifdef __APPLE__ + if (pidfromfile >= 0 && (pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)) != pidfromfile) { +#else + if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) { +#endif + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &ruidlist, li_chain) +#ifdef __APPLE__ + if ((uid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_RUID)) == (uid_t)li->li_number) +#else + if (kp->ki_ruid == (uid_t)li->li_number) +#endif + break; + if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &rgidlist, li_chain) +#ifdef __APPLE__ + if ((gid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_RGID)) == (gid_t)li->li_number) +#else + if (kp->ki_rgid == (gid_t)li->li_number) +#endif + break; + if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &euidlist, li_chain) +#ifdef __APPLE__ + if ((uid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_UID)) == (uid_t)li->li_number) +#else + if (kp->ki_uid == (uid_t)li->li_number) +#endif + break; + if (SLIST_FIRST(&euidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &ppidlist, li_chain) +#ifdef __APPLE__ + if ((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PPID)) == (pid_t)li->li_number) +#else + if (kp->ki_ppid == (pid_t)li->li_number) +#endif + break; + if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &pgrplist, li_chain) +#ifdef __APPLE__ + if ((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PGID)) == (pid_t)li->li_number) +#else + if (kp->ki_pgid == (pid_t)li->li_number) +#endif + break; + if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &tdevlist, li_chain) { + if (li->li_number == -1 && +#ifdef __APPLE__ + (xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_FLAGS)) & PROC_FLAG_CONTROLT) == 0) +#else + (kp->ki_flag & P_CONTROLT) == 0) +#endif + break; +#ifdef __APPLE__ + if ((dev_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_TDEV)) == (dev_t)li->li_number) +#else + if (kp->ki_tdev == (dev_t)li->li_number) +#endif + break; + } + if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + +#ifndef __APPLE__ + SLIST_FOREACH(li, &sidlist, li_chain) + if (kp->ki_sid == (pid_t)li->li_number) + break; + if (SLIST_FIRST(&sidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } + + SLIST_FOREACH(li, &jidlist, li_chain) { + /* A particular jail ID, including 0 (not in jail) */ + if (kp->ki_jid == (int)li->li_number) + break; + /* Any jail */ + if (kp->ki_jid > 0 && li->li_number == -1) + break; + } + if (SLIST_FIRST(&jidlist) != NULL && li == NULL) { + selected[i] = 0; + continue; + } +#endif /* !__APPLE__ */ + + if (argc == 0) + selected[i] = 1; + } + + if (!ancestors) { + pid = mypid; + while (pid) { +#ifdef __APPLE__ + for (i = 0; i < nproc; i++) { + kp = sysmon_table_get_row(plist, i); +#else + for (i = 0, kp = plist; i < nproc; i++, kp++) { +#endif + if (PSKIP(kp)) + continue; +#ifdef __APPLE__ + if ((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)) == pid) { + selected[i] = 0; + pid = (pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PPID)); + break; + } +#else + if (kp->ki_pid == pid) { + selected[i] = 0; + pid = kp->ki_ppid; + break; + } +#endif + } + if (i == nproc) { + if (pid == mypid) + pid = getppid(); + else + break; /* Maybe we're in a jail ? */ + } + } + } + + if (newest || oldest) { +#ifdef __APPLE__ + best_tval = 0; +#else + best_tval.tv_sec = 0; + best_tval.tv_usec = 0; +#endif + bestidx = -1; + +#ifdef __APPLE__ + for (i = 0; i < nproc; i++) { + kp = sysmon_table_get_row(plist, i); +#else + for (i = 0, kp = plist; i < nproc; i++, kp++) { +#endif + if (!selected[i]) + continue; + if (bestidx == -1) { + /* The first entry of the list which matched. */ + ; +#ifdef __APPLE__ + } else if (xpc_date_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_START)) > best_tval) { +#else + } else if (timercmp(&kp->ki_start, &best_tval, >)) { +#endif + /* This entry is newer than previous "best". */ + if (oldest) /* but we want the oldest */ + continue; + } else { + /* This entry is older than previous "best". */ + if (newest) /* but we want the newest */ + continue; + } + /* This entry is better than previous "best" entry. */ +#ifdef __APPLE__ + best_tval = xpc_date_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_START)); +#else + best_tval.tv_sec = kp->ki_start.tv_sec; + best_tval.tv_usec = kp->ki_start.tv_usec; +#endif + bestidx = i; + } + + memset(selected, 0, nproc); + if (bestidx != -1) + selected[bestidx] = 1; + } + + /* + * Take the appropriate action for each matched process, if any. + */ + did_action = 0; +#ifdef __APPLE__ + for (i = 0, rv = 0; i < nproc; i++) { + kp = sysmon_table_get_row(plist, i); +#else + for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) { +#endif + if (PSKIP(kp)) + continue; + if (selected[i]) { + if (longfmt && !pgrep) { + did_action = 1; +#ifdef __APPLE__ + printf("kill -%d %d\n", signum, (int)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID))); +#else + printf("kill -%d %d\n", signum, kp->ki_pid); +#endif + } + if (inverse) + continue; + } else if (!inverse) + continue; + rv |= (*action)(kp); + } + if (!did_action && !pgrep && longfmt) + fprintf(stderr, + "No matching processes belonging to you were found\n"); + + exit(rv ? STATUS_MATCH : STATUS_NOMATCH); +} + +static void +usage(void) +{ + const char *ustr; + + if (pgrep) +#ifdef __APPLE__ + ustr = "[-Lfilnoqvx] [-d delim]"; +#else + ustr = "[-LSfilnoqvx] [-d delim]"; +#endif + else + ustr = "[-signal] [-ILfilnovx]"; + + fprintf(stderr, +#ifdef __APPLE__ + "usage: %s %s [-F pidfile] [-G gid]\n" + " [-P ppid] [-U uid] [-g pgrp]\n" +#else + "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n" + " [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n" +#endif + " [-t tty] [-u euid] pattern ...\n", getprogname(), + ustr); + + exit(STATUS_BADUSAGE); +} + +static void +#ifdef __APPLE__ +show_process(const sysmon_row_t kp) +#else +show_process(const struct kinfo_proc *kp) +#endif +{ +#ifdef __APPLE__ + xpc_object_t argv; +#else + char **argv; +#endif + + if (quiet) { + assert(pgrep); + return; + } +#ifdef __APPLE__ + if ((longfmt || !pgrep) && matchargs && + (argv = sysmon_row_get_value(kp, SYSMON_ATTR_PROC_ARGUMENTS)) != NULL) { + printf("%d ", (int)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID))); + (void)xpc_array_apply(argv, ^(size_t index, xpc_object_t value) { + printf("%s", xpc_string_get_string_ptr(value)); + if (index < xpc_array_get_count(argv) - 1) + putchar(' '); + return (bool)true; + }); + } else if (longfmt || !pgrep) + printf("%d %s", + (int)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)), + xpc_string_get_string_ptr(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_COMM))); + else + printf("%d", (int)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID))); +#else + if ((longfmt || !pgrep) && matchargs && + (argv = kvm_getargv(kd, kp, 0)) != NULL) { + printf("%d ", (int)kp->ki_pid); + for (; *argv != NULL; argv++) { + printf("%s", *argv); + if (argv[1] != NULL) + putchar(' '); + } + } else if (longfmt || !pgrep) + printf("%d %s", (int)kp->ki_pid, kp->ki_comm); + else + printf("%d", (int)kp->ki_pid); +#endif +} + +static int +#ifdef __APPLE__ +killact(const sysmon_row_t kp) +#else +killact(const struct kinfo_proc *kp) +#endif +{ + int ch, first; + + if (interactive) { + /* + * Be careful, ask before killing. + */ + printf("kill "); + show_process(kp); + printf("? "); + fflush(stdout); + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + if (first != 'y' && first != 'Y') + return (1); + } +#ifdef __APPLE__ + if (kill((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)), signum) == -1) { +#else + if (kill(kp->ki_pid, signum) == -1) { +#endif + /* + * Check for ESRCH, which indicates that the process + * disappeared between us matching it and us + * signalling it; don't issue a warning about it. + */ + if (errno != ESRCH) +#ifdef __APPLE__ + warn("signalling pid %d", (int)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID))); +#else + warn("signalling pid %d", (int)kp->ki_pid); +#endif + /* + * Return 0 to indicate that the process should not be + * considered a match, since we didn't actually get to + * signal it. + */ + return (0); + } + return (1); +} + +static int +#ifdef __APPLE__ +grepact(const sysmon_row_t kp) +#else +grepact(const struct kinfo_proc *kp) +#endif +{ + + show_process(kp); + if (!quiet) + printf("%s", delim); + return (1); +} + +static void +makelist(struct listhead *head, enum listtype type, char *src) +{ + struct list *li; + struct passwd *pw; + struct group *gr; + struct stat st; + const char *cp; + char *sp, *ep, buf[MAXPATHLEN]; + int empty; + + empty = 1; + + while ((sp = strsep(&src, ",")) != NULL) { + if (*sp == '\0') + usage(); + + if ((li = malloc(sizeof(*li))) == NULL) { + err(STATUS_ERROR, "Cannot allocate %zu bytes", + sizeof(*li)); + } + + SLIST_INSERT_HEAD(head, li, li_chain); + empty = 0; + + li->li_number = (uid_t)strtol(sp, &ep, 0); + if (*ep == '\0') { + switch (type) { + case LT_PGRP: + if (li->li_number == 0) + li->li_number = getpgrp(); + break; +#ifndef __APPLE__ + case LT_SID: + if (li->li_number == 0) + li->li_number = getsid(mypid); + break; + case LT_JID: + if (li->li_number < 0) + errx(STATUS_BADUSAGE, + "Negative jail ID `%s'", sp); + /* For compatibility with old -j */ + if (li->li_number == 0) + li->li_number = -1; /* any jail */ + break; +#endif /* !__APPLE__ */ + case LT_TTY: + if (li->li_number < 0) + errx(STATUS_BADUSAGE, + "Negative /dev/pts tty `%s'", sp); + snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s", + sp); + if (stat(buf, &st) != -1) + goto foundtty; + if (errno == ENOENT) + errx(STATUS_BADUSAGE, "No such tty: `" + _PATH_DEV "pts/%s'", sp); + err(STATUS_ERROR, "Cannot access `" + _PATH_DEV "pts/%s'", sp); + break; + default: + break; + } + continue; + } + + switch (type) { + case LT_USER: + if ((pw = getpwnam(sp)) == NULL) + errx(STATUS_BADUSAGE, "Unknown user `%s'", sp); + li->li_number = pw->pw_uid; + break; + case LT_GROUP: + if ((gr = getgrnam(sp)) == NULL) + errx(STATUS_BADUSAGE, "Unknown group `%s'", sp); + li->li_number = gr->gr_gid; + break; + case LT_TTY: + if (strcmp(sp, "-") == 0) { + li->li_number = -1; + break; + } else if (strcmp(sp, "co") == 0) { + cp = "console"; + } else { + cp = sp; + } + + snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp); + if (stat(buf, &st) != -1) + goto foundtty; + + snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp); + if (stat(buf, &st) != -1) + goto foundtty; + + if (errno == ENOENT) + errx(STATUS_BADUSAGE, "No such tty: `%s'", sp); + err(STATUS_ERROR, "Cannot access `%s'", sp); + +foundtty: if ((st.st_mode & S_IFCHR) == 0) + errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp); + + li->li_number = st.st_rdev; + break; +#ifndef __APPLE__ + case LT_JID: + if (strcmp(sp, "none") == 0) + li->li_number = 0; + else if (strcmp(sp, "any") == 0) + li->li_number = -1; + else if (*ep != '\0') + errx(STATUS_BADUSAGE, + "Invalid jail ID `%s'", sp); + break; +#endif /* !__APPLE__ */ + default: + usage(); + } + } + + if (empty) + usage(); +} + +static int +takepid(const char *pidfile, int pidfilelock) +{ + char *endp, line[BUFSIZ]; + FILE *fh; + long rval; + + fh = fopen(pidfile, "r"); + if (fh == NULL) + err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile); + + if (pidfilelock) { + /* + * If we can lock pidfile, this means that daemon is not + * running, so would be better not to kill some random process. + */ + if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) { + (void)fclose(fh); + errx(STATUS_ERROR, "File '%s' can be locked", pidfile); + } else { + if (errno != EWOULDBLOCK) { + errx(STATUS_ERROR, + "Error while locking file '%s'", pidfile); + } + } + } + + if (fgets(line, sizeof(line), fh) == NULL) { + if (feof(fh)) { + (void)fclose(fh); + errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile); + } + (void)fclose(fh); + err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile); + } + (void)fclose(fh); + + rval = strtol(line, &endp, 10); + if (*endp != '\0' && !isspace((unsigned char)*endp)) + errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile); + else if (rval < MIN_PID || rval > MAX_PID) + errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile); + return (rval); +} diff --git a/adv_cmds/ps/entitlements.plist b/adv_cmds/ps/entitlements.plist new file mode 100644 index 0000000..eaaf1de --- /dev/null +++ b/adv_cmds/ps/entitlements.plist @@ -0,0 +1,10 @@ + + + + + com.apple.system-task-ports + + task_for_pid-allow + + + diff --git a/adv_cmds/ps/extern.h b/adv_cmds/ps/extern.h new file mode 100644 index 0000000..d3f6503 --- /dev/null +++ b/adv_cmds/ps/extern.h @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.3 (Berkeley) 4/2/94 + * $FreeBSD: extern.h,v 1.8 1998/05/25 05:07:17 steve Exp $ + */ + +struct kinfo; +struct nlist; +struct var; +struct varent; + +extern fixpt_t ccpu; +extern int cflag, eval, fscale, nlistread, rawcpu; +#ifdef __APPLE__ +extern uint64_t mempages; +#else +extern unsigned long mempages; +#endif +extern time_t now; +extern int showthreads, sumrusage, termwidth, totwidth; +extern STAILQ_HEAD(velisthead, varent) varlist; + +__BEGIN_DECLS +int get_task_info(KINFO *); +void command(KINFO *, VARENT *); +void just_command(KINFO *, VARENT *); +void args(KINFO *, VARENT *); +int s_command(KINFO *); +int s_just_command(KINFO *); +int s_args(KINFO *); +void cputime(KINFO *, VARENT *); +void pstime(KINFO *, VARENT *); +void p_etime(KINFO *, VARENT *); +int s_etime(KINFO *); +void putime(KINFO *, VARENT *); +int donlist(void); +void evar(KINFO *, VARENT *); +VARENT *find_varentry(VAR *); +const char *fmt_argv(char **, char *, size_t); +int getpcpu(KINFO *); +double getpmem(KINFO *); +void logname(KINFO *, VARENT *); +void longtname(KINFO *, VARENT *); +void lstarted(KINFO *, VARENT *); +void maxrss(KINFO *, VARENT *); +void nlisterr(struct nlist *); +void p_rssize(KINFO *, VARENT *); +void pagein(KINFO *, VARENT *); +void parsefmt(const char *, int); +void pcpu(KINFO *, VARENT *); +void pmem(KINFO *, VARENT *); +void pri(KINFO *, VARENT *); +void rtprior(KINFO *, VARENT *); +void printheader(void); +void pvar(KINFO *, VARENT *); +void runame(KINFO *, VARENT *); +void rvar(KINFO *, VARENT *); +int s_runame(KINFO *); +int s_uname(KINFO *); +void showkey(void); +void started(KINFO *, VARENT *); +void state(KINFO *, VARENT *); +void tdev(KINFO *, VARENT *); +void tname(KINFO *, VARENT *); +void tsize(KINFO *, VARENT *); +void ucomm(KINFO *, VARENT *); +void uname(KINFO *, VARENT *); +void uvar(KINFO *, VARENT *); +void vsize(KINFO *, VARENT *); +void wchan(KINFO *, VARENT *); +void wq(KINFO *, VARENT *); +__END_DECLS diff --git a/adv_cmds/ps/fmt.c b/adv_cmds/ps/fmt.c new file mode 100644 index 0000000..26ba3dc --- /dev/null +++ b/adv_cmds/ps/fmt.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)fmt.c 8.4 (Berkeley) 4/15/94"; +#endif +#endif + +#include +__FBSDID("$FreeBSD: src/bin/ps/fmt.c,v 1.34 2004/06/22 02:18:29 gad Exp $"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +static char *cmdpart(char *); +static char *shquote(char **); + +static char * +shquote(char **argv) +{ + long arg_max; + static size_t buf_size; + size_t len; + char **p, *dst, *src; + static char *buf = NULL; + + if (buf == NULL) { + if ((arg_max = sysconf(_SC_ARG_MAX)) == -1) + errx(1, "sysconf _SC_ARG_MAX failed"); + if (arg_max >= LONG_MAX / 4 || arg_max >= (long)(SIZE_MAX / 4)) + errx(1, "sysconf _SC_ARG_MAX preposterously large"); + buf_size = 4 * arg_max + 1; + if ((buf = malloc(buf_size)) == NULL) + errx(1, "malloc failed"); + } + + if (*argv == NULL) { + buf[0] = '\0'; + return (buf); + } + dst = buf; + for (p = argv; (src = *p++) != NULL; ) { + if (*src == '\0') + continue; + len = (buf_size - 1 - (dst - buf)) / 4; + strvisx(dst, src, strlen(src) < len ? strlen(src) : len, + VIS_NL | VIS_CSTYLE); + while (*dst != '\0') + dst++; + if ((buf_size - 1 - (dst - buf)) / 4 > 0) + *dst++ = ' '; + } + /* Chop off trailing space */ + if (dst != buf && dst[-1] == ' ') + dst--; + *dst = '\0'; + return (buf); +} + +static char * +cmdpart(char *arg0) +{ + char *cp; + + return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0); +} + +const char * +fmt_argv(char **argv, char *cmd, size_t maxlen) +{ + size_t len; + char *ap, *cp; + + if (argv == NULL || argv[0] == NULL) { + if (cmd == NULL) + return (""); + ap = NULL; + len = maxlen + 3; + } else { + ap = shquote(argv); + len = strlen(ap) + maxlen + 4; + } + cp = malloc(len); + if (cp == NULL) + errx(1, "malloc failed"); + if (ap == NULL) + sprintf(cp, "[%.*s]", (int)maxlen, cmd); + else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0) + sprintf(cp, "%s (%.*s)", ap, (int)maxlen, cmd); + else + strcpy(cp, ap); + return (cp); +} diff --git a/adv_cmds/ps/keyword.c b/adv_cmds/ps/keyword.c new file mode 100644 index 0000000..ff311b4 --- /dev/null +++ b/adv_cmds/ps/keyword.c @@ -0,0 +1,340 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)keyword.c 8.5 (Berkeley) 4/2/94"; +#else +static const char rcsid[] = + "$FreeBSD: keyword.c,v 1.23 1999/01/26 02:38:09 julian Exp $"; +#endif /* not lint */ +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ps.h" + +VAR *findvar(char *, int, char **header); +static int vcmp(const void *, const void *); + +/* Compute offset in common structures. */ +#define POFF(x) offsetof(struct extern_proc, x) +#define EOFF(x) offsetof(struct eproc, x) +#define UOFF(x) offsetof(struct usave, x) +#define ROFF(x) offsetof(struct rusage, x) + +#define EMULLEN 13 /* enough for "FreeBSD ELF32" */ +#define LWPFMT "d" +#define LWPLEN 6 +#define NLWPFMT "d" +#define NLWPLEN 4 +#ifdef __APPLE__ +#define UIDFMT "d" +#else +#define UIDFMT "u" +#endif +#define UIDLEN 5 +#define PIDFMT "d" +#define PIDLEN 5 +#define USERLEN 16 + +/* PLEASE KEEP THE TABLE BELOW SORTED ALPHABETICALLY!!! */ +static VAR var[] = { + /* 4133537: 5 characters to accomodate 100% or more */ + {"%cpu", "%CPU", NULL, 0, pcpu, NULL, 5, 0, CHAR, NULL, 0}, + {"%mem", "%MEM", NULL, 0, pmem, NULL, 4}, + {"acflag", "ACFLG", + NULL, 0, pvar, NULL, 3, POFF(p_acflag), USHORT, "x"}, + {"acflg", "", "acflag"}, + {"args", "ARGS", NULL, COMM|LJUST|USER|DSIZ, args, s_args, 64}, + {"blocked", "", "sigmask"}, + {"caught", "", "sigcatch"}, + {"comm", "COMM", NULL, COMM|LJUST|USER|DSIZ, just_command, s_just_command, 16}, + {"command", "COMMAND", NULL, COMM|LJUST|USER|DSIZ, command, s_command, 16}, + {"cpu", "CPU", NULL, 0, pvar, NULL, 3, POFF(p_estcpu), UINT, "d"}, + {"cputime", "", "time"}, + {"etime", "ELAPSED", NULL, USER|DSIZ, p_etime, s_etime, 20}, + /* 5861775: Make F column 8 characters. */ + {"f", "F", NULL, 0, pvar, NULL, 8, POFF(p_flag), INT, "x"}, + {"flags", "", "f"}, + {"gid", "GID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_ucred.cr_gid), + UINT, UIDFMT}, + {"group", "GROUP", "gid"}, + {"ignored", "", "sigignore"}, + {"inblk", "INBLK", + NULL, USER, rvar, NULL, 4, ROFF(ru_inblock), LONG, "ld"}, + {"inblock", "", "inblk"}, + {"jobc", "JOBC", NULL, 0, evar, NULL, 4, EOFF(e_jobc), SHORT, "d"}, + {"ktrace", "KTRACE", + NULL, 0, pvar, NULL, 8, POFF(p_traceflag), INT, "x"}, + {"ktracep", "KTRACEP", + NULL, 0, pvar, NULL, 8, POFF(p_tracep), LONG, "lx"}, + {"lim", "LIM", NULL, 0, maxrss, NULL, 5}, + {"login", "LOGIN", NULL, LJUST, logname, NULL, MAXLOGNAME-1}, + {"logname", "", "login"}, + {"lstart", "STARTED", NULL, LJUST|USER, lstarted, NULL, 28}, + {"majflt", "MAJFLT", + NULL, USER, rvar, NULL, 4, ROFF(ru_majflt), LONG, "ld"}, + {"minflt", "MINFLT", + NULL, USER, rvar, NULL, 4, ROFF(ru_minflt), LONG, "ld"}, + {"msgrcv", "MSGRCV", + NULL, USER, rvar, NULL, 4, ROFF(ru_msgrcv), LONG, "ld"}, + {"msgsnd", "MSGSND", + NULL, USER, rvar, NULL, 4, ROFF(ru_msgsnd), LONG, "ld"}, + {"ni", "", "nice"}, + {"nice", "NI", NULL, 0, pvar, NULL, 2, POFF(p_nice), CHAR, "d"}, + {"nivcsw", "NIVCSW", + NULL, USER, rvar, NULL, 5, ROFF(ru_nivcsw), LONG, "ld"}, + {"nsignals", "", "nsigs"}, + {"nsigs", "NSIGS", + NULL, USER, rvar, NULL, 4, ROFF(ru_nsignals), LONG, "ld"}, + {"nswap", "NSWAP", + NULL, USER, rvar, NULL, 4, ROFF(ru_nswap), LONG, "ld"}, + {"nvcsw", "NVCSW", + NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw), LONG, "ld"}, + {"nwchan", "WCHAN", NULL, 0, pvar, NULL, 6, POFF(p_wchan), KPTR, "lx"}, + {"oublk", "OUBLK", + NULL, USER, rvar, NULL, 4, ROFF(ru_oublock), LONG, "ld"}, + {"oublock", "", "oublk"}, + {"p_ru", "P_RU", NULL, 0, pvar, NULL, 6, POFF(p_ru), KPTR, "lx"}, + {"paddr", "PADDR", NULL, 0, evar, NULL, sizeof(void *) * 2, EOFF(e_paddr), KPTR, "lx"}, + {"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6}, + {"pcpu", "", "%cpu"}, + {"pending", "", "sig"}, + {"pgid", "PGID", + NULL, 0, evar, NULL, PIDLEN, EOFF(e_pgid), UINT, PIDFMT}, + {"pid", "PID", NULL, 0, pvar, NULL, PIDLEN, POFF(p_pid), UINT, PIDFMT}, + {"pmem", "", "%mem"}, + {"ppid", "PPID", + NULL, 0, evar, NULL, PIDLEN, EOFF(e_ppid), UINT, PIDFMT}, + {"pri", "PRI", NULL, 0, pri, NULL, 3}, + {"pstime", "", "stime"}, + {"putime", "", "utime"}, + {"re", "RE", NULL, 0, pvar, NULL, 3, POFF(p_swtime), UINT, "d"}, + {"rgid", "RGID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_pcred.p_rgid), + UINT, UIDFMT}, + {"rgroup", "RGROUP", "rgid"}, + {"rss", "RSS", NULL, 0, p_rssize, NULL, 6}, +#if FIXME + {"rtprio", "RTPRIO", NULL, 0, rtprior, NULL, 7, POFF(p_rtprio)}, +#endif /* FIXME */ + {"ruid", "RUID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_pcred.p_ruid), + UINT, UIDFMT}, + {"ruser", "RUSER", NULL, LJUST|DSIZ, runame, s_runame, USERLEN}, + {"sess", "SESS", NULL, 0, evar, NULL, 6, EOFF(e_sess), KPTR, "lx"}, + {"sig", "PENDING", NULL, 0, pvar, NULL, 8, POFF(p_siglist), INT, "x"}, +#if FIXME + {"sigcatch", "CAUGHT", + NULL, 0, evar, NULL, 8, EOFF(e_procsig.ps_sigcatch), UINT, "x"}, + {"sigignore", "IGNORED", + NULL, 0, evar, NULL, 8, EOFF(e_procsig.ps_sigignore), UINT, "x"}, +#endif /* FIXME */ + {"sigmask", "BLOCKED", + NULL, 0, pvar, NULL, 8, POFF(p_sigmask), UINT, "x"}, + {"sl", "SL", NULL, 0, pvar, NULL, 3, POFF(p_slptime), UINT, "d"}, + {"start", "STARTED", NULL, LJUST|USER, started, NULL, 7}, + {"stat", "", "state"}, + {"state", "STAT", NULL, 0, state, NULL, 4}, + {"stime", "STIME", NULL, USER, pstime, NULL, 9}, + {"svgid", "SVGID", NULL, 0, + evar, NULL, UIDLEN, EOFF(e_pcred.p_svgid), UINT, UIDFMT}, + {"svuid", "SVUID", NULL, 0, + evar, NULL, UIDLEN, EOFF(e_pcred.p_svuid), UINT, UIDFMT}, + {"tdev", "TDEV", NULL, 0, tdev, NULL, 4}, + {"time", "TIME", NULL, USER, cputime, NULL, 9}, + {"tpgid", "TPGID", + NULL, 0, evar, NULL, 4, EOFF(e_tpgid), UINT, PIDFMT}, + {"tsess", "TSESS", NULL, 0, evar, NULL, 6, EOFF(e_tsess), KPTR, "lx"}, + {"tsiz", "TSIZ", NULL, 0, tsize, NULL, 8}, + {"tt", "TT ", NULL, 0, tname, NULL, 5}, + {"tty", "TTY", NULL, LJUST, longtname, NULL, 8}, + {"ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN}, + {"uid", "UID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_ucred.cr_uid), + UINT, UIDFMT}, + {"upr", "UPR", NULL, 0, pvar, NULL, 3, POFF(p_usrpri), CHAR, "d"}, + {"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN}, + {"usrpri", "", "upr"}, + {"utime", "UTIME", NULL, USER, putime, NULL, 9}, + {"vsize", "", "vsz"}, + {"vsz", "VSZ", NULL, 0, vsize, NULL, 8}, + {"wchan", "WCHAN", NULL, LJUST, wchan, NULL, 6}, + {"wq", "WQ", NULL, 0, wq, NULL, 4, 0, CHAR, NULL, 0}, + {"wqb", "WQB", NULL, 0, wq, NULL, 4, 0, CHAR, NULL, 0}, + {"wql", "WQL", NULL, 0, wq, NULL, 3, 0, CHAR, NULL, 0}, + {"wqr", "WQR", NULL, 0, wq, NULL, 4, 0, CHAR, NULL, 0}, + {"xstat", "XSTAT", NULL, 0, pvar, NULL, 4, POFF(p_xstat), USHORT, "x"}, + {""}, +}; + +void +showkey(void) +{ + VAR *v; + int i; + const char *p, *sep; + + i = 0; + sep = ""; + for (v = var; *(p = v->name); ++v) { + int len = strlen(p); + if (termwidth && (i += len + 1) > termwidth) { + i = len; + sep = "\n"; + } + (void) printf("%s%s", sep, p); + sep = " "; + } + (void) printf("\n"); +} + +void +parsefmt(const char *p, int user) +{ + char *tempstr, *tempstr1; + +#define FMTSEP " \t,\n" + tempstr1 = tempstr = strdup(p); + while (tempstr && *tempstr) { + char *cp, *hp; + VAR *v; + struct varent *vent; + +#ifndef __APPLE__ + /* + * If an item contains an equals sign, it specifies a column + * header, may contain embedded separator characters and + * is always the last item. + */ + if (tempstr[strcspn(tempstr, "="FMTSEP)] != '=') +#endif /* !__APPLE__ */ + while ((cp = strsep(&tempstr, FMTSEP)) != NULL && + *cp == '\0') + /* void */; +#ifndef __APPLE__ + else { + cp = tempstr; + tempstr = NULL; + } +#endif /* !__APPLE__ */ + if (cp == NULL || !(v = findvar(cp, user, &hp))) + continue; + if (!user) { + /* + * If the user is NOT adding this field manually, + * get on with our lives if this VAR is already + * represented in the list. + */ + vent = find_varentry(v); + if (vent != NULL) + continue; + } + if ((vent = malloc(sizeof(struct varent))) == NULL) + errx(1, "malloc failed"); + vent->header = v->header; + if (hp) { + hp = strdup(hp); + if (hp) + vent->header = hp; + } + vent->var = malloc(sizeof(*vent->var)); + if (vent->var == NULL) + errx(1, "malloc failed"); + memcpy(vent->var, v, sizeof(*vent->var)); + STAILQ_INSERT_TAIL(&varlist, vent, next_ve); + } + free(tempstr1); + if (STAILQ_EMPTY(&varlist)) { + warnx("no valid keywords; valid keywords:"); + showkey(); + exit(1); + } +} + +VAR * +findvar(char *p, int user, char **header) +{ + size_t rflen; + VAR *v, key; + char *hp, *realfmt; + + hp = strchr(p, '='); + if (hp) + *hp++ = '\0'; + + key.name = p; + v = bsearch(&key, var, sizeof(var)/sizeof(VAR) - 1, sizeof(VAR), vcmp); + + if (v && v->alias) { + /* + * If the user specified an alternate-header for this + * (aliased) format-name, then we need to copy that + * alternate-header when making the recursive call to + * process the alias. + */ + if (hp == NULL) + parsefmt(v->alias, user); + else { + /* + * XXX - This processing will not be correct for + * any alias which expands into a list of format + * keywords. Presently there are no aliases + * which do that. + */ + rflen = strlen(v->alias) + strlen(hp) + 2; + realfmt = malloc(rflen); + snprintf(realfmt, rflen, "%s=%s", v->alias, hp); + parsefmt(realfmt, user); + } + return ((VAR *)NULL); + } + if (!v) { + warnx("%s: keyword not found", p); + eval = 1; + } + if (header) + *header = hp; + return (v); +} + +static int +vcmp(const void *a, const void *b) +{ + return (strcmp(((const VAR *)a)->name, ((const VAR *)b)->name)); +} diff --git a/adv_cmds/ps/nlist.c b/adv_cmds/ps/nlist.c new file mode 100644 index 0000000..90a2303 --- /dev/null +++ b/adv_cmds/ps/nlist.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)nlist.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/bin/ps/nlist.c,v 1.21 2004/04/06 20:06:49 markm Exp $"); + +#include +#include +#ifdef __APPLE__ +#include +#endif + +#include + +#include "ps.h" + +fixpt_t ccpu; /* kernel _ccpu variable */ +int nlistread; /* if nlist already read. */ +#ifdef __APPLE__ +uint64_t mempages; /* number of pages of phys. memory */ +#else +unsigned long mempages; /* number of pages of phys. memory */ +#endif +int fscale; /* kernel _fscale variable */ + +int +donlist(void) +{ +#ifdef __APPLE__ + int mib[2]; +#endif + size_t oldlen; + +#ifdef __APPLE__ + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + oldlen = sizeof(mempages); + if (sysctl(mib, 2, &mempages, &oldlen, NULL, 0) == -1) + return (1); + fscale = 100; +#else + oldlen = sizeof(ccpu); + if (sysctlbyname("kern.ccpu", &ccpu, &oldlen, NULL, 0) == -1) + return (1); + oldlen = sizeof(fscale); + if (sysctlbyname("kern.fscale", &fscale, &oldlen, NULL, 0) == -1) + return (1); + oldlen = sizeof(mempages); + if (sysctlbyname("hw.availpages", &mempages, &oldlen, NULL, 0) == -1) + return (1); +#endif + nlistread = 1; + return (0); +} diff --git a/adv_cmds/ps/print.c b/adv_cmds/ps/print.c new file mode 100644 index 0000000..103ba48 --- /dev/null +++ b/adv_cmds/ps/print.c @@ -0,0 +1,1225 @@ +/*- + * 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 +#if 0 +static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94"; +#endif +static const char rcsid[] = + "$FreeBSD: print.c,v 1.33 1998/11/25 09:34:00 dfr Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if FIXME +#include +#endif /* FIXME */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +extern int mflg, print_all_thread, print_thread_num; + +void +printheader(void) +{ + VAR *v; + struct varent *vent; + + STAILQ_FOREACH(vent, &varlist, next_ve) + if (*vent->header != '\0') + break; + if (!vent) + return; + + STAILQ_FOREACH(vent, &varlist, next_ve) { + v = vent->var; + if (v->flag & LJUST) { + if (STAILQ_NEXT(vent, next_ve) == NULL) /* last one */ + (void)printf("%s", vent->header); + else + (void)printf("%-*s", v->width, vent->header); + } else + (void)printf("%*s", v->width, vent->header); + if (STAILQ_NEXT(vent, next_ve) != NULL) + (void)putchar(' '); + } + (void)putchar('\n'); +} + +/* + * Get command and arguments. + * + * If the global variable eflg is non-zero and the user has permission to view + * the process's environment, the environment is included. + * + * on return argvlen is the length of the extracted string, argv0len is + * the length of the command (same as argvlen if show_args is true) + */ +static void +getproclline(KINFO *k, char **command_name, int *argvlen, int *argv0len, + int show_args) +{ + int mib[3], argmax, nargs, c = 0; + size_t size; + char *procargs, *sp, *np, *cp; + extern int eflg; + + /* Get the maximum process arguments size. */ + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + + size = sizeof(argmax); + if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) { + goto ERROR_A; + } + + /* Allocate space for the arguments. */ + procargs = (char *)malloc(argmax); + if (procargs == NULL) { + goto ERROR_A; + } + + /* + * Make a sysctl() call to get the raw argument space of the process. + * The layout is documented in start.s, which is part of the Csu + * project. In summary, it looks like: + * + * /---------------\ 0x00000000 + * : : + * : : + * |---------------| + * | argc | + * |---------------| + * | arg[0] | + * |---------------| + * : : + * : : + * |---------------| + * | arg[argc - 1] | + * |---------------| + * | 0 | + * |---------------| + * | env[0] | + * |---------------| + * : : + * : : + * |---------------| + * | env[n] | + * |---------------| + * | 0 | + * |---------------| <-- Beginning of data returned by sysctl() is here. + * | argc | + * |---------------| + * | exec_path | + * |:::::::::::::::| + * | | + * | String area. | + * | | + * |---------------| <-- Top of stack. + * : : + * : : + * \---------------/ 0xffffffff + */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = KI_PROC(k)->p_pid; + + size = (size_t)argmax; + if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) { + goto ERROR_B; + } + + memcpy(&nargs, procargs, sizeof(nargs)); + cp = procargs + sizeof(nargs); + + /* Skip the saved exec_path. */ + for (; cp < &procargs[size]; cp++) { + if (*cp == '\0') { + /* End of exec_path reached. */ + break; + } + } + if (cp == &procargs[size]) { + goto ERROR_B; + } + + /* Skip trailing '\0' characters. */ + for (; cp < &procargs[size]; cp++) { + if (*cp != '\0') { + /* Beginning of first argument reached. */ + break; + } + } + if (cp == &procargs[size]) { + goto ERROR_B; + } + /* Save where the argv[0] string starts. */ + sp = cp; + + /* + * Iterate through the '\0'-terminated strings and convert '\0' to ' ' + * until a string is found that has a '=' character in it (or there are + * no more strings in procargs). There is no way to deterministically + * know where the command arguments end and the environment strings + * start, which is why the '=' character is searched for as a heuristic. + */ + for (np = NULL; c < nargs && cp < &procargs[size]; cp++) { + if (*cp == '\0') { + c++; + if (np != NULL) { + /* Convert previous '\0'. */ + *np = ' '; + } else { + *argv0len = cp - sp; + } + /* Note location of current '\0'. */ + np = cp; + + if (!show_args) { + /* + * Don't convert '\0' characters to ' '. + * However, we needed to know that the + * command name was terminated, which we + * now know. + */ + break; + } + } + } + + /* + * If eflg is non-zero, continue converting '\0' characters to ' ' + * characters until no more strings that look like environment settings + * follow. + */ + if ( show_args && (eflg != 0) && ( (getuid() == 0) || (KI_EPROC(k)->e_pcred.p_ruid == getuid()) ) ) { + for (; cp < &procargs[size]; cp++) { + if (*cp == '\0') { + if (np != NULL) { + if (&np[1] == cp) { + /* + * Two '\0' characters in a row. + * This should normally only + * happen after all the strings + * have been seen, but in any + * case, stop parsing. + */ + break; + } + /* Convert previous '\0'. */ + *np = ' '; + } + /* Note location of current '\0'. */ + np = cp; + } + } + } + + /* + * sp points to the beginning of the arguments/environment string, and + * np should point to the '\0' terminator for the string. + */ + if (np == NULL || np == sp) { + /* Empty or unterminated string. */ + goto ERROR_B; + } + + /* Make a copy of the string. */ + *argvlen = asprintf(command_name, "%s", sp); + + /* Clean up. */ + free(procargs); + return; + + ERROR_B: + free(procargs); + ERROR_A: + *argv0len = *argvlen + = asprintf(command_name, "(%s)", KI_PROC(k)->p_comm); +} + +/* Return value is malloc'ed, please free it */ +char * +get_command_and_or_args(KINFO *k, int show_cmd, int show_args) +{ + char *vis_args; + + char *rawcmd, *cmd; + int cmdlen, argv0len = 0; + + + if(!mflg || (print_all_thread && (print_thread_num== 0))) { + getproclline(k, &rawcmd, &cmdlen, &argv0len, show_args); + + if (cflag) { + /* Ignore the path in cmd, if any. */ + for (cmd = &rawcmd[cmdlen - 1]; cmd > rawcmd; cmd--) { + if (*cmd == '/') { + cmd++; + break; + } + } + } else { + cmd = rawcmd; + } + + if (!show_cmd) { + cmd += argv0len; + if (*cmd) { + cmd++; + } + } + + if ((vis_args = malloc(strlen(cmd) * 4 + 1)) == NULL) + err(1, NULL); + strvis(vis_args, cmd, VIS_TAB | VIS_NL | VIS_NOSLASH); + free(rawcmd); + return vis_args; + } else { + return strdup(""); + } +} + +int +s_command_and_or_args(KINFO *k, int show_cmd, int show_args) +{ + char *s = get_command_and_or_args(k, show_cmd, show_args); + int sz = strlen(s); + free(s); + + return sz; +} + +void +p_command_and_or_args(KINFO *k, VARENT *ve, int show_cmd, int show_args, + int no_trunc) +{ + VAR *v = ve->var; + char *s = get_command_and_or_args(k, show_cmd, show_args); + + if (STAILQ_NEXT(ve, next_ve) == NULL) { + /* last field */ + if (termwidth == UNLIMITED) { + fputs(s, stdout); + } else { + int left; + char *cp; + + left = termwidth - (totwidth - v->width); + if (left < 1 || no_trunc) { + /* already wrapped, just use std * width */ + left = v->width; + } + for(cp = s; --left >= 0 && *cp;) { + (void)putchar(*cp++); + } + } + } else { + /* XXX env? */ + (void)printf("%-*.*s", v->width, v->width, s); + } + + free(s); +} + +int s_command(KINFO *k) { + return s_command_and_or_args(k, 1, !cflag); +} + +int s_args(KINFO *k) { + return s_command_and_or_args(k, 1, 1); +} + +int s_just_command(KINFO *k) { + return s_command_and_or_args(k, 1, 0); +} + +void command(KINFO *k, VARENT *ve) { + p_command_and_or_args(k, ve, 1, !cflag, 0); +} + +void args(KINFO *k, VARENT *ve) { + p_command_and_or_args(k, ve, 1, 1, 1); +} + +void just_command(KINFO *k, VARENT *ve) { + p_command_and_or_args(k, ve, 1, 0, 0); +} + +void +ucomm(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%-*s", v->width, KI_PROC(k)->p_comm); +} + +char *getname(uid) + uid_t uid; +{ + register struct passwd *pw; + struct passwd *getpwuid(); + + pw = getpwuid((short)uid); + if (pw == NULL) { + return( "UNKNOWN" ); + } + return( pw->pw_name ); +} + +void +logname(KINFO *k, VARENT *ve) +{ + VAR *v; + char *s; + + v = ve->var; + (void)printf("%-*s", v->width, (s = getname(KI_EPROC(k)->e_ucred.cr_uid), *s) ? s : "-"); +} + +extern int mach_state_order(); +void +state(k, ve) + KINFO *k; + VARENT *ve; +{ + struct extern_proc *p; + int flag,j; + char *cp; + VAR *v; + char buf[16]; + extern char mach_state_table[]; + + v = ve->var; + p = KI_PROC(k); + flag = p->p_flag; + cp = buf; + + if(!mflg ) { + switch (p->p_stat) { + + case SSTOP: + *cp = 'T'; + break; + + case SZOMB: + *cp = 'Z'; + break; + + default: + *cp = mach_state_table[k->state]; + } + cp++; + if (p->p_nice < 0) + *cp++ = '<'; + else if (p->p_nice > 0) + *cp++ = 'N'; + if (flag & P_TRACED) + *cp++ = 'X'; + if (flag & P_WEXIT && p->p_stat != SZOMB) + *cp++ = 'E'; + if (flag & P_PPWAIT) + *cp++ = 'V'; + if (flag & (P_SYSTEM | P_NOSWAP | P_PHYSIO)) + *cp++ = 'L'; + if (KI_EPROC(k)->e_flag & EPROC_SLEADER) + *cp++ = 's'; + if ((flag & P_CONTROLT) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid) + *cp++ = '+'; + *cp = '\0'; + (void)printf("%-*s", v->width, buf); + } else if (print_all_thread) { + j = mach_state_order(k->thval[print_thread_num].tb.run_state, + k->thval[print_thread_num].tb.sleep_time); + *cp++ = mach_state_table[j]; + *cp++='\0'; + (void)printf("%-*s", v->width, buf); + } else { + (void)printf("%-*s", v->width, " "); + } + +} + +void +pri(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + int j=0; + char c = '?'; + + v = ve->var; + if (!mflg ) { + (void)printf("%*d", v->width, k->curpri); + } else if (print_all_thread) { + switch(k->thval[print_thread_num].tb.policy) { + case POLICY_TIMESHARE : + j = k->thval[print_thread_num].schedinfo.tshare.cur_priority; + c = 'T'; + break; + case POLICY_FIFO : + j = k->thval[print_thread_num].schedinfo.fifo.base_priority; + c = 'F'; + break; + case POLICY_RR : + j = k->thval[print_thread_num].schedinfo.rr.base_priority; + c = 'R'; + break; + default : + j = 0; + } + (void)printf("%*d%c", v->width - 1, j, c); + }else { + j=0; + (void)printf("%*d", v->width, j); + + } +} + +void +uname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if(!mflg || (print_all_thread && (print_thread_num== 0))) + (void)printf("%-*s", + (int)v->width, + user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0)); + else + (void)printf("%-*s", (int)v->width, " "); +} + +int +s_uname(KINFO *k) +{ + return (strlen(user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0))); +} + +void +runame(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%-*s", + (int)v->width, user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0)); +} + +int +s_runame(KINFO *k) +{ + return (strlen(user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0))); +} + +void +tdev(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char buff[16]; + + v = ve->var; + dev = KI_EPROC(k)->e_tdev; + if (dev == NODEV) + (void)printf("%*s", v->width, "??"); + else { + (void)snprintf(buff, sizeof(buff), + "%d/%d", major(dev), minor(dev)); + (void)printf("%*s", v->width, buff); + } +} + +void +tname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char *ttname; + + v = ve->var; + + if(!mflg || (print_all_thread && (print_thread_num== 0))) { + dev = KI_EPROC(k)->e_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) + (void)printf("%*s ", v->width-1, "??"); + else { + if (strncmp(ttname, "tty", 3) == 0 || + strncmp(ttname, "cua", 3) == 0) + ttname += 3; + (void)printf("%*.*s%c", v->width-1, v->width-1, ttname, + KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-'); + } + } + else { + (void)printf("%*s ", v->width-1, " "); + } +} + +void +longtname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char *ttname; + + v = ve->var; + dev = KI_EPROC(k)->e_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) + (void)printf("%-*s", v->width, "??"); + else + (void)printf("%-*s", v->width, ttname); +} + +void +started(KINFO *k, VARENT *ve) +{ + VAR *v; + time_t then; + struct tm *tp; + static int use_ampm = -1; + char buf[100]; + + v = ve->var; + if (use_ampm < 0) + use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0'); + then = KI_PROC(k)->p_starttime.tv_sec; + tp = localtime(&then); + if (now - KI_PROC(k)->p_starttime.tv_sec < 24 * 3600) { + (void)strftime(buf, sizeof(buf), + use_ampm ? "%l:%M%p" : "%k:%M ", tp); + } else if (now - KI_PROC(k)->p_starttime.tv_sec < 7 * 86400) { + (void)strftime(buf, sizeof(buf), + use_ampm ? "%a%I%p" : "%a%H ", tp); + } else + (void)strftime(buf, sizeof(buf), "%e%b%y", tp); + (void)printf("%-*s", v->width, buf); +} + +void +lstarted(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + time_t then; + char buf[100]; + + v = ve->var; + then = KI_PROC(k)->p_starttime.tv_sec; + (void)strftime(buf, sizeof(buf) -1, "%c", localtime(&then)); + (void)printf("%-*s", v->width, buf); +} + +char *get_etime(KINFO *k) { + struct timeval tv; + gettimeofday(&tv, NULL); + long e = tv.tv_sec - KI_PROC(k)->p_starttime.tv_sec; + + char *ret; + + if (e > 100*60*60*24) { + asprintf(&ret, "%ld-%02ld:%02ld:%02ld", + e / (60*60*24), + (e / (60*60)) % 24, + (e / 60) % 60, + e % 60); + } else if (e > 60*60*24) { + asprintf(&ret, "%02ld-%02ld:%02ld:%02ld", + e / (60*60*24), + (e / (60*60)) % 24, + (e / 60) % 60, + e % 60); + } else if (e > 60*60) { + asprintf(&ret, "%02ld:%02ld:%02ld", + (e / (60*60)), + (e / 60) % 60, + e % 60); + } else { + asprintf(&ret, "%02ld:%02ld", + (e / 60), + e % 60); + } + + return ret; +} + +void p_etime(KINFO *k, VARENT *ve) { + char *str = get_etime(k); + printf("%*s", ve->var->width, str); + free(str); +} + +int s_etime(KINFO *k) { + char *str = get_etime(k); + int sz = strlen(str); + free(str); + return sz; +} + +void +wchan(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (KI_PROC(k)->p_wchan) { + if (KI_PROC(k)->p_wmesg) + (void)printf("%-*.*s", v->width, v->width, + KI_EPROC(k)->e_wmesg); + else +#if FIXME + (void)printf("%-*lx", v->width, + (long)KI_PROC(k)->p_wchan &~ KERNBASE); +#else /* FIXME */ + (void)printf("%-*lx", v->width, + (long)KI_PROC(k)->p_wchan); +#endif /* FIXME */ + } else + (void)printf("%-*s", v->width, "-"); +} + +#define pgtok(a) (((a)*getpagesize())/1024) + +void +vsize(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#if FIXME + (void)printf("%*d", v->width, + (KI_EPROC(k)->e_vm.vm_map.size/1024)); +#else /* FIXME */ + (void)printf("%*lu", v->width, + (u_long)((k)->tasks_info.virtual_size)/1024); +#endif /* FIXME */ +} + +void +p_rssize(k, ve) /* doesn't account for text */ + KINFO *k; + VARENT *ve; +{ + VAR *v; +/* FIXME LATER */ + v = ve->var; + /* (void)printf("%*ld", v->width, "-"); */ + (void)printf("%*lu", v->width, + (u_long)((k)->tasks_info.resident_size)/1024); +} + +void +cputime(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + long secs; + long psecs; /* "parts" of a second. first micro, then centi */ + char obuff[128]; + time_value_t total_time, system_time; + v = ve->var; +#if FIXME + if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) { + secs = 0; + psecs = 0; + } else { + /* + * This counts time spent handling interrupts. We could + * fix this, but it is not 100% trivial (and interrupt + * time fractions only work on the sparc anyway). XXX + */ +#if FIXME + secs = KI_PROC(k)->p_runtime / 1000000; + psecs = KI_PROC(k)->p_runtime % 1000000; +#endif /* FIXME */ + if (sumrusage) { + secs += k->ki_u.u_cru.ru_utime.tv_sec + + k->ki_u.u_cru.ru_stime.tv_sec; + psecs += k->ki_u.u_cru.ru_utime.tv_usec + + k->ki_u.u_cru.ru_stime.tv_usec; + } + /* + * round and scale to 100's + */ + psecs = (psecs + 5000) / 10000; + secs += psecs / 100; + psecs = psecs % 100; + } +#else /* FIXME */ + total_time = k->tasks_info.user_time; + system_time = k->tasks_info.system_time; + + time_value_add(&total_time, &k->times.user_time); + time_value_add(&system_time, &k->times.system_time); + time_value_add(&total_time, &system_time); + + secs = total_time.seconds; + psecs = total_time.microseconds; + /* + * round and scale to 100's + */ + psecs = (psecs + 5000) / 10000; + secs += psecs / 100; + psecs = psecs % 100; +#endif /* FIXME */ + (void)snprintf(obuff, sizeof(obuff), + "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); + (void)printf("%*s", v->width, obuff); +} + +void +putime(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + long secs; + long psecs; /* "parts" of a second. first micro, then centi */ + char obuff[128]; + time_value_t user_time; + + + v = ve->var; + if (!mflg) { + user_time = k->tasks_info.user_time; + time_value_add(&user_time, &k->times.user_time); + } else if (print_all_thread) { + user_time = k->thval[print_thread_num].tb.user_time; + } else { + user_time.seconds =0; + user_time.microseconds =0; + } + + secs = user_time.seconds; + psecs = user_time.microseconds; + /* + * round and scale to 100's + */ + psecs = (psecs + 5000) / 10000; + secs += psecs / 100; + psecs = psecs % 100; + + (void)snprintf(obuff, sizeof(obuff), + "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); + (void)printf("%*s", v->width, obuff); +} + +void +pstime(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + long secs; + long psecs; /* "parts" of a second. first micro, then centi */ + char obuff[128]; + time_value_t system_time; + + v = ve->var; + if (!mflg) { + system_time = k->tasks_info.system_time; + time_value_add(&system_time, &k->times.system_time); + } else if (print_all_thread) { + system_time = k->thval[print_thread_num].tb.system_time; + } else { + system_time.seconds =0; + system_time.microseconds =0; + } + secs = system_time.seconds; + psecs = system_time.microseconds; + /* + * round and scale to 100's + */ + psecs = (psecs + 5000) / 10000; + secs += psecs / 100; + psecs = psecs % 100; + + (void)snprintf(obuff, sizeof(obuff), + "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); + (void)printf("%*s", v->width, obuff); + +} + +int +getpcpu(k) + KINFO *k; +{ +#if FIXME + struct proc *p; + static int failure; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); + p = KI_PROC(k); +#define fxtofl(fixpt) ((double)(fixpt) / fscale) + + /* XXX - I don't like this */ + if (p->p_swtime == 0 || (p->p_flag & P_INMEM) == 0) + return (0.0); + if (rawcpu) + return (100.0 * fxtofl(p->p_pctcpu)); + return (100.0 * fxtofl(p->p_pctcpu) / + (1.0 - exp(p->p_swtime * log(fxtofl(ccpu))))); +#else + return (k->cpu_usage); +#endif /* FIXME */ +} + +#ifndef TH_USAGE_SCALE +#define TH_USAGE_SCALE 1000 +#endif /* !TH_USAGE_SCALE */ + +void +pcpu(KINFO *k, VARENT *ve) +{ + VAR *v; + int cp; + + if (!mflg) { + cp = getpcpu(k); + } else if (print_all_thread) { + cp = k->thval[print_thread_num].tb.cpu_usage; + } else { + cp = 0; + } + + v = ve->var; + (void)printf("%*.1f", v->width, ((double)cp) * 100.0 / ((double)TH_USAGE_SCALE)); +} + +double +getpmem(k) + KINFO *k; +{ + static int failure; + double fracmem; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); +#if FIXME + p = KI_PROC(k); + e = KI_EPROC(k); + if ((p->p_flag & P_INMEM) == 0) + return (0.0); + /* XXX want pmap ptpages, segtab, etc. (per architecture) */ + szptudot = UPAGES; + /* XXX don't have info about shared */ + fracmem = ((float)e->e_vm.vm_rssize + szptudot)/mempages; + return (100.0 * fracmem); +#else /* FIXME */ + fracmem = ((float)k->tasks_info.resident_size)/(double)mempages; + return (100.0 * fracmem); +#endif /* FIXME */ +} + +void +pmem(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*.1f", v->width, getpmem(k)); +} + +void +pagein(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*ld", v->width, + k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0); +} + +void +maxrss(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + /* XXX not yet */ + (void)printf("%*s", v->width, "-"); +} + +void +tsize(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + int dummy=0; + + v = ve->var; +#if 0 + (void)printf("%*ld", v->width, (long)pgtok(KI_EPROC(k)->e_vm.vm_tsize)); +#else + (void)printf("%*ld", v->width, (long)dummy); +#endif +} + +void +rtprior(k, ve) + KINFO *k; + VARENT *ve; +{ +#if FIXME + + VAR *v; + struct rtprio *prtp; + char str[8]; + unsigned prio, type; + + v = ve->var; + prtp = (struct rtprio *) ((char *)KI_PROC(k) + v->off); + prio = prtp->prio; + type = prtp->type; + switch (type) { + case RTP_PRIO_REALTIME: + snprintf(str, sizeof(str), "real:%u", prio); + break; + case RTP_PRIO_NORMAL: + strncpy(str, "normal", sizeof(str)); + break; + case RTP_PRIO_IDLE: + snprintf(str, sizeof(str), "idle:%u", prio); + break; + default: + snprintf(str, sizeof(str), "%u:%u", type, prio); + break; + } + str[sizeof(str) - 1] = '\0'; + (void)printf("%*s", v->width, str); +#endif /* FIXME */ +} + +/* + * Generic output routines. Print fields from various prototype + * structures. + */ +static void +printval(void *bp, VAR *v) +{ + static char ofmt[32] = "%"; + const char *fcp; + char *cp; + + cp = ofmt + 1; + fcp = v->fmt; + if (v->flag & LJUST) + *cp++ = '-'; + *cp++ = '*'; + while ((*cp++ = *fcp++)); + + switch (v->type) { + case CHAR: + (void)printf(ofmt, v->width, *(char *)bp); + break; + case UCHAR: + (void)printf(ofmt, v->width, *(u_char *)bp); + break; + case SHORT: + (void)printf(ofmt, v->width, *(short *)bp); + break; + case USHORT: + (void)printf(ofmt, v->width, *(u_short *)bp); + break; + case INT: + (void)printf(ofmt, v->width, *(int *)bp); + break; + case UINT: + (void)printf(ofmt, v->width, *(u_int *)bp); + break; + case LONG: + (void)printf(ofmt, v->width, *(long *)bp); + break; + case ULONG: + (void)printf(ofmt, v->width, *(u_long *)bp); + break; + case KPTR: +#if FIXME + (void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); +#else /* FIXME */ + (void)printf(ofmt, v->width, *(u_long *)bp); +#endif /* FIXME */ + break; + default: + errx(1, "unknown type %d", v->type); + } +} + +void +pvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + printval((char *)((char *)KI_PROC(k) + v->off), v); +} + +void +evar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + printval((char *)((char *)KI_EPROC(k) + v->off), v); +} + +void +uvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (k->ki_u.u_valid) + printval((char *)((char *)&k->ki_u + v->off), v); + else + (void)printf("%*s", v->width, "-"); +} + +void +rvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (k->ki_u.u_valid) + printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v); + else + (void)printf("%*s", v->width, "-"); +} + +void +wq(KINFO *k, VARENT *ve) +{ + VAR *v; + struct proc_workqueueinfo wqinfo; + int len; + int ret; + uint32_t nthreads; + + len = sizeof(wqinfo); + ret = proc_pidinfo(KI_PROC(k)->p_pid, PROC_PIDWORKQUEUEINFO, 0, &wqinfo, len); + + v = ve->var; + + if (len == ret && len == PROC_PIDWORKQUEUEINFO_SIZE) { + if (strcmp(v->name, "wql") == 0) { + char *s; + switch (wqinfo.pwq_state & (WQ_EXCEEDED_CONSTRAINED_THREAD_LIMIT | WQ_EXCEEDED_TOTAL_THREAD_LIMIT)) { + case 0: + s = "-"; + break; + case WQ_EXCEEDED_CONSTRAINED_THREAD_LIMIT: + s = "C"; + break; + case WQ_EXCEEDED_TOTAL_THREAD_LIMIT: + s = "T"; + break; + default: + s = "CT"; + break; + } + printf("%*s", v->width, s); + return; + } + if (strcmp(v->name, "wqr") == 0) + nthreads = wqinfo.pwq_runthreads; + else if (strcmp(v->name, "wqb") == 0) + nthreads = wqinfo.pwq_blockedthreads; + else + nthreads = wqinfo.pwq_nthreads; + printf("%*d", v->width, nthreads); + } else + printf("%*s", v->width, "-"); +} diff --git a/adv_cmds/ps/ps.1 b/adv_cmds/ps/ps.1 new file mode 100644 index 0000000..20eed1c --- /dev/null +++ b/adv_cmds/ps/ps.1 @@ -0,0 +1,663 @@ +.\"- +.\" Copyright (c) 1980, 1990, 1991, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ps.1 8.3 (Berkeley) 4/18/94 +.\" $FreeBSD: src/bin/ps/ps.1,v 1.86 2005/04/29 11:10:27 maxim Exp $ +.\" +.Dd March 20, 2005 +.Dt PS 1 +.Os +.Sh NAME +.Nm ps +.Nd process status +.Sh SYNOPSIS +.Nm +.Op Fl AaCcEefhjlMmrSTvwXx +.Op Fl O Ar fmt | Fl o Ar fmt +.Op Fl G Ar gid Ns Op , Ns Ar gid Ns Ar ... +.Op Fl g Ar grp Ns Op , Ns Ar grp Ns Ar ... +.Op Fl u Ar uid Ns Op , Ns Ar uid Ns Ar ... +.Op Fl p Ar pid Ns Op , Ns Ar pid Ns Ar ... +.Op Fl t Ar tty Ns Op , Ns Ar tty Ns Ar ... +.Op Fl U Ar user Ns Op , Ns Ar user Ns Ar ... +.Nm +.Op Fl L +.Sh DESCRIPTION +The +.Nm +utility +displays a header line, followed by lines containing information about +all of your +processes that have controlling terminals. +.Pp +A different set of processes can be selected for display by using any +combination of the +.Fl a , G , g , p , T , t , U , +and +.Fl u +options. +If more than one of these options are given, then +.Nm +will select all processes which are matched by at least one of the +given options. +.Pp +For the processes which have been selected for display, +.Nm +will usually display one line per process. +The +.Fl M +option may result in multiple output lines (one line per thread) for +some processes. +By default all of these output lines are sorted first by controlling +terminal, then by process ID. +The +.Fl m , r , +and +.Fl v +options will change the sort order. +If more than one sorting option was given, then the selected processes +will be sorted by the last sorting option which was specified. +.Pp +For the processes which have been selected for display, the information +to display is selected based on a set of keywords (see the +.Fl L , O , +and +.Fl o +options). +The default output format includes, for each process, the process' ID, +controlling terminal, CPU time (including both user and system time), +state, and associated command. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl A +Display information about other users' processes, +including those without controlling terminals. +.It Fl a +Display information about other users' processes as well as your own. +This will skip any processes which do not have a controlling terminal, +unless the +.Fl x +option is also specified. +.It Fl C +Change the way the CPU percentage is calculated by using a +.Dq raw +CPU calculation that ignores +.Dq resident +time (this normally has +no effect). +.It Fl c +Change the +.Dq command +column output to just contain the executable name, +rather than the full command line. +.It Fl d +Like +.Fl A , +but excludes session leaders. +.It Fl E +Display the environment as well. +This does not reflect changes in the environment after process launch. +.It Fl e +Identical to +.Fl A . +.It Fl f +Display the uid, pid, parent pid, recent CPU usage, process start time, +controlling tty, elapsed CPU usage, and the associated command. +If the +.Fl u +option is also used, display the user name rather then the numeric uid. +When +.Fl o +or +.Fl O +is used to add to the display following +.Fl f , +the command field is not truncated as severely as it is in other formats. +.It Fl G +Display information about processes +which are running with the specified real group IDs. +.It Fl g +Display information about processes with the specified +process group leaders. +.It Fl h +Repeat the information header as often as necessary +to guarantee one header per page of information. +.It Fl j +Print information associated with the following keywords: +.Cm user , pid , ppid , pgid , sess , jobc , state , tt , time , +and +.Cm command . +.It Fl L +List the set of keywords available for the +.Fl O +and +.Fl o +options. +.It Fl l +Display information associated with the following keywords: +.Cm uid , pid , ppid , flags , cpu , pri , nice , vsz=SZ , rss , +.Cm wchan , state=S , paddr=ADDR , tty , time , +and +.Cm command=CMD . +.It Fl M +Print the threads corresponding to each task. +.It Fl m +Sort by memory usage, instead of the combination of controlling +terminal and process ID. +.It Fl O +Add the information associated with the space or comma separated list +of keywords specified, after the process ID, +in the default information +display. +Keywords may be appended with an equals +.Pq Ql = +sign and a string. +This causes the printed header to use the specified string instead of +the standard header. +.It Fl o +Display information associated with the space or comma separated +list of keywords specified. +Multiple keywords may also be given in the form of more than one +.Fl o +option. +Keywords may be appended with an equals +.Pq Ql = +sign and a string. +This causes the printed header to use the specified string instead of +the standard header. +If all keywords have empty header texts, no header line is written. +.It Fl p +Display information about processes which match the specified process IDs. +.It Fl r +Sort by current CPU usage, instead of the combination of controlling +terminal and process ID. +.It Fl S +Change the way the process time is calculated by summing all exited +children to their parent process. +.It Fl T +Display information about processes attached to the device associated +with the standard input. +.It Fl t +Display information about processes attached to the specified terminal +devices. +.It Fl U +Display the processes belonging to the specified real user IDs. +.It Fl u +Display the processes belonging to the specified usernames. +.It Fl v +Display information associated with the following keywords: +.Cm pid , state , time , sl , re , pagein , vsz , rss , lim , tsiz , +.Cm %cpu , %mem , +and +.Cm command . +The +.Fl v +option implies the +.Fl m +option. +.It Fl w +Use 132 columns to display information, instead of the default which +is your window size. +If the +.Fl w +option is specified more than once, +.Nm +will use as many columns as necessary without regard for your window size. +When output is not to a terminal, an unlimited number of columns are +always used. +.It Fl X +When displaying processes matched by other options, skip any processes +which do not have a controlling terminal. +.It Fl x +When displaying processes matched by other options, include processes +which do not have a controlling terminal. +This is the opposite of the +.Fl X +option. +If both +.Fl X +and +.Fl x +are specified in the same command, then +.Nm +will use the one which was specified last. +.El +.Pp +A complete list of the available keywords is given below. +Some of these keywords are further specified as follows: +.Bl -tag -width lockname +.It Cm %cpu +The CPU utilization of the process; +this is a decaying average over up to a minute of previous (real) time. +Because the time base over which this is computed varies +(some processes may be very young), +it is possible for the sum of all +.Cm %cpu +fields to exceed 100%. +.It Cm %mem +The percentage of real memory used by this process. +.It Cm flags +The flags associated with the process as in +the include file +.In sys/proc.h : +.Bl -column P_STOPPED_SINGLE 0x4000000 +.It Dv "P_ADVLOCK" Ta No "0x00001 Process may hold a POSIX advisory lock" +.It Dv "P_CONTROLT" Ta No "0x00002 Has a controlling terminal" +.It Dv "P_LP64" Ta No "0x00004 Process is LP64" +.It Dv "P_NOCLDSTOP" Ta No "0x00008 No SIGCHLD when children stop" +.It Dv "P_PPWAIT" Ta No "0x00010 Parent is waiting for child to exec/exit" +.It Dv "P_PROFIL" Ta No "0x00020 Has started profiling" +.It Dv "P_SELECT" Ta No "0x00040 Selecting; wakeup/waiting danger" +.It Dv "P_CONTINUED" Ta No "0x00080 Process was stopped and continued" +.It Dv "P_SUGID" Ta No "0x00100 Had set id privileges since last exec" +.It Dv "P_SYSTEM" Ta No "0x00200 System proc: no sigs, stats or swapping" +.It Dv "P_TIMEOUT" Ta No "0x00400 Timing out during sleep" +.It Dv "P_TRACED" Ta No "0x00800 Debugged process being traced" +.It Dv "P_WAITED" Ta No "0x01000 Debugging process has waited for child" +.It Dv "P_WEXIT" Ta No "0x02000 Working on exiting" +.It Dv "P_EXEC" Ta No "0x04000 Process called exec" +.It Dv "P_OWEUPC" Ta No "0x08000 Owe process an addupc() call at next ast" +.It Dv "P_WAITING" Ta No "0x40000 Process has a wait() in progress" +.It Dv "P_KDEBUG" Ta No "0x80000 Kdebug tracing on for this process" +.El +.It Cm lim +The soft limit on memory used, specified via a call to +.Xr setrlimit 2 . +.It Cm lstart +The exact time the command started, using the +.Ql %c +format described in +.Xr strftime 3 . +.It Cm nice +The process scheduling increment (see +.Xr setpriority 2 ) . +.It Cm rss +the real memory (resident set) size of the process (in 1024 byte units). +.It Cm start +The time the command started. +If the command started less than 24 hours ago, the start time is +displayed using the +.Dq Li %l:ps.1p +format described in +.Xr strftime 3 . +If the command started less than 7 days ago, the start time is +displayed using the +.Dq Li %a6.15p +format. +Otherwise, the start time is displayed using the +.Dq Li %e%b%y +format. +.It Cm state +The state is given by a sequence of characters, for example, +.Dq Li RWNA . +The first character indicates the run state of the process: +.Pp +.Bl -tag -width indent -compact +.It Li I +Marks a process that is idle (sleeping for longer than about 20 seconds). +.It Li R +Marks a runnable process. +.It Li S +Marks a process that is sleeping for less than about 20 seconds. +.It Li T +Marks a stopped process. +.It Li U +Marks a process in uninterruptible wait. +.It Li Z +Marks a dead process (a +.Dq zombie ) . +.El +.Pp +Additional characters after these, if any, indicate additional state +information: +.Pp +.Bl -tag -width indent -compact +.It Li + +The process is in the foreground process group of its control terminal. +.It Li < +The process has raised CPU scheduling priority. +.It Li > +The process has specified a soft limit on memory requirements and is +currently exceeding that limit; such a process is (necessarily) not +swapped. +.It Li A +the process has asked for random page replacement +.Pf ( Dv VA_ANOM , +from +.Xr vadvise 2 , +for example, +.Xr lisp 1 +in a garbage collect). +.It Li E +The process is trying to exit. +.It Li L +The process has pages locked in core (for example, for raw +.Tn I/O ) . +.It Li N +The process has reduced CPU scheduling priority (see +.Xr setpriority 2 ) . +.It Li S +The process has asked for +.Tn FIFO +page replacement +.Pf ( Dv VA_SEQL , +from +.Xr vadvise 2 , +for example, a large image processing program using virtual memory to +sequentially address voluminous data). +.It Li s +The process is a session leader. +.It Li V +The process is suspended during a +.Xr vfork 2 . +.It Li W +The process is swapped out. +.It Li X +The process is being traced or debugged. +.El +.It Cm tt +An abbreviation for the pathname of the controlling terminal, if any. +The abbreviation consists of the three letters following +.Pa /dev/tty , +or, for the console, +.Dq Li con . +This is followed by a +.Ql - +if the process can no longer reach that +controlling terminal (i.e., it has been revoked). +.It Cm wchan +The event (an address in the system) on which a process waits. +When printed numerically, the initial part of the address is +trimmed off and the result is printed in hex, for example, 0x80324000 prints +as 324000. +.El +.Pp +When printing using the command keyword, a process that has exited and +has a parent that has not yet waited for the process (in other words, a zombie) +is listed as +.Dq Li , +and a process which is blocked while trying +to exit is listed as +.Dq Li . +If the arguments cannot be located (usually because it has not been set, as is +the case of system processes and/or kernel threads) the command name is printed +within square brackets. +The process can change the arguments shown with +.Xr setproctitle 3 . +Otherwise, +.Nm +makes an educated guess as to the file name and arguments given when the +process was created by examining memory or the swap area. +The method is inherently somewhat unreliable and in any event a process +is entitled to destroy this information. +The ucomm (accounting) keyword can, however, be depended on. +If the arguments are unavailable or do not agree with the ucomm keyword, +the value for the ucomm keyword is appended to the arguments in parentheses. +.Sh KEYWORDS +The following is a complete list of the available keywords and their +meanings. +Several of them have aliases (keywords which are synonyms). +.Pp +.Bl -tag -width ".Cm sigignore" -compact +.It Cm %cpu +percentage CPU usage (alias +.Cm pcpu ) +.It Cm %mem +percentage memory usage (alias +.Cm pmem ) +.It Cm acflag +accounting flag (alias +.Cm acflg ) +.It Cm args +command and arguments +.It Cm comm +command +.It Cm command +command and arguments +.It Cm cpu +short-term CPU usage factor (for scheduling) +.It Cm etime +elapsed running time +.It Cm flags +the process flags, in hexadecimal (alias +.Cm f ) +.It Cm gid +processes group id (alias +.Cm group ) +.It Cm inblk +total blocks read (alias +.Cm inblock ) +.It Cm jobc +job control count +.It Cm ktrace +tracing flags +.It Cm ktracep +tracing vnode +.It Cm lim +memoryuse limit +.It Cm logname +login name of user who started the session +.It Cm lstart +time started +.It Cm majflt +total page faults +.It Cm minflt +total page reclaims +.It Cm msgrcv +total messages received (reads from pipes/sockets) +.It Cm msgsnd +total messages sent (writes on pipes/sockets) +.It Cm nice +nice value (alias +.Cm ni ) +.It Cm nivcsw +total involuntary context switches +.It Cm nsigs +total signals taken (alias +.Cm nsignals ) +.It Cm nswap +total swaps in/out +.It Cm nvcsw +total voluntary context switches +.It Cm nwchan +wait channel (as an address) +.It Cm oublk +total blocks written (alias +.Cm oublock ) +.It Cm p_ru +resource usage (valid only for zombie) +.It Cm paddr +swap address +.It Cm pagein +pageins (same as majflt) +.It Cm pgid +process group number +.It Cm pid +process ID +.It Cm ppid +parent process ID +.It Cm pri +scheduling priority +.It Cm re +core residency time (in seconds; 127 = infinity) +.It Cm rgid +real group ID +.It Cm rss +resident set size +.It Cm ruid +real user ID +.It Cm ruser +user name (from ruid) +.It Cm sess +session ID +.It Cm sig +pending signals (alias +.Cm pending ) +.It Cm sigmask +blocked signals (alias +.Cm blocked ) +.It Cm sl +sleep time (in seconds; 127 = infinity) +.It Cm start +time started +.It Cm state +symbolic process state (alias +.Cm stat ) +.It Cm svgid +saved gid from a setgid executable +.It Cm svuid +saved UID from a setuid executable +.It Cm tdev +control terminal device number +.It Cm time +accumulated CPU time, user + system (alias +.Cm cputime ) +.It Cm tpgid +control terminal process group ID +.\".It Cm trss +.\"text resident set size (in Kbytes) +.It Cm tsess +control terminal session ID +.It Cm tsiz +text size (in Kbytes) +.It Cm tt +control terminal name (two letter abbreviation) +.It Cm tty +full name of control terminal +.It Cm ucomm +name to be used for accounting +.It Cm uid +effective user ID +.It Cm upr +scheduling priority on return from system call (alias +.Cm usrpri ) +.It Cm user +user name (from UID) +.It Cm utime +user CPU time (alias +.Cm putime ) +.It Cm vsz +virtual size in Kbytes (alias +.Cm vsize ) +.It Cm wchan +wait channel (as a symbolic name) +.It Cm wq +total number of workqueue threads +.It Cm wqb +number of blocked workqueue threads +.It Cm wqr +number of running workqueue threads +.It Cm wql +workqueue limit status (C = constrained thread limit, T = total thread limit) +.It Cm xstat +exit or stop status (valid only for stopped or zombie process) +.El +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm : +.Bl -tag -width ".Ev COLUMNS" +.It Ev COLUMNS +If set, specifies the user's preferred output width in column positions. +By default, +.Nm +attempts to automatically determine the terminal width. +.El +.Sh FILES +.Bl -tag -width ".Pa /boot/kernel/kernel" -compact +.It Pa /dev +special files and device names +.It Pa /var/run/dev.db +/dev name database +.It Pa /var/db/kvm_kernel.db +system namelist database +.El +.Sh LEGACY DESCRIPTION +In legacy mode, +.Nm +functions as described above, with the following differences: +.Bl -tag -width indent +.It Fl e +Display the environment as well. Same as +.Fl E . +.It Fl g +Ignored for compatibility. Takes no argument. +.It Fl l +Display information associated with the following keywords: +.Cm uid , pid , ppid , cpu , pri , nice , vsz , rss , wchan , state , +.Cm tt, time , +and +.Cm command . +.It Fl u +Display information associated with the following keywords: +.Cm user , pid , %cpu , %mem , vsz , rss , tt , state , start , time , +and +.Cm command . +The +.Fl u +option implies the +.Fl r +option. +.El +.Pp +The biggest change is in the interpretation of the +.Fl u +option, +which now displays processes belonging to the specified username(s). +Thus, "ps -aux" will fail (unless you want to know about user "x"). +As a convenience, however, "ps aux" still works as it did in Tiger. +.Pp +For more information about legacy mode, see +.Xr compat 5 . +.Sh SEE ALSO +.Xr kill 1 , +.Xr w 1 , +.Xr kvm 3 , +.Xr strftime 3 , +.Xr sysctl 8 +.Sh STANDARDS +The +.Nm +utility supports the +.St -susv3 +standard. +.Sh HISTORY +The +.Nm +command appeared in +.At v4 . +.Sh BUGS +Since +.Nm +cannot run faster than the system and is run as any other scheduled +process, the information it displays can never be exact. +.Pp +The +.Nm +utility does not correctly display argument lists containing multibyte +characters. diff --git a/adv_cmds/ps/ps.c b/adv_cmds/ps/ps.c new file mode 100644 index 0000000..72c0242 --- /dev/null +++ b/adv_cmds/ps/ps.c @@ -0,0 +1,1373 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ------+---------+---------+-------- + --------+---------+---------+---------* + * Copyright (c) 2004 - Garance Alistair Drosehn . + * All rights reserved. + * + * Significant modifications made to bring `ps' options somewhat closer + * to the standard for `ps' as described in SingleUnixSpec-v3. + * ------+---------+---------+-------- + --------+---------+---------+---------* + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1990, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)ps.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/bin/ps/ps.c,v 1.110 2005/02/09 17:37:38 ru Exp $"); + +#include +#ifdef __APPLE__ +#include +#endif /* __APPLE__ */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifndef __APPLE__ +#include +#endif /* !__APPLE__ */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +#ifdef __APPLE__ +#include +#else /* !__APPLE__ */ +#define COMPAT_MODE(func, mode) (1) +#endif /* __APPLE__ */ + +#define W_SEP " \t" /* "Whitespace" list separators */ +#define T_SEP "," /* "Terminate-element" list separators */ + +#ifdef LAZY_PS +#define DEF_UREAD 0 +#define OPT_LAZY_f "f" +#else +#define DEF_UREAD 1 /* Always do the more-expensive read. */ +#define OPT_LAZY_f /* I.e., the `-f' option is not added. */ +#endif + +/* + * isdigit takes an `int', but expects values in the range of unsigned char. + * This wrapper ensures that values from a 'char' end up in the correct range. + */ +#define isdigitch(Anychar) isdigit((u_char)(Anychar)) + +int cflag; /* -c */ +int eval; /* Exit value */ +time_t now; /* Current time(3) value */ +int rawcpu; /* -C */ +int sumrusage; /* -S */ +int termwidth; /* Width of the screen (0 == infinity). */ +int totwidth; /* Calculated-width of requested variables. */ + +struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist); + +#ifndef __APPLE__ +static int forceuread = DEF_UREAD; /* Do extra work to get u-area. */ +static kvm_t *kd; +#endif /* !__APPLE__ */ +static KINFO *kinfo; +static int needcomm; /* -o "command" */ +static int needenv; /* -e */ +static int needuser; /* -o "user" */ +static int optfatal; /* Fatal error parsing some list-option. */ + +static enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; + +struct listinfo; +typedef int addelem_rtn(struct listinfo *_inf, const char *_elem); + +struct listinfo { + int count; + int maxcount; + int elemsize; + addelem_rtn *addelem; + const char *lname; + union { + gid_t *gids; + pid_t *pids; + dev_t *ttys; + uid_t *uids; + void *ptr; + } l; +}; + +#ifndef __APPLE__ +static int check_procfs(void); +#endif /* !__APPLE__ */ +static int addelem_gid(struct listinfo *, const char *); +static int addelem_pid(struct listinfo *, const char *); +static int addelem_tty(struct listinfo *, const char *); +static int addelem_uid(struct listinfo *, const char *); +static void add_list(struct listinfo *, const char *); +static void dynsizevars(KINFO *); +static void *expand_list(struct listinfo *); +#ifndef __APPLE__ +static const char * + fmt(char **(*)(kvm_t *, const struct kinfo_proc *, int), + KINFO *, char *, int); +#endif /* !__APPLE__ */ +static void free_list(struct listinfo *); +static void init_list(struct listinfo *, addelem_rtn, int, const char *); +static char *kludge_oldps_options(const char *, char *, const char *, int *); +static int pscomp(const void *, const void *); +static void saveuser(KINFO *); +static void scanvars(void); +static void sizevars(void); +static void usage(int); + +/* 5842004: Fix -f option. */ +VAR *findvar(char *, int, char **); + +/* p_ == POSIX/SUSv3/UNIX2003 format */ +static char dfmt[] = "pid,tt,state,time,command"; +static char jfmt[] = "user,pid,ppid,pgid,sess,jobc,state,tt,time,command"; +static char lfmt[] = "uid,pid,ppid,cpu,pri,nice,vsz,rss,wchan,state," + "tt,time,command"; +static char o1[] = "pid"; +static char o2[] = "tt,state,time,command"; +static char ufmt[] = "user,pid,%cpu,%mem,vsz,rss,tt,state,start,time,command"; +static char vfmt[] = "pid,state,time,sl,re,pagein,vsz,rss,lim,tsiz," + "%cpu,%mem,command"; +#ifndef __APPLE__ +static char Zfmt[] = "label"; +#endif /* !__APPLE__ */ +char p_dfmt[] = "pid tty time command=CMD"; +char p_ffmt[] = "uid pid ppid cpu=C start=STIME tty time command=CMD"; +char p_uffmt[] = "user pid ppid cpu=C start=STIME tty time command=CMD"; +char p_lfmt[] = "uid pid ppid flags cpu pri nice vsz=SZ rss wchan state=S paddr=ADDR tty time command=CMD"; +char mfmt[] = "user pid tt %cpu state pri stime utime command"; + +int eflg = 0; +int mflg = 0; /* if -M option to display all mach threads */ +int print_thread_num = 0; +int print_all_thread = 0; + +#define PS_ARGS (u03 ? "aACcdeEfg:G:hjLlMmO:o:p:rSTt:U:u:vwx" : \ + "aACcdeEgG:hjLlMmO:o:p:rSTt:U:uvwx") + +int +main(int argc, char *argv[]) +{ + struct listinfo gidlist, pgrplist, pidlist; + struct listinfo ruidlist, sesslist, ttylist, uidlist; + struct kinfo_proc *kp; + KINFO *next_KINFO; + struct varent *vent; + struct winsize ws; +#ifndef __APPLE__ + const char *nlistf, *memf; +#endif /* !__APPLE__ */ + char *cols; + int all, ch, elem, flag, _fmt, i, lineno; + int nentries, nkept, nselectors; + int prtheader, showthreads, wflag, what, xkeep, xkeep_implied; +#ifndef __APPLE__ + char errbuf[_POSIX2_LINE_MAX]; +#endif /* !__APPLE__ */ + struct kinfo_proc *kprocbuf; + int j; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; + size_t bufSize = 0; + size_t orig_bufSize = 0; + int local_error=0; + int retry_count = 0; + int u03 = COMPAT_MODE("bin/ps", "unix2003"); +#ifdef __APPLE__ + int dflag = 0; +#endif /* __APPLE__ */ + + (void) setlocale(LC_ALL, ""); + time(&now); /* Used by routines in print.c. */ + + if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') + termwidth = atoi(cols); + else if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && + ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && + ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) == -1) || + ws.ws_col == 0) + termwidth = 79; + else + termwidth = ws.ws_col - 1; + + /* + * Hide a number of option-processing kludges in a separate routine, + * to support some historical BSD behaviors, such as `ps axu'. + */ + if (argc > 1) + argv[1] = kludge_oldps_options(PS_ARGS, argv[1], argv[2], &u03); + + all = _fmt = nselectors = optfatal = 0; + prtheader = showthreads = wflag = xkeep_implied = 0; + xkeep = -1; /* Neither -x nor -X. */ + init_list(&gidlist, addelem_gid, sizeof(gid_t), "group"); + init_list(&pgrplist, addelem_pid, sizeof(pid_t), "process group"); + init_list(&pidlist, addelem_pid, sizeof(pid_t), "process id"); + init_list(&ruidlist, addelem_uid, sizeof(uid_t), "ruser"); + init_list(&sesslist, addelem_pid, sizeof(pid_t), "session id"); + init_list(&ttylist, addelem_tty, sizeof(dev_t), "tty"); + init_list(&uidlist, addelem_uid, sizeof(uid_t), "user"); +#ifndef __APPLE__ + memf = nlistf = _PATH_DEVNULL; +#endif /* !__APPLE__ */ + while ((ch = getopt(argc, argv, PS_ARGS)) != -1) + switch ((char)ch) { +#ifdef __APPLE__ + case 'd': + dflag = 1; +#endif /* __APPLE__ */ + case 'A': + /* + * Exactly the same as `-ax'. This has been + * added for compatability with SUSv3, but for + * now it will not be described in the man page. + */ + nselectors++; + all = xkeep = 1; + break; + case 'a': + nselectors++; + all = 1; + break; + case 'C': + rawcpu = 1; + break; + case 'c': + cflag = 1; + break; + case 'e': /* XXX set ufmt */ + if (u03) { + nselectors++; + all = xkeep = 1; + break; + } + case 'E': + needenv = 1; + eflg = 1; + break; +#ifdef LAZY_PS + case 'f': + if (getuid() == 0 || getgid() == 0) + forceuread = 1; + break; +#endif + case 'f': + termwidth = UNLIMITED; /* 4990408 */ + if (u03 && uidlist.count == 0) { + parsefmt(p_ffmt, 0); + /* This is a unplesent little trick that makes + ./ps -f -p PID -o pid,comm,args + print out the whole command even if they slap + more fields on after it and gobble up too much + space */ + VAR *v = findvar("command", 0, NULL); + if (v) { + v->width = 64; + } + } else { + parsefmt(p_uffmt, 0); + } + _fmt = 1; + break; + case 'G': + add_list(&gidlist, optarg); + xkeep_implied = 1; + nselectors++; + break; + case 'g': + /* The historical BSD-ish (from SunOS) behavior. */ + if (!u03) break; + + add_list(&pgrplist, optarg); + xkeep_implied = 1; + nselectors++; + break; +#ifndef __APPLE__ + case 'H': + showthreads = KERN_PROC_INC_THREAD; + break; +#endif /* !__APPLE__ */ + case 'h': + prtheader = ws.ws_row > 5 ? ws.ws_row : 22; + break; + case 'j': + parsefmt(jfmt, 0); + _fmt = 1; + jfmt[0] = '\0'; + break; + case 'L': + showkey(); + exit(0); + case 'l': + parsefmt(u03 ? p_lfmt : lfmt, 0); + _fmt = 1; + lfmt[0] = '\0'; + break; + case 'M': +#ifndef __APPLE__ + memf = optarg; +#else + parsefmt(mfmt, 0); + _fmt = 1; + mfmt[0] = '\0'; + mflg = 1; +#endif /* 0 */ + break; + case 'm': + sortby = SORTMEM; + break; +#ifndef __APPLE__ + case 'N': + nlistf = optarg; + break; +#endif /* !__APPLE__ */ + case 'O': + parsefmt(o1, 1); + parsefmt(optarg, 1); + parsefmt(o2, 1); + o1[0] = o2[0] = '\0'; + _fmt = 1; + break; + case 'o': + parsefmt(optarg, 1); + _fmt = 1; + break; + case 'p': + add_list(&pidlist, optarg); + /* + * Note: `-p' does not *set* xkeep, but any values + * from pidlist are checked before xkeep is. That + * way they are always matched, even if the user + * specifies `-X'. + */ + nselectors++; + break; + case 'r': + sortby = SORTCPU; + break; + case 'S': + sumrusage = 1; + break; + case 'T': + if ((optarg = ttyname(STDIN_FILENO)) == NULL) + errx(1, "stdin: not a terminal"); + /* FALLTHROUGH */ + case 't': + add_list(&ttylist, optarg); + xkeep_implied = 1; + nselectors++; + break; + case 'U': + add_list(&ruidlist, optarg); + xkeep_implied = 1; + nselectors++; + break; + case 'u': + if (u03) { + /* This is what SUSv3 defines as the `-u' option. */ + add_list(&uidlist, optarg); + xkeep_implied = 1; + nselectors++; + break; + } + parsefmt(ufmt, 0); + sortby = SORTCPU; + _fmt = 1; + ufmt[0] = '\0'; + break; + case 'v': + parsefmt(vfmt, 0); + sortby = SORTMEM; + _fmt = 1; + vfmt[0] = '\0'; + break; + case 'w': + if (wflag) + termwidth = UNLIMITED; + else if (termwidth < 131) + termwidth = 131; + wflag++; + break; + case 'X': + /* + * Note that `-X' and `-x' are not standard "selector" + * options. For most selector-options, we check *all* + * processes to see if any are matched by the given + * value(s). After we have a set of all the matched + * processes, then `-X' and `-x' govern whether we + * modify that *matched* set for processes which do + * not have a controlling terminal. `-X' causes + * those processes to be deleted from the matched + * set, while `-x' causes them to be kept. + */ + xkeep = 0; + break; + case 'x': + xkeep = 1; + break; + case '?': + default: + usage(u03); + } + argc -= optind; + argv += optind; + +#ifdef __APPLE__ + /* 3862041 */ + if (!isatty(STDOUT_FILENO)) + termwidth = UNLIMITED; +#endif /* __APPLE__ */ + + /* + * If the user specified ps -e then they want a copy of the process + * environment kvm_getenvv(3) attempts to open /proc//mem. + * Check to make sure that procfs is mounted on /proc, otherwise + * print a warning informing the user that output will be incomplete. + */ +#ifndef __APPLE__ + if (needenv == 1 && check_procfs() == 0) + warnx("Process environment requires procfs(5)"); +#endif /* !__APPLE__ */ + /* + * If there arguments after processing all the options, attempt + * to treat them as a list of process ids. + */ + while (*argv) { + if (!isdigitch(**argv)) + break; + add_list(&pidlist, *argv); + argv++; + } + if (*argv) { + fprintf(stderr, "%s: illegal argument: %s\n", + getprogname(), *argv); + usage(u03); + } + if (optfatal) + exit(1); /* Error messages already printed. */ + if (xkeep < 0) /* Neither -X nor -x was specified. */ + xkeep = xkeep_implied; + +#if FIXME + kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); + if (kd == 0) + errx(1, "%s", errbuf); +#endif /* FIXME */ + + if (!_fmt) { + if (u03 && uidlist.count != 0) { + parsefmt("uid", 0); + } + parsefmt(u03 ? p_dfmt : dfmt, 0); + } + + if (nselectors == 0) { + uidlist.l.ptr = malloc(sizeof(uid_t)); + if (uidlist.l.ptr == NULL) + errx(1, "malloc failed"); + nselectors = 1; + uidlist.count = uidlist.maxcount = 1; + *uidlist.l.uids = getuid(); + } + + /* + * scan requested variables, noting what structures are needed, + * and adjusting header widths as appropriate. + */ + scanvars(); + + /* + * Get process list. If the user requested just one selector- + * option, then kvm_getprocs can be asked to return just those + * processes. Otherwise, have it return all processes, and + * then this routine will search that full list and select the + * processes which match any of the user's selector-options. + */ + what = KERN_PROC_ALL; + flag = 0; + if (nselectors == 1) { + if (gidlist.count == 1) { +#if 0 + what = KERN_PROC_RGID | showthreads; + flag = *gidlist.l.gids; + nselectors = 0; +#endif /* 0 */ + } else if (pgrplist.count == 1) { + what = KERN_PROC_PGRP | showthreads; + flag = *pgrplist.l.pids; + nselectors = 0; + } else if (pidlist.count == 1) { + what = KERN_PROC_PID | showthreads; + flag = *pidlist.l.pids; + nselectors = 0; + } else if (ruidlist.count == 1) { + what = KERN_PROC_RUID | showthreads; + flag = *ruidlist.l.uids; + nselectors = 0; + } else if (sesslist.count == 1) { + what = KERN_PROC_SESSION | showthreads; + flag = *sesslist.l.pids; + nselectors = 0; + } else if (ttylist.count == 1) { + what = KERN_PROC_TTY | showthreads; + flag = *ttylist.l.ttys; + nselectors = 0; + } else if (uidlist.count == 1) { + what = (xkeep ? KERN_PROC_RUID : KERN_PROC_UID) | showthreads; + flag = *uidlist.l.uids; + nselectors = 0; + } + } + + /* + * select procs + */ + nentries = -1; +#if FIXME + kp = kvm_getprocs(kd, what, flag, &nentries); + if ((kp == NULL && nentries > 0) || (kp != NULL && nentries < 0)) + errx(1, "%s", kvm_geterr(kd)); +#else /* FIXME */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = what; + mib[3] = flag; + + if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) { + perror("Failure calling sysctl"); + return 0; + } + + kprocbuf= kp = (struct kinfo_proc *)malloc(bufSize); + + retry_count = 0; + orig_bufSize = bufSize; + for(retry_count=0; ; retry_count++) { + /* retry for transient errors due to load in the system */ + local_error = 0; + bufSize = orig_bufSize; + if ((local_error = sysctl(mib, 4, kp, &bufSize, NULL, 0)) < 0) { + if (retry_count < 1000) { + /* 1 sec back off */ + sleep(1); + continue; + } + perror("Failure calling sysctl"); + return 0; + } else if (local_error == 0) { + break; + } + /* 1 sec back off */ + sleep(1); + } + + /* This has to be after the second sysctl since the bufSize + may have changed. */ + nentries = bufSize / sizeof(struct kinfo_proc); +#endif /* FIXME */ + nkept = 0; + if (nentries > 0) { + if ((kinfo = calloc(nentries, sizeof(*kinfo))) == NULL) + errx(1, "malloc failed"); + for (i = nentries; --i >= 0; ++kp) { +#ifdef __APPLE__ + if (kp->kp_proc.p_pid == 0) { + continue; + } +#endif /* __APPLE__ */ + +#ifdef __APPLE__ + if (dflag && (kp->kp_proc.p_pid == kp->kp_eproc.e_pgid)) + continue; +#endif /* __APPLE__ */ + + /* + * If the user specified multiple selection-criteria, + * then keep any process matched by the inclusive OR + * of all the selection-criteria given. + */ + if (pidlist.count > 0) { + for (elem = 0; elem < pidlist.count; elem++) + if (kp->kp_proc.p_pid == pidlist.l.pids[elem]) + goto keepit; + } + /* + * Note that we had to process pidlist before + * filtering out processes which do not have + * a controlling terminal. + */ + if (xkeep == 0) { + if ((kp->kp_eproc.e_tdev == NODEV || + (kp->kp_proc.p_flag & P_CONTROLT) == 0)) + continue; + } + if (all || nselectors == 0) + goto keepit; + if (gidlist.count > 0) { + for (elem = 0; elem < gidlist.count; elem++) + if (kp->kp_eproc.e_pcred.p_rgid == gidlist.l.gids[elem]) + goto keepit; + } + if (pgrplist.count > 0) { + for (elem = 0; elem < pgrplist.count; elem++) + if (kp->kp_eproc.e_pgid == + pgrplist.l.pids[elem]) + goto keepit; + } + if (ruidlist.count > 0) { + for (elem = 0; elem < ruidlist.count; elem++) + if (kp->kp_eproc.e_pcred.p_ruid == + ruidlist.l.uids[elem]) + goto keepit; + } +#if 0 + if (sesslist.count > 0) { + for (elem = 0; elem < sesslist.count; elem++) + if (kp->ki_sid == sesslist.l.pids[elem]) + goto keepit; + } +#endif + if (ttylist.count > 0) { + for (elem = 0; elem < ttylist.count; elem++) + if (kp->kp_eproc.e_tdev == ttylist.l.ttys[elem]) + goto keepit; + } + if (uidlist.count > 0) { + for (elem = 0; elem < uidlist.count; elem++) + if (kp->kp_eproc.e_ucred.cr_uid == uidlist.l.uids[elem]) + goto keepit; + } + /* + * This process did not match any of the user's + * selector-options, so skip the process. + */ + continue; + + keepit: + next_KINFO = &kinfo[nkept]; + next_KINFO->ki_p = kp; + get_task_info(next_KINFO); +#ifndef __APPLE__ + next_KINFO->ki_pcpu = getpcpu(next_KINFO); + if (sortby == SORTMEM) + next_KINFO->ki_memsize = kp->ki_tsize + + kp->ki_dsize + kp->ki_ssize; +#endif /* !__APPLE__ */ + if (needuser) + saveuser(next_KINFO); + dynsizevars(next_KINFO); + nkept++; + } + } + + sizevars(); + + /* + * print header + */ + printheader(); + if (nkept == 0) + exit(1); + + /* + * sort proc list + */ + qsort(kinfo, nkept, sizeof(KINFO), pscomp); + /* + * For each process, call each variable output function. + */ + for (i = lineno = 0; i < nkept; i++) { + if(mflg) { + print_all_thread = 1; + for(j=0; j < kinfo[i].thread_count; j++) { + print_thread_num = j; + STAILQ_FOREACH(vent, &varlist, next_ve) { + (vent->var->oproc)(&kinfo[i], vent); + if (STAILQ_NEXT(vent, next_ve) != NULL) + (void)putchar(' '); + } + + (void)putchar('\n'); + if (prtheader && lineno++ == prtheader - 4) { + (void)putchar('\n'); + printheader(); + lineno = 0; + } + } + print_all_thread = 0; + } else { + STAILQ_FOREACH(vent, &varlist, next_ve) { + (vent->var->oproc)(&kinfo[i], vent); + if (STAILQ_NEXT(vent, next_ve) != NULL) + (void)putchar(' '); + } + + (void)putchar('\n'); + if (prtheader && lineno++ == prtheader - 4) { + (void)putchar('\n'); + printheader(); + lineno = 0; + } + } + } + for (i = 0; i < nkept; i++) { + if (kinfo[i].invalid_tinfo == 0 && kinfo[i].thread_count) + free(kinfo[i].thval); + } + free(kprocbuf); + free(kinfo); + free_list(&gidlist); + free_list(&pidlist); + free_list(&pgrplist); + free_list(&ruidlist); + free_list(&sesslist); + free_list(&ttylist); + free_list(&uidlist); + + exit(eval); +} + +static int +addelem_gid(struct listinfo *inf, const char *elem) +{ + struct group *grp; + const char *nameorID; + char *endp; + u_long bigtemp; + + if (*elem == '\0' || strlen(elem) >= MAXLOGNAME) { + if (*elem == '\0') + warnx("Invalid (zero-length) %s name", inf->lname); + else + warnx("%s name too long: %s", inf->lname, elem); + optfatal = 1; + return (0); /* Do not add this value. */ + } + + /* + * SUSv3 states that `ps -G grouplist' should match "real-group + * ID numbers", and does not mention group-names. I do want to + * also support group-names, so this tries for a group-id first, + * and only tries for a name if that doesn't work. This is the + * opposite order of what is done in addelem_uid(), but in + * practice the order would only matter for group-names which + * are all-numeric. + */ + grp = NULL; + nameorID = "named"; + errno = 0; + bigtemp = strtoul(elem, &endp, 10); + if (errno == 0 && *endp == '\0' && bigtemp <= GID_MAX) { + nameorID = "name or ID matches"; + grp = getgrgid((gid_t)bigtemp); + } + if (grp == NULL) + grp = getgrnam(elem); + if (grp == NULL) { + warnx("No %s %s '%s'", inf->lname, nameorID, elem); + optfatal = 1; + return (0); + } + if (inf->count >= inf->maxcount) + expand_list(inf); + inf->l.gids[(inf->count)++] = grp->gr_gid; + return (1); +} + +#define BSD_PID_MAX 99999 /* Copy of PID_MAX from sys/proc.h. */ +static int +addelem_pid(struct listinfo *inf, const char *elem) +{ + char *endp; + long tempid; + + if (*elem == '\0') { + warnx("Invalid (zero-length) process id"); + optfatal = 1; + return (0); /* Do not add this value. */ + } + + errno = 0; + tempid = strtol(elem, &endp, 10); + if (*endp != '\0' || tempid < 0 || elem == endp) { + warnx("Invalid %s: %s", inf->lname, elem); + errno = ERANGE; + } else if (errno != 0 || tempid > BSD_PID_MAX) { + warnx("%s too large: %s", inf->lname, elem); + errno = ERANGE; + } + if (errno == ERANGE) { + optfatal = 1; + return (0); + } + if (inf->count >= inf->maxcount) + expand_list(inf); + inf->l.pids[(inf->count)++] = tempid; + return (1); +} +#undef BSD_PID_MAX + +/*- + * The user can specify a device via one of three formats: + * 1) fully qualified, e.g.: /dev/ttyp0 /dev/console + * 2) missing "/dev", e.g.: ttyp0 console + * 3) two-letters, e.g.: p0 co + * (matching letters that would be seen in the "TT" column) + */ +static int +addelem_tty(struct listinfo *inf, const char *elem) +{ + const char *ttypath; + struct stat sb; + char pathbuf[PATH_MAX], pathbuf2[PATH_MAX]; + + ttypath = NULL; + pathbuf2[0] = '\0'; + switch (*elem) { + case '/': + ttypath = elem; + break; + case 'c': + if (strcmp(elem, "co") == 0) { + ttypath = _PATH_CONSOLE; + break; + } + /* FALLTHROUGH */ + default: + strlcpy(pathbuf, _PATH_DEV, sizeof(pathbuf)); + strlcat(pathbuf, elem, sizeof(pathbuf)); + ttypath = pathbuf; + if (strncmp(pathbuf, _PATH_TTY, strlen(_PATH_TTY)) == 0) + break; + if (strcmp(pathbuf, _PATH_CONSOLE) == 0) + break; + /* Check to see if /dev/tty${elem} exists */ + strlcpy(pathbuf2, _PATH_TTY, sizeof(pathbuf2)); + strlcat(pathbuf2, elem, sizeof(pathbuf2)); + if (stat(pathbuf2, &sb) == 0 && S_ISCHR(sb.st_mode)) { + /* No need to repeat stat() && S_ISCHR() checks */ + ttypath = NULL; + break; + } + break; + } + if (ttypath) { +#ifdef __APPLE__ + if (access(ttypath, F_OK) == -1 || stat(ttypath, &sb) == -1) { +#else + if (stat(ttypath, &sb) == -1) { +#endif + if (pathbuf2[0] != '\0') + warn("%s and %s", pathbuf2, ttypath); + else + warn("%s", ttypath); + optfatal = 1; + return (0); + } + if (!S_ISCHR(sb.st_mode)) { + if (pathbuf2[0] != '\0') + warnx("%s and %s: Not a terminal", pathbuf2, + ttypath); + else + warnx("%s: Not a terminal", ttypath); + optfatal = 1; + return (0); + } + } + if (inf->count >= inf->maxcount) + expand_list(inf); + inf->l.ttys[(inf->count)++] = sb.st_rdev; + return (1); +} + +static int +addelem_uid(struct listinfo *inf, const char *elem) +{ + struct passwd *pwd; + char *endp; + u_long bigtemp; + + if (*elem == '\0' || strlen(elem) >= MAXLOGNAME) { + if (*elem == '\0') + warnx("Invalid (zero-length) %s name", inf->lname); + else + warnx("%s name too long: %s", inf->lname, elem); + optfatal = 1; + return (0); /* Do not add this value. */ + } + + pwd = getpwnam(elem); + if (pwd == NULL) { + errno = 0; + bigtemp = strtoul(elem, &endp, 10); + if (errno != 0 || *endp != '\0' || bigtemp > UID_MAX) + warnx("No %s named '%s'", inf->lname, elem); + else { + /* The string is all digits, so it might be a userID. */ + pwd = getpwuid((uid_t)bigtemp); + if (pwd == NULL) + warnx("No %s name or ID matches '%s'", + inf->lname, elem); + } + } + if (pwd == NULL) { + /* + * These used to be treated as minor warnings (and the + * option was simply ignored), but now they are fatal + * errors (and the command will be aborted). + */ + optfatal = 1; + return (0); + } + if (inf->count >= inf->maxcount) + expand_list(inf); + inf->l.uids[(inf->count)++] = pwd->pw_uid; + return (1); +} + +static void +add_list(struct listinfo *inf, const char *argp) +{ + const char *savep; + char *cp, *endp; + int toolong; + char elemcopy[PATH_MAX]; + + if (*argp == 0) + inf->addelem(inf, elemcopy); + while (*argp != '\0') { + while (*argp != '\0' && strchr(W_SEP, *argp) != NULL) + argp++; + savep = argp; + toolong = 0; + cp = elemcopy; + if (strchr(T_SEP, *argp) == NULL) { + endp = elemcopy + sizeof(elemcopy) - 1; + while (*argp != '\0' && cp <= endp && + strchr(W_SEP T_SEP, *argp) == NULL) + *cp++ = *argp++; + if (cp > endp) + toolong = 1; + } + if (!toolong) { + *cp = '\0'; + /* + * Add this single element to the given list. + */ + inf->addelem(inf, elemcopy); + } else { + /* + * The string is too long to copy. Find the end + * of the string to print out the warning message. + */ + while (*argp != '\0' && strchr(W_SEP T_SEP, + *argp) == NULL) + argp++; + warnx("Value too long: %.*s", (int)(argp - savep), + savep); + optfatal = 1; + } + /* + * Skip over any number of trailing whitespace characters, + * but only one (at most) trailing element-terminating + * character. + */ + while (*argp != '\0' && strchr(W_SEP, *argp) != NULL) + argp++; + if (*argp != '\0' && strchr(T_SEP, *argp) != NULL) { + argp++; +#if 0 + /* Catch case where string ended with a comma. */ + if (*argp == '\0') + inf->addelem(inf, argp); +#endif /* 0 */ + } + } +} + +static void * +expand_list(struct listinfo *inf) +{ + void *newlist; + int newmax; + + newmax = (inf->maxcount + 1) << 1; + newlist = realloc(inf->l.ptr, newmax * inf->elemsize); + if (newlist == NULL) { + free(inf->l.ptr); + errx(1, "realloc to %d %ss failed", newmax, inf->lname); + } + inf->maxcount = newmax; + inf->l.ptr = newlist; + + return (newlist); +} + +static void +free_list(struct listinfo *inf) +{ + + inf->count = inf->elemsize = inf->maxcount = 0; + if (inf->l.ptr != NULL) + free(inf->l.ptr); + inf->addelem = NULL; + inf->lname = NULL; + inf->l.ptr = NULL; +} + +static void +init_list(struct listinfo *inf, addelem_rtn artn, int elemsize, + const char *lname) +{ + + inf->count = inf->maxcount = 0; + inf->elemsize = elemsize; + inf->addelem = artn; + inf->lname = lname; + inf->l.ptr = NULL; +} + +VARENT * +find_varentry(VAR *v) +{ + struct varent *vent; + + STAILQ_FOREACH(vent, &varlist, next_ve) { + if (strcmp(vent->var->name, v->name) == 0) + return vent; + } + return NULL; +} + +static void +scanvars(void) +{ + struct varent *vent; + VAR *v; + + STAILQ_FOREACH(vent, &varlist, next_ve) { + v = vent->var; + if (v->flag & DSIZ) { + v->dwidth = v->width; + v->width = 0; + } + if (v->flag & USER) + needuser = 1; + if (v->flag & COMM) + needcomm = 1; + } +} + +static void +dynsizevars(KINFO *ki) +{ + struct varent *vent; + VAR *v; + int i; + + STAILQ_FOREACH(vent, &varlist, next_ve) { + v = vent->var; + if (!(v->flag & DSIZ)) + continue; + i = (v->sproc)( ki); + if (v->width < i) + v->width = i; + if (v->width > v->dwidth) + v->width = v->dwidth; + } +} + +static void +sizevars(void) +{ + struct varent *vent; + VAR *v; + int i; + + STAILQ_FOREACH(vent, &varlist, next_ve) { + v = vent->var; + i = strlen(vent->header); + if (v->width < i) + v->width = i; + totwidth += v->width + 1; /* +1 for space */ + } + totwidth--; +} + +#ifndef __APPLE__ +static const char * +fmt(char **(*fn)(kvm_t *, const struct kinfo_proc *, int), KINFO *ki, + char *comm, int maxlen) +{ + const char *s; + + s = fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm, maxlen); + return (s); +} +#endif /* !__APPLE__ */ + +#define UREADOK(ki) (forceuread || (KI_PROC(ki)->p_flag & P_INMEM)) + +static void +saveuser(KINFO *ki) +{ + struct usave *usp; +#if FIXME + struct user *u_addr = (struct user *)USRSTACK; +#endif /* FIXME */ + + usp = &ki->ki_u; +#if FIXME + if (UREADOK(ki) && kvm_uread(kd, KI_PROC(ki), (unsigned long)&u_addr->u_stats, + (char *)&pstats, sizeof(pstats)) == sizeof(pstats)) + { + /* + * The u-area might be swapped out, and we can't get + * at it because we have a crashdump and no swap. + * If it's here fill in these fields, otherwise, just + * leave them 0. + */ + usp->u_start = pstats.p_start; + usp->u_ru = pstats.p_ru; + usp->u_cru = pstats.p_cru; + usp->u_valid = 1; + } else + usp->u_valid = 0; +#else /* FIXME */ + usp->u_valid = 0; +#endif /* FIXME */ + /* + * save arguments if needed + */ +#if FIXME + if (needcomm && UREADOK(ki)) { + ki->ki_args = fmt(kvm_getargv, ki, KI_PROC(ki)->p_comm, + MAXCOMLEN); + } else if (needcomm) { + ki->ki_args = malloc(strlen(KI_PROC(ki)->p_comm) + 3); + sprintf(ki->ki_args, "(%s)", KI_PROC(ki)->p_comm); + } else { + ki->ki_args = NULL; + } +#else /* FIXME */ + ki->ki_args = malloc(strlen(KI_PROC(ki)->p_comm) + 3); + sprintf(ki->ki_args, "%s", KI_PROC(ki)->p_comm); + //ki->ki_args = malloc(10); + //strcpy(ki->ki_args, "()"); +#endif /* FIXME */ +#if FIXME + if (needenv && UREADOK(ki)) { + ki->ki_env = fmt(kvm_getenvv, ki, (char *)NULL, 0); + } else if (needenv) { + ki->ki_env = malloc(3); + strcpy(ki->ki_env, "()"); + } else { + ki->ki_env = NULL; + } +#else /* FIXME */ + ki->ki_env = malloc(10); + strcpy(ki->ki_env, ""); +#endif /* FIXME */ +} + +static int +pscomp(const void *a, const void *b) +{ + int i; +#if FIXME +#define VSIZE(k) (KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + \ + KI_EPROC(k)->e_vm.vm_tsize) +#else /* FIXME */ +#define VSIZE(k) ((k)->tasks_info.resident_size) + +#endif /* FIXME */ + + if (sortby == SORTCPU) + return (getpcpu((KINFO *)b) - getpcpu((KINFO *)a)); + if (sortby == SORTMEM) + return (VSIZE((KINFO *)b) - VSIZE((KINFO *)a)); + i = KI_EPROC((KINFO *)a)->e_tdev - KI_EPROC((KINFO *)b)->e_tdev; + if (i == 0) + i = KI_PROC((KINFO *)a)->p_pid - KI_PROC((KINFO *)b)->p_pid; + return (i); +} + +/* + * ICK (all for getopt), would rather hide the ugliness + * here than taint the main code. + * + * ps foo -> ps -foo + * ps 34 -> ps -p34 + * + * The old convention that 't' with no trailing tty arg means the users + * tty, is only supported if argv[1] doesn't begin with a '-'. This same + * feature is available with the option 'T', which takes no argument. + */ +static char * +kludge_oldps_options(const char *optlist, char *origval, const char *nextarg, int *u03) +{ + size_t len; + char *argp, *cp, *newopts, *ns, *optp, *pidp; + + /* + * See if the original value includes any option which takes an + * argument (and will thus use up the remainder of the string). + */ + argp = NULL; + if (optlist != NULL) { + for (cp = origval; *cp != '\0'; cp++) { + optp = strchr(optlist, *cp); + if ((optp != NULL) && *(optp + 1) == ':') { + argp = cp; + break; + } + } + } + if (argp != NULL && *origval == '-') + return (origval); + + /* + * if last letter is a 't' flag with no argument (in the context + * of the oldps options -- option string NOT starting with a '-' -- + * then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)). + * + * However, if a flag accepting a string argument is found earlier + * in the option string (including a possible `t' flag), then the + * remainder of the string must be the argument to that flag; so + * do not modify that argument. Note that a trailing `t' would + * cause argp to be set, if argp was not already set by some + * earlier option. + */ + len = strlen(origval); + cp = origval + len - 1; + pidp = NULL; + if (*cp == 't' && *origval != '-' && cp == argp) { + if (nextarg == NULL || *nextarg == '-' || isdigitch(*nextarg)) + *cp = 'T'; + } else if (argp == NULL) { + /* + * The original value did not include any option which takes + * an argument (and that would include `p' and `t'), so check + * the value for trailing number, or comma-separated list of + * numbers, which we will treat as a pid request. + */ + if (isdigitch(*cp)) { + while (cp >= origval && (*cp == ',' || isdigitch(*cp))) + --cp; + pidp = cp + 1; + } + } + + /* + * If nothing needs to be added to the string, then return + * the "original" (although possibly modified) value. + */ + if (*origval == '-' && pidp == NULL) + return (origval); + + /* + * Create a copy of the string to add '-' and/or 'p' to the + * original value. + */ + if ((newopts = ns = malloc(len + 3)) == NULL) + errx(1, "malloc failed"); + + if (*origval != '-') { + *ns++ = '-'; /* add option flag */ + *u03 = 0; + } + + if (pidp == NULL) + strcpy(ns, origval); + else { + /* + * Copy everything before the pid string, add the `p', + * and then copy the pid string. + */ + len = pidp - origval; + memcpy(ns, origval, len); + ns += len; + *ns++ = 'p'; + strcpy(ns, pidp); + } + + return (newopts); +} + +#ifndef __APPLE__ +static int +check_procfs(void) +{ + struct statfs mnt; + + if (statfs("/proc", &mnt) < 0) + return (0); + if (strcmp(mnt.f_fstypename, "procfs") != 0) + return (0); + return (1); +} +#endif /* !__APPLE__ */ + +static void +usage(int u03) +{ +#define SINGLE_OPTS "[-AaCcEefhjlMmrSTvwXx]" + + (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", + "usage: ps " SINGLE_OPTS " [-O fmt | -o fmt] [-G gid[,gid...]]", + (u03 ? " [-g grp[,grp...]] [-u [uid,uid...]]" : " [-u]"), + " [-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]", + " ps [-L]"); + exit(1); +} diff --git a/adv_cmds/ps/ps.h b/adv_cmds/ps/ps.h new file mode 100644 index 0000000..a077eff --- /dev/null +++ b/adv_cmds/ps/ps.h @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)ps.h 8.1 (Berkeley) 5/31/93 + * $FreeBSD: ps.h,v 1.6 1998/09/14 08:32:20 dfr Exp $ + */ + +#include + +#include +#include +#include +#include +#include + +#define UNLIMITED 0 /* unlimited terminal width */ +enum type { CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG, KPTR, PGTOK }; + +struct usave { + struct timeval u_start; + struct rusage u_ru; + struct rusage u_cru; + char u_acflag; + char u_valid; +}; + +#define KI_PROC(ki) (&(ki)->ki_p->kp_proc) +#define KI_EPROC(ki) (&(ki)->ki_p->kp_eproc) + +typedef struct thread_values { + struct thread_basic_info tb; + /* struct policy_infos schedinfo; */ + union { + struct policy_timeshare_info tshare; + struct policy_rr_info rr; + struct policy_fifo_info fifo; + } schedinfo; +} thread_values_t; + +typedef struct kinfo { + struct kinfo_proc *ki_p; /* kinfo_proc structure */ + struct usave ki_u; /* interesting parts of user */ + char *ki_args; /* exec args */ + char *ki_env; /* environment */ + task_port_t task; + int state; + int cpu_usage; + int curpri; + int basepri; + int swapped; + struct task_basic_info tasks_info; + struct task_thread_times_info times; + /* struct policy_infos schedinfo; */ + union { + struct policy_timeshare_info tshare; + struct policy_rr_info rr; + struct policy_fifo_info fifo; + } schedinfo; + int invalid_tinfo; + unsigned int thread_count; + thread_port_array_t thread_list; + thread_values_t *thval; + int invalid_thinfo; +} KINFO; + +/* Variables. */ +typedef struct varent { + STAILQ_ENTRY(varent) next_ve; + const char *header; + struct var *var; +} VARENT; + +typedef struct var { + const char *name; /* name(s) of variable */ + const char *header; /* default header */ + const char *alias; /* aliases */ +#define COMM 0x01 /* needs exec arguments and environment (XXX) */ +#define LJUST 0x02 /* left adjust on output (trailing blanks) */ +#define USER 0x04 /* needs user structure */ +#define DSIZ 0x08 /* field size is dynamic*/ +#define INF127 0x10 /* values >127 displayed as 127 */ + u_int flag; + /* output routine */ + void (*oproc)(struct kinfo *, struct varent *); + /* sizing routine*/ + int (*sproc)(struct kinfo *); + short width; /* printing width */ + /* + * The following (optional) elements are hooks for passing information + * to the generic output routine pvar (which prints simple elements + * from the well known kinfo_proc structure). + */ + size_t off; /* offset in structure */ + enum type type; /* type of element */ + const char *fmt; /* printf format */ + short dwidth; /* dynamic printing width */ + /* + * glue to link selected fields together + */ +} VAR; + +#include "extern.h" diff --git a/adv_cmds/ps/tasks.c b/adv_cmds/ps/tasks.c new file mode 100644 index 0000000..4548b56 --- /dev/null +++ b/adv_cmds/ps/tasks.c @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" +#include + +extern kern_return_t task_for_pid(task_port_t task, pid_t pid, task_port_t *target); + +#define STATE_MAX 7 + +int +mach_state_order(s, sleep_time) +int s; +long sleep_time; +{ +switch (s) { +case TH_STATE_RUNNING: return(1); +case TH_STATE_UNINTERRUPTIBLE: + return(2); + case TH_STATE_WAITING: return((sleep_time > 20) ? 4 : 3); + case TH_STATE_STOPPED: return(5); + case TH_STATE_HALTED: return(6); + default: return(7); + } +} + /*01234567 */ +char mach_state_table[] = " RUSITH?"; + + +int +thread_schedinfo( + KINFO *ki, + thread_port_t thread, + policy_t pol, + void * buf) +{ + unsigned int count; + int ret = KERN_FAILURE; + + switch (pol) { + + case POLICY_TIMESHARE: + count = POLICY_TIMESHARE_INFO_COUNT; + ret = thread_info(thread, THREAD_SCHED_TIMESHARE_INFO, + (thread_info_t)buf, &count); + if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_timeshare_info *)buf)->cur_priority))) + ki->curpri = ((struct policy_timeshare_info *)buf)->cur_priority; + break; + + case POLICY_FIFO: + count = POLICY_FIFO_INFO_COUNT; + ret = thread_info(thread, THREAD_SCHED_FIFO_INFO, + buf, &count); + if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_fifo_info *)buf)->base_priority))) + ki->curpri = ((struct policy_fifo_info *)buf)->base_priority; + break; + + case POLICY_RR: + count = POLICY_RR_INFO_COUNT; + ret = thread_info(thread, THREAD_SCHED_RR_INFO, + buf, &count); + if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_rr_info *)buf)->base_priority))) + ki->curpri = ((struct policy_rr_info *)buf)->base_priority; + break; + } + return(ret); +} + +int get_task_info (KINFO *ki) +{ + kern_return_t error; + unsigned int info_count = TASK_BASIC_INFO_COUNT; + unsigned int thread_info_count = THREAD_BASIC_INFO_COUNT; + pid_t pid; + int j, err = 0; + + ki->state = STATE_MAX; + + pid = KI_PROC(ki)->p_pid; + if (task_for_pid(mach_task_self(), pid, &ki->task) != KERN_SUCCESS) { + return(1); + } + info_count = TASK_BASIC_INFO_COUNT; + error = task_info(ki->task, TASK_BASIC_INFO, (task_info_t)&ki->tasks_info, &info_count); + if (error != KERN_SUCCESS) { + ki->invalid_tinfo=1; +#ifdef DEBUG + mach_error("Error calling task_info()", error); +#endif + return(1); + } + { + vm_region_basic_info_data_64_t b_info; + vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT; + vm_size_t size; + mach_port_t object_name; + + /* + * try to determine if this task has the split libraries + * mapped in... if so, adjust its virtual size down by + * the 2 segments that are used for split libraries + */ + info_count = VM_REGION_BASIC_INFO_COUNT_64; + error = vm_region_64(ki->task, &address, &size, VM_REGION_BASIC_INFO, + (vm_region_info_t)&b_info, &info_count, &object_name); + if (error == KERN_SUCCESS) { + if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) && + ki->tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) + ki->tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE); + } + } + info_count = TASK_THREAD_TIMES_INFO_COUNT; + error = task_info(ki->task, TASK_THREAD_TIMES_INFO, (task_info_t)&ki->times, &info_count); + if (error != KERN_SUCCESS) { + ki->invalid_tinfo=1; +#ifdef DEBUG + mach_error("Error calling task_info()", error); +#endif + return(1); + } + switch(ki->tasks_info.policy) { + case POLICY_TIMESHARE : + info_count = POLICY_TIMESHARE_INFO_COUNT; + error = task_info(ki->task, TASK_SCHED_TIMESHARE_INFO, (task_info_t)&ki->schedinfo.tshare, &info_count); + if (error != KERN_SUCCESS) { + ki->invalid_tinfo=1; +#ifdef DEBUG + mach_error("Error calling task_info()", error); +#endif + return(1); + } + + ki->curpri = ki->schedinfo.tshare.cur_priority; + ki->basepri = ki->schedinfo.tshare.base_priority; + break; + case POLICY_RR : + info_count = POLICY_RR_INFO_COUNT; + error = task_info(ki->task, TASK_SCHED_RR_INFO, (task_info_t)&ki->schedinfo.rr, &info_count); + if (error != KERN_SUCCESS) { + ki->invalid_tinfo=1; +#ifdef DEBUG + mach_error("Error calling task_info()", error); +#endif + return(1); + } + + ki->curpri = ki->schedinfo.rr.base_priority; + ki->basepri = ki->schedinfo.rr.base_priority; + break; + + case POLICY_FIFO : + info_count = POLICY_FIFO_INFO_COUNT; + error = task_info(ki->task, TASK_SCHED_FIFO_INFO, (task_info_t)&ki->schedinfo.fifo, &info_count); + if (error != KERN_SUCCESS) { + ki->invalid_tinfo=1; +#ifdef DEBUG + mach_error("Error calling task_info()", error); +#endif + return(1); + } + + ki->curpri = ki->schedinfo.fifo.base_priority; + ki->basepri = ki->schedinfo.fifo.base_priority; + break; + } + + ki->invalid_tinfo=0; + + ki->cpu_usage=0; + error = task_threads(ki->task, &ki->thread_list, &ki->thread_count); + if (error != KERN_SUCCESS) { + mach_port_deallocate(mach_task_self(),ki->task); +#ifdef DEBUG + mach_error("Call to task_threads() failed", error); +#endif + return(1); + } + err=0; + //ki->curpri = 255; + //ki->basepri = 255; + ki->swapped = 1; + ki->thval = calloc(ki->thread_count, sizeof(struct thread_values)); + for (j = 0; j < ki->thread_count; j++) { + int tstate; + thread_info_count = THREAD_BASIC_INFO_COUNT; + error = thread_info(ki->thread_list[j], THREAD_BASIC_INFO, + (thread_info_t)&ki->thval[j].tb, + &thread_info_count); + if (error != KERN_SUCCESS) { +#ifdef DEBUG + mach_error("Call to thread_info() failed", error); +#endif + err=1; + } else { + ki->cpu_usage += ki->thval[j].tb.cpu_usage; + } + error = thread_schedinfo(ki, ki->thread_list[j], + ki->thval[j].tb.policy, &ki->thval[j].schedinfo); + if (error != KERN_SUCCESS) { +#ifdef DEBUG + mach_error("Call to thread_schedinfo() failed", error); +#endif + err=1; + } + tstate = mach_state_order(ki->thval[j].tb.run_state, + ki->thval[j].tb.sleep_time); + if (tstate < ki->state) + ki->state = tstate; + if ((ki->thval[j].tb.flags & TH_FLAGS_SWAPPED ) == 0) + ki->swapped = 0; + mach_port_deallocate(mach_task_self(), + ki->thread_list[j]); + } + ki->invalid_thinfo = err; + /* Deallocate the list of threads. */ + error = vm_deallocate(mach_task_self(), + (vm_address_t)(ki->thread_list), + sizeof(*ki->thread_list) * ki->thread_count); + if (error != KERN_SUCCESS) { +#ifdef DEBUG + mach_error("Trouble freeing thread_list", error); +#endif + } + + mach_port_deallocate(mach_task_self(),ki->task); + return(0); +} diff --git a/adv_cmds/stty/cchar.c b/adv_cmds/stty/cchar.c new file mode 100644 index 0000000..da9d523 --- /dev/null +++ b/adv_cmds/stty/cchar.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)cchar.c 8.5 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/cchar.c,v 1.13 2002/06/30 05:15:04 obrien Exp $"); + +#include + +#include +#include +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +static int c_cchar(const void *, const void *); + +/* + * Special control characters. + * + * Cchars1 are the standard names, cchars2 are the old aliases. + * The first are displayed, but both are recognized on the + * command line. + */ +struct cchar cchars1[] = { + { "discard", VDISCARD, CDISCARD }, + { "dsusp", VDSUSP, CDSUSP }, + { "eof", VEOF, CEOF }, + { "eol", VEOL, CEOL }, + { "eol2", VEOL2, CEOL }, + { "erase", VERASE, CERASE }, +#ifndef __APPLE__ + { "erase2", VERASE2, CERASE2 }, +#endif + { "intr", VINTR, CINTR }, + { "kill", VKILL, CKILL }, + { "lnext", VLNEXT, CLNEXT }, + { "min", VMIN, CMIN }, + { "quit", VQUIT, CQUIT }, + { "reprint", VREPRINT, CREPRINT }, + { "start", VSTART, CSTART }, + { "status", VSTATUS, CSTATUS }, + { "stop", VSTOP, CSTOP }, + { "susp", VSUSP, CSUSP }, + { "time", VTIME, CTIME }, + { "werase", VWERASE, CWERASE }, + { NULL, 0, 0}, +}; + +struct cchar cchars2[] = { + { "brk", VEOL, CEOL }, + { "flush", VDISCARD, CDISCARD }, + { "rprnt", VREPRINT, CREPRINT }, + { NULL, 0, 0 }, +}; + +static int +c_cchar(const void *a, const void *b) +{ + + return (strcmp(((const struct cchar *)a)->name, ((const struct cchar *)b)->name)); +} + +int +csearch(char ***argvp, struct info *ip) +{ + struct cchar *cp, tmp; + long val; + char *arg, *ep, *name; + + name = **argvp; + + tmp.name = name; + if (!(cp = (struct cchar *)bsearch(&tmp, cchars1, + sizeof(cchars1)/sizeof(struct cchar) - 1, sizeof(struct cchar), + c_cchar)) && !(cp = (struct cchar *)bsearch(&tmp, cchars2, + sizeof(cchars2)/sizeof(struct cchar) - 1, sizeof(struct cchar), + c_cchar))) + return (0); + + arg = *++*argvp; + if (!arg) { + warnx("option requires an argument -- %s", name); + usage(); + } + +#define CHK(s) (*arg == s[0] && !strcmp(arg, s)) + if (CHK("undef") || CHK("")) + ip->t.c_cc[cp->sub] = _POSIX_VDISABLE; + else if (cp->sub == VMIN || cp->sub == VTIME) { + val = strtol(arg, &ep, 10); +#ifdef __APPLE__ + if (val == _POSIX_VDISABLE) { + warnx("value of %ld would disable the option -- %s", + val, name); + usage(); + } +#endif + if (val > UCHAR_MAX) { + warnx("maximum option value is %d -- %s", + UCHAR_MAX, name); + usage(); + } + if (*ep != '\0') { + warnx("option requires a numeric argument -- %s", name); + usage(); + } + ip->t.c_cc[cp->sub] = val; + } else if (arg[0] == '^') + ip->t.c_cc[cp->sub] = (arg[1] == '?') ? 0177 : + (arg[1] == '-') ? _POSIX_VDISABLE : arg[1] & 037; + else + ip->t.c_cc[cp->sub] = arg[0]; + ip->set = 1; + return (1); +} diff --git a/adv_cmds/stty/extern.h b/adv_cmds/stty/extern.h new file mode 100644 index 0000000..193142a --- /dev/null +++ b/adv_cmds/stty/extern.h @@ -0,0 +1,49 @@ +/*- + * 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. + * + * @(#)extern.h 8.1 (Berkeley) 5/31/93 + * $FreeBSD: src/bin/stty/extern.h,v 1.9 2002/02/02 06:50:56 imp Exp $ + */ + +int c_cchars(const void *, const void *); +int c_modes(const void *, const void *); +int csearch(char ***, struct info *); +void checkredirect(void); +void gprint(struct termios *, struct winsize *, int); +void gread(struct termios *, char *); +int ksearch(char ***, struct info *); +int msearch(char ***, struct info *); +void optlist(void); +void print(struct termios *, struct winsize *, int, enum FMT); +void usage(void); + +extern struct cchar cchars1[], cchars2[]; diff --git a/adv_cmds/stty/gfmt.c b/adv_cmds/stty/gfmt.c new file mode 100644 index 0000000..4e5203f --- /dev/null +++ b/adv_cmds/stty/gfmt.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)gfmt.c 8.6 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/gfmt.c,v 1.18 2002/06/30 05:15:04 obrien Exp $"); + +#include + +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +static void gerr(const char *s); + +static void +gerr(const char *s) +{ + if (s) + errx(1, "illegal gfmt1 option -- %s", s); + else + errx(1, "illegal gfmt1 option"); +} + +void +#ifndef __APPLE__ +gprint(struct termios *tp, struct winsize *wp __unused, int ldisc __unused) +#else +gprint(struct termios *tp, struct winsize *wp, int ldisc) +#endif +{ + struct cchar *cp; + + (void)printf("gfmt1:cflag=%lx:iflag=%lx:lflag=%lx:oflag=%lx:", + (u_long)tp->c_cflag, (u_long)tp->c_iflag, (u_long)tp->c_lflag, + (u_long)tp->c_oflag); + for (cp = cchars1; cp->name; ++cp) + (void)printf("%s=%x:", cp->name, tp->c_cc[cp->sub]); + (void)printf("ispeed=%lu:ospeed=%lu\n", + (u_long)cfgetispeed(tp), (u_long)cfgetospeed(tp)); +} + +void +gread(struct termios *tp, char *s) +{ + struct cchar *cp; + char *ep, *p; + long tmp; + + if ((s = strchr(s, ':')) == NULL) + gerr(NULL); + for (++s; s != NULL;) { + p = strsep(&s, ":\0"); + if (!p || !*p) + break; + if (!(ep = strchr(p, '='))) + gerr(p); + *ep++ = '\0'; + (void)sscanf(ep, "%lx", &tmp); + +#define CHK(s) (*p == s[0] && !strcmp(p, s)) + if (CHK("cflag")) { + tp->c_cflag = tmp; + continue; + } + if (CHK("iflag")) { + tp->c_iflag = tmp; + continue; + } + if (CHK("ispeed")) { + (void)sscanf(ep, "%ld", &tmp); + tp->c_ispeed = tmp; + continue; + } + if (CHK("lflag")) { + tp->c_lflag = tmp; + continue; + } + if (CHK("oflag")) { + tp->c_oflag = tmp; + continue; + } + if (CHK("ospeed")) { + (void)sscanf(ep, "%ld", &tmp); + tp->c_ospeed = tmp; + continue; + } + for (cp = cchars1; cp->name != NULL; ++cp) + if (CHK(cp->name)) { + if (cp->sub == VMIN || cp->sub == VTIME) + (void)sscanf(ep, "%ld", &tmp); + tp->c_cc[cp->sub] = tmp; + break; + } + if (cp->name == NULL) + gerr(p); + } +} diff --git a/adv_cmds/stty/key.c b/adv_cmds/stty/key.c new file mode 100644 index 0000000..b38cab8 --- /dev/null +++ b/adv_cmds/stty/key.c @@ -0,0 +1,297 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)key.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/key.c,v 1.17 2002/06/30 05:15:04 obrien Exp $"); + +#include + +#include +#include +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +__BEGIN_DECLS +static int c_key(const void *, const void *); +void f_all(struct info *); +void f_cbreak(struct info *); +void f_columns(struct info *); +void f_dec(struct info *); +void f_ek(struct info *); +void f_everything(struct info *); +void f_extproc(struct info *); +void f_ispeed(struct info *); +void f_nl(struct info *); +void f_ospeed(struct info *); +void f_raw(struct info *); +void f_rows(struct info *); +void f_sane(struct info *); +void f_size(struct info *); +void f_speed(struct info *); +void f_tty(struct info *); +__END_DECLS + +static struct key { + const char *name; /* name */ + void (*f)(struct info *); /* function */ +#define F_NEEDARG 0x01 /* needs an argument */ +#define F_OFFOK 0x02 /* can turn off */ + int flags; +} keys[] = { + { "all", f_all, 0 }, + { "cbreak", f_cbreak, F_OFFOK }, + { "cols", f_columns, F_NEEDARG }, + { "columns", f_columns, F_NEEDARG }, + { "cooked", f_sane, 0 }, + { "dec", f_dec, 0 }, + { "ek", f_ek, 0 }, + { "everything", f_everything, 0 }, + { "extproc", f_extproc, F_OFFOK }, + { "ispeed", f_ispeed, F_NEEDARG }, + { "new", f_tty, 0 }, + { "nl", f_nl, F_OFFOK }, + { "old", f_tty, 0 }, + { "ospeed", f_ospeed, F_NEEDARG }, + { "raw", f_raw, F_OFFOK }, + { "rows", f_rows, F_NEEDARG }, + { "sane", f_sane, 0 }, + { "size", f_size, 0 }, + { "speed", f_speed, 0 }, + { "tty", f_tty, 0 }, +}; + +static int +c_key(const void *a, const void *b) +{ + + return (strcmp(((const struct key *)a)->name, ((const struct key *)b)->name)); +} + +int +ksearch(char ***argvp, struct info *ip) +{ + char *name; + struct key *kp, tmp; + + name = **argvp; + if (*name == '-') { + ip->off = 1; + ++name; + } else + ip->off = 0; + + tmp.name = name; + if (!(kp = (struct key *)bsearch(&tmp, keys, + sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key))) + return (0); + if (!(kp->flags & F_OFFOK) && ip->off) { + warnx("illegal option -- -%s", name); + usage(); + } + if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) { + warnx("option requires an argument -- %s", name); + usage(); + } + kp->f(ip); + return (1); +} + +void +f_all(struct info *ip) +{ + print(&ip->t, &ip->win, ip->ldisc, BSD); +} + +void +f_cbreak(struct info *ip) +{ + + if (ip->off) + f_sane(ip); + else { + ip->t.c_iflag |= BRKINT|IXON|IMAXBEL; + ip->t.c_oflag |= OPOST; + ip->t.c_lflag |= ISIG|IEXTEN; + ip->t.c_lflag &= ~ICANON; + ip->set = 1; + } +} + +void +f_columns(struct info *ip) +{ + + ip->win.ws_col = atoi(ip->arg); + ip->wset = 1; +} + +void +f_dec(struct info *ip) +{ + + ip->t.c_cc[VERASE] = (u_char)0177; + ip->t.c_cc[VKILL] = CTRL('u'); + ip->t.c_cc[VINTR] = CTRL('c'); + ip->t.c_lflag &= ~ECHOPRT; + ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; + ip->t.c_iflag &= ~IXANY; + ip->set = 1; +} + +void +f_ek(struct info *ip) +{ + + ip->t.c_cc[VERASE] = CERASE; + ip->t.c_cc[VKILL] = CKILL; + ip->set = 1; +} + +void +f_everything(struct info *ip) +{ + + print(&ip->t, &ip->win, ip->ldisc, BSD); +} + +void +f_extproc(struct info *ip) +{ + + if (ip->off) { + int tmp = 0; + (void)ioctl(ip->fd, TIOCEXT, &tmp); + } else { + int tmp = 1; + (void)ioctl(ip->fd, TIOCEXT, &tmp); + } +} + +void +f_ispeed(struct info *ip) +{ + + cfsetispeed(&ip->t, (speed_t)atoi(ip->arg)); + ip->set = 1; +} + +void +f_nl(struct info *ip) +{ + + if (ip->off) { + ip->t.c_iflag |= ICRNL; + ip->t.c_oflag |= ONLCR; + } else { + ip->t.c_iflag &= ~ICRNL; + ip->t.c_oflag &= ~ONLCR; + } + ip->set = 1; +} + +void +f_ospeed(struct info *ip) +{ + + cfsetospeed(&ip->t, (speed_t)atoi(ip->arg)); + ip->set = 1; +} + +void +f_raw(struct info *ip) +{ + + if (ip->off) + f_sane(ip); + else { + cfmakeraw(&ip->t); + ip->t.c_cflag &= ~(CSIZE|PARENB); + ip->t.c_cflag |= CS8; + ip->set = 1; + } +} + +void +f_rows(struct info *ip) +{ + + ip->win.ws_row = atoi(ip->arg); + ip->wset = 1; +} + +void +f_sane(struct info *ip) +{ + + ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & CLOCAL); + ip->t.c_iflag = TTYDEF_IFLAG; + ip->t.c_iflag |= ICRNL; + /* preserve user-preference flags in lflag */ +#define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) + ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP); + ip->t.c_oflag = TTYDEF_OFLAG; + ip->set = 1; +} + +void +f_size(struct info *ip) +{ + + (void)printf("%d %d\n", ip->win.ws_row, ip->win.ws_col); +} + +void +f_speed(struct info *ip) +{ + + (void)printf("%lu\n", (u_long)cfgetospeed(&ip->t)); +} + +void +f_tty(struct info *ip) +{ + int tmp; + + tmp = TTYDISC; + if (ioctl(ip->fd, TIOCSETD, &tmp) < 0) + err(1, "TIOCSETD"); +} diff --git a/adv_cmds/stty/modes.c b/adv_cmds/stty/modes.c new file mode 100644 index 0000000..0313c87 --- /dev/null +++ b/adv_cmds/stty/modes.c @@ -0,0 +1,308 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/modes.c,v 1.12 2002/06/30 05:15:04 obrien Exp $"); + +#include +#include +#include +#include "stty.h" + +#ifdef __APPLE__ +#include +#else +#define COMPAT_MODE(a,b) (1) +#endif /* __APPLE__ */ + +int msearch(char ***, struct info *); + +struct modes { + const char *name; + long set; + long unset; +}; + +/* + * The code in optlist() depends on minus options following regular + * options, i.e. "foo" must immediately precede "-foo". + */ +struct modes cmodes[] = { + { "cs5", CS5, CSIZE }, + { "cs6", CS6, CSIZE }, + { "cs7", CS7, CSIZE }, + { "cs8", CS8, CSIZE }, + { "cstopb", CSTOPB, 0 }, + { "-cstopb", 0, CSTOPB }, + { "cread", CREAD, 0 }, + { "-cread", 0, CREAD }, + { "parenb", PARENB, 0 }, + { "-parenb", 0, PARENB }, + { "parodd", PARODD, 0 }, + { "-parodd", 0, PARODD }, + { "parity", PARENB | CS7, PARODD | CSIZE }, + { "-parity", CS8, PARODD | PARENB | CSIZE }, + { "evenp", PARENB | CS7, PARODD | CSIZE }, + { "-evenp", CS8, PARODD | PARENB | CSIZE }, + { "oddp", PARENB | CS7 | PARODD, CSIZE }, + { "-oddp", CS8, PARODD | PARENB | CSIZE }, + { "pass8", CS8, PARODD | PARENB | CSIZE }, + { "-pass8", PARENB | CS7, PARODD | CSIZE }, + { "hupcl", HUPCL, 0 }, + { "-hupcl", 0, HUPCL }, + { "hup", HUPCL, 0 }, + { "-hup", 0, HUPCL }, + { "clocal", CLOCAL, 0 }, + { "-clocal", 0, CLOCAL }, + { "crtscts", CRTSCTS, 0 }, + { "-crtscts", 0, CRTSCTS }, + { "ctsflow", CCTS_OFLOW, 0 }, + { "-ctsflow", 0, CCTS_OFLOW }, + { "dsrflow", CDSR_OFLOW, 0 }, + { "-dsrflow", 0, CDSR_OFLOW }, + { "dtrflow", CDTR_IFLOW, 0 }, + { "-dtrflow", 0, CDTR_IFLOW }, + { "rtsflow", CRTS_IFLOW, 0 }, + { "-rtsflow", 0, CRTS_IFLOW }, + { "mdmbuf", MDMBUF, 0 }, + { "-mdmbuf", 0, MDMBUF }, + { NULL, 0, 0 }, +}; + +struct modes imodes[] = { + { "ignbrk", IGNBRK, 0 }, + { "-ignbrk", 0, IGNBRK }, + { "brkint", BRKINT, 0 }, + { "-brkint", 0, BRKINT }, + { "ignpar", IGNPAR, 0 }, + { "-ignpar", 0, IGNPAR }, + { "parmrk", PARMRK, 0 }, + { "-parmrk", 0, PARMRK }, + { "inpck", INPCK, 0 }, + { "-inpck", 0, INPCK }, + { "istrip", ISTRIP, 0 }, + { "-istrip", 0, ISTRIP }, + { "inlcr", INLCR, 0 }, + { "-inlcr", 0, INLCR }, + { "igncr", IGNCR, 0 }, + { "-igncr", 0, IGNCR }, + { "icrnl", ICRNL, 0 }, + { "-icrnl", 0, ICRNL }, + { "ixon", IXON, 0 }, + { "-ixon", 0, IXON }, + { "flow", IXON, 0 }, + { "-flow", 0, IXON }, + { "ixoff", IXOFF, 0 }, + { "-ixoff", 0, IXOFF }, + { "tandem", IXOFF, 0 }, + { "-tandem", 0, IXOFF }, + { "ixany", IXANY, 0 }, + { "-ixany", 0, IXANY }, + { "decctlq", 0, IXANY }, + { "-decctlq", IXANY, 0 }, + { "imaxbel", IMAXBEL, 0 }, + { "-imaxbel", 0, IMAXBEL }, + { "iutf8", IUTF8, 0 }, + { "-iutf8", 0, IUTF8 }, + { NULL, 0, 0 }, +}; + +struct modes lmodes[] = { + { "echo", ECHO, 0 }, + { "-echo", 0, ECHO }, + { "echoe", ECHOE, 0 }, + { "-echoe", 0, ECHOE }, + { "crterase", ECHOE, 0 }, + { "-crterase", 0, ECHOE }, + { "crtbs", ECHOE, 0 }, /* crtbs not supported, close enough */ + { "-crtbs", 0, ECHOE }, + { "echok", ECHOK, 0 }, + { "-echok", 0, ECHOK }, + { "echoke", ECHOKE, 0 }, + { "-echoke", 0, ECHOKE }, + { "crtkill", ECHOKE, 0 }, + { "-crtkill", 0, ECHOKE }, + { "altwerase", ALTWERASE, 0 }, + { "-altwerase", 0, ALTWERASE }, + { "iexten", IEXTEN, 0 }, + { "-iexten", 0, IEXTEN }, + { "echonl", ECHONL, 0 }, + { "-echonl", 0, ECHONL }, + { "echoctl", ECHOCTL, 0 }, + { "-echoctl", 0, ECHOCTL }, + { "ctlecho", ECHOCTL, 0 }, + { "-ctlecho", 0, ECHOCTL }, + { "echoprt", ECHOPRT, 0 }, + { "-echoprt", 0, ECHOPRT }, + { "prterase", ECHOPRT, 0 }, + { "-prterase", 0, ECHOPRT }, + { "isig", ISIG, 0 }, + { "-isig", 0, ISIG }, + { "icanon", ICANON, 0 }, + { "-icanon", 0, ICANON }, + { "noflsh", NOFLSH, 0 }, + { "-noflsh", 0, NOFLSH }, + { "tostop", TOSTOP, 0 }, + { "-tostop", 0, TOSTOP }, + { "flusho", FLUSHO, 0 }, + { "-flusho", 0, FLUSHO }, + { "pendin", PENDIN, 0 }, + { "-pendin", 0, PENDIN }, + { "crt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, + { "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, + { "newcrt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, + { "-newcrt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, + { "nokerninfo", NOKERNINFO, 0 }, + { "-nokerninfo",0, NOKERNINFO }, + { "kerninfo", 0, NOKERNINFO }, + { "-kerninfo", NOKERNINFO, 0 }, + { NULL, 0, 0 }, +}; + +struct modes omodes[] = { + { "opost", OPOST, 0 }, + { "-opost", 0, OPOST }, + { "litout", 0, OPOST }, + { "-litout", OPOST, 0 }, + { "onlcr", ONLCR, 0 }, + { "-onlcr", 0, ONLCR }, +#ifndef __APPLE__ + { "ocrnl", OCRNL, 0 }, + { "-ocrnl", 0, OCRNL }, +#endif + { "tabs", 0, OXTABS }, /* "preserve" tabs */ + { "-tabs", OXTABS, 0 }, + { "oxtabs", OXTABS, 0 }, + { "-oxtabs", 0, OXTABS }, +#ifndef __APPLE__ + { "onocr", ONOCR, 0 }, + { "-onocr", 0, ONOCR }, + { "onlret", ONLRET, 0 }, + { "-onlret", 0, ONLRET }, +#endif + { NULL, 0, 0 }, +}; + +struct modes umodes[] = { /* For Unix conformance only */ + { "ocrnl", OCRNL, 0 }, + { "-ocrnl", 0, OCRNL }, + { "onocr", ONOCR, 0 }, + { "-onocr", 0, ONOCR }, + { "onlret", ONLRET, 0 }, + { "-onlret", 0, ONLRET }, + + { "ofill", OFILL, 0 }, + { "-ofill", 0, OFILL }, + + { "ofdel", OFDEL, 0 }, + { "-ofdel", 0, OFDEL }, + + { "bs0", BS0, 0 }, + { "bs1", BS1, 0 }, + + { "cr0", CR0, 0 }, + { "cr1", CR1, 0 }, + { "cr2", CR2, 0 }, + { "cr3", CR3, 0 }, + + { "ff0", FF0, 0 }, + { "ff1", FF1, 0 }, + + { "nl0", NL0, 0 }, + { "nl1", NL1, 0 }, + + { "tab0", TAB0, 0 }, + { "tab1", TAB1, 0 }, + { "tab2", TAB2, 0 }, + { "tab3", TAB3, 0 }, + + { "vt0", VT0, 0 }, + { "vt1", VT1, 0 }, + + { NULL, 0, 0 }, +}; + +#define CHK(s) (*name == s[0] && !strcmp(name, s)) + +int +msearch(char ***argvp, struct info *ip) +{ + struct modes *mp; + char *name; + + name = **argvp; + + for (mp = cmodes; mp->name; ++mp) + if (CHK(mp->name)) { + ip->t.c_cflag &= ~mp->unset; + ip->t.c_cflag |= mp->set; + ip->set = 1; + return (1); + } + for (mp = imodes; mp->name; ++mp) + if (CHK(mp->name)) { + ip->t.c_iflag &= ~mp->unset; + ip->t.c_iflag |= mp->set; + ip->set = 1; + return (1); + } + for (mp = lmodes; mp->name; ++mp) + if (CHK(mp->name)) { + ip->t.c_lflag &= ~mp->unset; + ip->t.c_lflag |= mp->set; + ip->set = 1; + return (1); + } + for (mp = omodes; mp->name; ++mp) + if (CHK(mp->name)) { + ip->t.c_oflag &= ~mp->unset; + ip->t.c_oflag |= mp->set; + ip->set = 1; + return (1); + } + if (COMPAT_MODE("bin/stty", "Unix2003")) { + for (mp = umodes; mp->name; ++mp) + if (CHK(mp->name)) { + ip->t.c_oflag &= ~mp->unset; + ip->t.c_oflag |= mp->set; + ip->set = 1; + return (1); + } + } + return (0); +} diff --git a/adv_cmds/stty/print.c b/adv_cmds/stty/print.c new file mode 100644 index 0000000..ef59bf1 --- /dev/null +++ b/adv_cmds/stty/print.c @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/print.c,v 1.18 2002/06/30 05:15:04 obrien Exp $"); + +#include + +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +#include /* XXX NTTYDISC is too well hidden */ + +static void binit(const char *); +static void bput(const char *); +static const char *ccval(struct cchar *, int); + +void +print(struct termios *tp, struct winsize *wp, int ldisc, enum FMT fmt) +{ + struct cchar *p; + long tmp; + u_char *cc; + int cnt, ispeed, ospeed; + char buf1[100], buf2[100]; + + cnt = 0; + + /* Line discipline. */ + if (ldisc != TTYDISC) { + switch(ldisc) { + case NTTYDISC: + cnt += printf("new tty disc; "); + break; +#ifdef __APPLE__ + case TABLDISC: + cnt += printf("tablet disc; "); + break; +#endif + case SLIPDISC: + cnt += printf("slip disc; "); + break; + case PPPDISC: + cnt += printf("ppp disc; "); + break; + default: + cnt += printf("#%d disc; ", ldisc); + break; + } + } + + /* Line speed. */ + ispeed = cfgetispeed(tp); + ospeed = cfgetospeed(tp); + if (ispeed != ospeed) + cnt += + printf("ispeed %d baud; ospeed %d baud;", ispeed, ospeed); + else + cnt += printf("speed %d baud;", ispeed); + if (fmt >= BSD) + cnt += printf(" %d rows; %d columns;", wp->ws_row, wp->ws_col); + if (cnt) + (void)printf("\n"); + +#define on(f) ((tmp & (f)) != 0) +#define put(n, f, d) \ + if (fmt >= BSD || on(f) != (d)) \ + bput((n) + on(f)); + + /* "local" flags */ + tmp = tp->c_lflag; + binit("lflags"); + put("-icanon", ICANON, 1); + put("-isig", ISIG, 1); + put("-iexten", IEXTEN, 1); + put("-echo", ECHO, 1); + put("-echoe", ECHOE, 0); + put("-echok", ECHOK, 0); + put("-echoke", ECHOKE, 0); + put("-echonl", ECHONL, 0); + put("-echoctl", ECHOCTL, 0); + put("-echoprt", ECHOPRT, 0); + put("-altwerase", ALTWERASE, 0); + put("-noflsh", NOFLSH, 0); + put("-tostop", TOSTOP, 0); + put("-flusho", FLUSHO, 0); + put("-pendin", PENDIN, 0); + put("-nokerninfo", NOKERNINFO, 0); + put("-extproc", EXTPROC, 0); + + /* input flags */ + tmp = tp->c_iflag; + binit("iflags"); + put("-istrip", ISTRIP, 0); + put("-icrnl", ICRNL, 1); + put("-inlcr", INLCR, 0); + put("-igncr", IGNCR, 0); + put("-ixon", IXON, 1); + put("-ixoff", IXOFF, 0); + put("-ixany", IXANY, 1); + put("-imaxbel", IMAXBEL, 1); + put("-iutf8", IUTF8, 0); + put("-ignbrk", IGNBRK, 0); + put("-brkint", BRKINT, 1); + put("-inpck", INPCK, 0); + put("-ignpar", IGNPAR, 0); + put("-parmrk", PARMRK, 0); + + /* output flags */ + tmp = tp->c_oflag; + binit("oflags"); + put("-opost", OPOST, 1); + put("-onlcr", ONLCR, 1); +#ifndef __APPLE__ + put("-ocrnl", OCRNL, 0); +#endif + put("-oxtabs", OXTABS, 1); + put("-onocr", OXTABS, 0); + put("-onlret", OXTABS, 0); + + /* control flags (hardware state) */ + tmp = tp->c_cflag; + binit("cflags"); + put("-cread", CREAD, 1); + switch(tmp&CSIZE) { + case CS5: + bput("cs5"); + break; + case CS6: + bput("cs6"); + break; + case CS7: + bput("cs7"); + break; + case CS8: + bput("cs8"); + break; + } + bput("-parenb" + on(PARENB)); + put("-parodd", PARODD, 0); + put("-hupcl", HUPCL, 1); + put("-clocal", CLOCAL, 0); + put("-cstopb", CSTOPB, 0); + switch(tmp & (CCTS_OFLOW | CRTS_IFLOW)) { + case CCTS_OFLOW: + bput("ctsflow"); + break; + case CRTS_IFLOW: + bput("rtsflow"); + break; + default: + put("-crtscts", CCTS_OFLOW | CRTS_IFLOW, 0); + break; + } + put("-dsrflow", CDSR_OFLOW, 0); + put("-dtrflow", CDTR_IFLOW, 0); + put("-mdmbuf", MDMBUF, 0); /* XXX mdmbuf == dtrflow */ + + /* special control characters */ + cc = tp->c_cc; + if (fmt == POSIX) { + binit("cchars"); + for (p = cchars1; p->name; ++p) { + (void)snprintf(buf1, sizeof(buf1), "%s = %s;", + p->name, ccval(p, cc[p->sub])); + bput(buf1); + } + binit(NULL); + } else { + binit(NULL); + for (p = cchars1, cnt = 0; p->name; ++p) { + if (fmt != BSD && cc[p->sub] == p->def) + continue; +#define WD "%-8s" + (void)snprintf(buf1 + cnt * 8, sizeof(buf1) - cnt * 8, + WD, p->name); + (void)snprintf(buf2 + cnt * 8, sizeof(buf2) - cnt * 8, + WD, ccval(p, cc[p->sub])); + if (++cnt == LINELENGTH / 8) { + cnt = 0; + (void)printf("%s\n", buf1); + (void)printf("%s\n", buf2); + } + } + if (cnt) { + (void)printf("%s\n", buf1); + (void)printf("%s\n", buf2); + } + } +} + +static int col; +static const char *label; + +static void +binit(const char *lb) +{ + + if (col) { + (void)printf("\n"); + col = 0; + } + label = lb; +} + +static void +bput(const char *s) +{ + + if (col == 0) { + col = printf("%s: %s", label, s); + return; + } + if ((col + strlen(s)) > LINELENGTH) { + (void)printf("\n\t"); + col = printf("%s", s) + 8; + return; + } + col += printf(" %s", s); +} + +static const char * +ccval(struct cchar *p, int c) +{ + static char buf[5]; + char *bp; + + if (p->sub == VMIN || p->sub == VTIME) { + (void)snprintf(buf, sizeof(buf), "%d", c); + return (buf); + } + if (c == _POSIX_VDISABLE) + return (""); + bp = buf; + if (c & 0200) { + *bp++ = 'M'; + *bp++ = '-'; + c &= 0177; + } + if (c == 0177) { + *bp++ = '^'; + *bp++ = '?'; + } + else if (c < 040) { + *bp++ = '^'; + *bp++ = c + '@'; + } + else + *bp++ = c; + *bp = '\0'; + return (buf); +} diff --git a/adv_cmds/stty/stty.1 b/adv_cmds/stty/stty.1 new file mode 100644 index 0000000..9a864b4 --- /dev/null +++ b/adv_cmds/stty/stty.1 @@ -0,0 +1,633 @@ +.\" Copyright (c) 1990, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed 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. +.\" +.\" @(#)stty.1 8.4 (Berkeley) 4/18/94 +.\" $FreeBSD: src/bin/stty/stty.1,v 1.27 2001/11/29 15:46:54 green Exp $ +.\" +.Dd April 18, 1994 +.Dt STTY 1 +.Os +.Sh NAME +.Nm stty +.Nd set the options for a terminal device interface +.Sh SYNOPSIS +.Nm +.Op Fl a | Fl e | Fl g +.Op Fl f Ar file +.Op operands +.Sh DESCRIPTION +The +.Nm +utility sets or reports on terminal +characteristics for the device that is its standard input. +If no options or operands are specified, it reports the settings of a subset +of characteristics as well as additional ones if they differ from their +default values. +Otherwise it modifies +the terminal state according to the specified arguments. +Some combinations of arguments are mutually +exclusive on some terminal types. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a +Display all the current settings for the terminal to standard output +as per +.St -p1003.2 . +.It Fl e +Display all the current settings for the terminal to standard output +in the traditional +.Bx +``all'' and ``everything'' formats. +.It Fl f +Open and use the terminal named by +.Ar file +rather than using standard input. The file is opened +using the +.Dv O_NONBLOCK +flag of +.Fn open , +making it possible to +set or display settings on a terminal that might otherwise +block on the open. +.It Fl g +Display all the current settings for the terminal to standard output +in a form that may be used as an argument to a subsequent invocation of +.Nm +to restore the current terminal state as per +.St -p1003.2 . +.El +.Pp +The following arguments are available to set the terminal +characteristics: +.Ss Control Modes: +.Pp +Control mode flags affect hardware characteristics associated with the +terminal. This corresponds to the c_cflag in the termios structure. +.Bl -tag -width Fl +.It Ar number +Set terminal baud rate to the number given, if possible. +If the baud rate is set to zero, +modem control is no longer asserted. +.It Cm clocal Pq Fl clocal +Assume a line without (with) modem control. +.It Cm cread Pq Fl cread +Enable (disable) the receiver. +.It Cm crtscts Pq Fl crtscts +Enable (disable) RTS/CTS flow control. +.It Cm cs5 cs6 cs7 cs8 +Select character size, if possible. +.It Cm cstopb Pq Fl cstopb +Use two (one) stop bits per character. +.It Cm hup Pq Fl hup +Same as +.Cm hupcl +.Pq Fl hupcl . +.It Cm hupcl Pq Fl hupcl +Stop asserting modem control +(do not stop asserting modem control) on last close. +.It Cm ispeed Ar number +Set terminal input baud rate to the number given, if possible. +If the input baud rate is set to zero, +the input baud rate is set to the value of the output baud rate. +.It Cm ospeed Ar number +Set terminal output baud rate to the number given, if possible. +If the output baud rate is set to zero, +modem control is no longer asserted. +.It Cm parenb Pq Fl parenb +Enable (disable) parity generation and detection. +.It Cm parodd Pq Fl parodd +Select odd (even) parity. +.It Cm speed Ar number +This sets both +.Cm ispeed +and +.Cm ospeed +to +.Ar number . +.El +.Ss Input Modes: +This corresponds to the c_iflag in the termios structure. +.Bl -tag -width Fl +.It Cm brkint Pq Fl brkint +Signal (do not signal) +.Dv INTR +on +break. +.It Cm icrnl Pq Fl icrnl +Map (do not map) +.Dv CR +to +.Dv NL +on input. +.It Cm ignbrk Pq Fl ignbrk +Ignore (do not ignore) break on input. +.It Cm igncr Pq Fl igncr +Ignore (do not ignore) +.Dv CR +on input. +.It Cm ignpar Pq Fl ignpar +Ignore (do not ignore) characters with parity errors. +.It Cm imaxbel Pq Fl imaxbel +The system imposes a limit of +.Dv MAX_INPUT +(currently 255) characters in the input queue. If +.Cm imaxbel +is set and the input queue limit has been reached, +subsequent input causes the system to send an ASCII BEL +character to the output queue (the terminal beeps at you). Otherwise, +if +.Cm imaxbel +is unset and the input queue is full, the next input character causes +the entire input and output queues to be discarded. +.It Cm inlcr Pq Fl inlcr +Map (do not map) +.Dv NL +to +.Dv CR +on input. +.It Cm inpck Pq Fl inpck +Enable (disable) input parity checking. +.It Cm istrip Pq Fl istrip +Strip (do not strip) input characters to seven bits. +.It Cm iutf8 Pq Fl iutf8 +Assume input characters are UTF-8 encoded. +.It Cm ixany Pq Fl ixany +Allow any character (allow only +.Dv START ) +to restart output. +.It Cm ixoff Pq Fl ixoff +Request that the system send (not send) +.Dv START/STOP +characters when the input queue is nearly empty/full. +.It Cm ixon Pq Fl ixon +Enable (disable) +.Dv START/STOP +output control. +Output from the system is stopped when the system receives +.Dv STOP +and started when the system receives +.Dv START , +or if +.Cm ixany +is set, any character restarts output. +.It Cm parmrk Pq Fl parmrk +Mark (do not mark) characters with parity errors. +.El +.Ss Output Modes: +This corresponds to the c_oflag of the termios structure. +.Bl -tag -width Fl +.It Cm bs0 bs1 +Select the style of delay for backspaces (e.g., set BSDLY to BS0). +.It Cm cr0 cr1 cr2 cr3 +Select the style of delay for carriage returns (e.g., set CRDLY to CR0). +.It Cm ff0 ff1 +Select the style of delay for form feeds (e.g., set FFDLY to FF0). +.It Cm nl0 nl1 +Select the style of delay for newlines (e.g., set NLDLY to NL0). +.It Cm ocrnl Pq Fl ocrnl +Map (do not map) carriage return to newline on output. +.It Cm ofdel Pq Fl odell +Use DELs (NULs) as fill characters. +.It Cm ofill Pq Fl ofill +Use fill characters (use timing) for delays. +.It Cm onlcr Pq Fl onlcr +Map (do not map) +.Dv NL +to +.Dv CR-NL +on output. +.It Cm onlret Pq Fl onlret +On the terminal, NL performs (does not perform) the CR function. +.It Cm onocr Pq Fl onocr +Do not (do) output CRs at column zero. +.It Cm opost Pq Fl opost +Post-process output (do not post-process output; +ignore all other output modes). +.It Cm oxtabs Pq Fl oxtabs +Expand (do not expand) tabs to spaces on output. +.It Cm tab0 tab1 tab2 tab3 +Select the style of delay for horizontal tabs (e.g., set TABDLY to TAB0). +.It Cm tabs Pq Fl tabs +Same as +.Cm tab0 +.Cm ( tab3 ) . +.It Cm vt0 vt1 +Select the style of delay for vertical tabs (e.g., set VTDLY to VT0). +.El +.Ss Local Modes: +.Pp +Local mode flags (lflags) affect various and sundry characteristics +of terminal processing. +Historically the term "local" pertained to new job control features +implemented by Jim Kulp on a +.Tn Pdp 11/70 +at +.Tn IIASA . +Later, the driver ran on the first +.Tn VAX +at Evans Hall, UC Berkeley, where the job control details +were greatly modified, +but the structure definitions and names remained essentially unchanged. +The second interpretation of the 'l' in lflag +is ``line discipline flag'', which corresponds to the +.Ar c_lflag +of the +.Ar termios +structure. +.Bl -tag -width Fl +.It Cm altwerase Pq Fl altwerase +Use (do not use) an alternate word erase algorithm when processing +.Dv WERASE +characters. +This alternate algorithm considers sequences of +alphanumeric/underscores as words. +It also skips the first preceding character in its classification +(as a convenience, since the one preceding character could have been +erased with simply an +.Dv ERASE +character.) +.It Cm echo Pq Fl echo +Echo back (do not echo back) every character typed. +.It Cm echoctl Pq Fl echoctl +If +.Cm echoctl +is set, echo control characters as ^X. +Otherwise, control characters echo as themselves. +.It Cm echoe Pq Fl echoe +The +.Dv ERASE +character shall (shall not) visually erase the last character +in the current line from the display, if possible. +.It Cm echok Pq Fl echok +Echo (do not echo) +.Dv NL +after +.Dv KILL +character. +.It Cm echoke Pq Fl echoke +The +.Dv KILL +character shall (shall +not) visually erase the +current line from the +display, if possible. +.It Cm echonl Pq Fl echonl +Echo (do not echo) +.Dv NL , +even if echo is disabled. +.It Cm echoprt Pq Fl echoprt +For printing terminals. +If set, echo erased characters backwards within ``\\'' and ``/''. +Otherwise, disable this feature. +.It Cm flusho Pq Fl flusho +Indicates output is (is not) being discarded. +.It Cm icanon Pq Fl icanon +Enable (disable) canonical input +.Pf ( Dv ERASE +and +.Dv KILL +processing). +.It Cm iexten Pq Fl iexten +Enable (disable) any implementation-defined special control characters +that are not currently controlled by +.Cm icanon , +.Cm isig , +.Cm ixoff , +or +.Cm ixon . +.It Cm isig Pq Fl isig +Enable (disable) the checking of characters +against the special control characters +.Dv INTR , QUIT , +and +.Dv SUSP . +.It Cm mdmbuf Pq Fl mdmbuf +If set, flow control output based on condition of Carrier Detect. +Otherwise, writes return an error if Carrier Detect is low +(and Carrier is not being ignored with the +.Dv CLOCAL +flag.) +.It Cm noflsh Pq Fl noflsh +Disable (enable) flush after +.Dv INTR , QUIT , +or +.Dv SUSP . +.It Cm pendin Pq Fl pendin +Indicates input is (is not) pending +after a switch from non-canonical to canonical mode +and will be re-input when a read becomes pending or more input arrives. +.It Cm tostop Pq Fl tostop +Send (do not send) +.Dv SIGTTOU +for background output. +This causes background jobs to stop if they attempt terminal output. +.El +.Ss Control Characters: +.Bl -tag -width Fl +.It Ar control-character Ar string +Set +.Ar control-character +to +.Ar string . +If string is a single character, +the control character is set to +that character. +If string is the +two character sequence "^-" or the +string "undef" the control character +is disabled (i.e. set to +.Pf { Dv _POSIX_VDISABLE Ns } . ) +.Pp +Recognized control-characters: +.Bd -ragged -offset indent +.Bl -column character Subscript +.It control- +.It character Ta Subscript Ta Description +.It _________ Ta _________ Ta _______________ +.It eof Ta Tn VEOF Ta EOF No character +.It eol Ta Tn VEOL Ta EOL No character +.It eol2 Ta Tn VEOL2 Ta EOL2 No character +.It erase Ta Tn VERASE Ta ERASE No character +.It erase2 Ta Tn VERASE2 Ta ERASE2 No character +.It werase Ta Tn VWERASE Ta WERASE No character +.It intr Ta Tn VINTR Ta INTR No character +.It kill Ta Tn VKILL Ta KILL No character +.It quit Ta Tn VQUIT Ta QUIT No character +.It susp Ta Tn VSUSP Ta SUSP No character +.It start Ta Tn VSTART Ta START No character +.It stop Ta Tn VSTOP Ta STOP No character +.It dsusp Ta Tn VDSUSP Ta DSUSP No character +.It lnext Ta Tn VLNEXT Ta LNEXT No character +.It reprint Ta Tn VREPRINT Ta REPRINT No character +.It status Ta Tn VSTATUS Ta STATUS No character +.El +.Ed +.It Cm min Ar number +.It Cm time Ar number +Set the value of min or time to number. +.Dv MIN +and +.Dv TIME +are used in Non-Canonical mode input processing (-icanon). +.El +.Ss Combination Modes: +.Pp +.Bl -tag -width Fl +.It Ar saved settings +Set the current terminal characteristics +to the saved settings produced by the +.Fl g +option. +.It Cm cols Ar number +Same as +.Cm columns . +.It Cm columns Ar number +The terminal size is recorded as having +.Ar number +columns. +.It Cm crt Pq Fl crt +Set (disable) all modes suitable for a CRT display device. +.It Cm dec +Set modes suitable for users of Digital Equipment Corporation systems +.Dv ( ERASE , +.Dv KILL , +and +.Dv INTR +characters are set to ^?, ^U, and ^C; +.Dv ixany +is disabled, and +.Dv crt +is enabled.) +.It Cm ek +Reset +.Dv ERASE , +.Dv ERASE2 , +and +.Dv KILL +characters +back to system defaults. +.It Fl evenp +Same as +.Fl oddp +and +.Fl parity . +.It Cm evenp +Enable +.Cm parenb +and +.Cm cs7 ; +disable +.Cm parodd . +.It Cm extproc Pq Fl extproc +If set, this flag indicates that some amount of terminal processing +is being performed by either the terminal hardware +or by the remote side connected to a pty. +.It Cm kerninfo Pq Fl kerninfo +Enable (disable) the system generated status line associated with +processing a +.Dv STATUS +character (usually set to ^T). The status line consists of the +system load average, the current command name, its process ID, the +event the process is waiting on (or the status of the process), the user +and system times, percent cpu, and current memory usage. +.It Cm \&nl Pq Fl \&nl +Enable (disable) +.Cm icrnl . +In addition, +.Fl nl +unsets +.Cm inlcr +and +.Cm igncr . +.It Fl oddp +Same as +.Fl evenp +and +.Fl parity . +.It Cm oddp +Enable +.Cm parenb , +.Cm cs7 , +and +.Cm parodd . +.It Fl parity +Disable +.Cm parenb ; +set +.Cm cs8 . +.It Cm parity +Same as +.Cm evenp . +.It Cm raw Pq Fl raw +If set, change the modes of the terminal +so that no input or output processing is performed. +If unset, change the modes of the terminal to some reasonable state +that performs input and output processing. +Note that since the terminal driver no longer has a single +.Dv RAW +bit, it is not possible to intuit what flags were set prior to setting +.Cm raw . +This means that unsetting +.Cm raw +may not put back all the setting that were previously in effect. +To set the terminal into a raw state and then accurately restore it, +the following shell code is recommended: +.Bd -literal +save_state=$(stty -g) +stty raw +\&... +stty "$save_state" +.Ed +.It Cm rows Ar number +The terminal size is recorded as having +.Ar number +rows. +.It Cm sane +Resets all modes to reasonable values for interactive terminal use. +.It Cm size +The size of the terminal is printed as two numbers on a single line, +first rows, then columns. +.It Cm tty +Set the line discipline to the standard terminal line discipline +.Dv TTYDISC . +.El +.Ss Compatibility Modes: +.Pp +These modes remain for compatibility with the previous version of +the +.Nm +command. +.Bl -tag -width Fl +.It Cm all +Reports all the terminal modes as with +.Cm stty Fl a , +except that the control characters are printed in a columnar format. +.It Cm brk Ar value +Same as the control character +.Cm eol . +.It Cm cbreak +If set, enables +.Cm brkint , ixon , imaxbel , opost , isig , iexten , +and +.Fl icanon . +If unset, same as +.Cm sane . +.It Cm cooked +Same as +.Cm sane . +.It Cm crtbs Pq Fl crtbs +Same as +.Cm echoe . +.It Cm crterase Pq Fl crterase +Same as +.Cm echoe . +.It Cm crtkill Pq Fl crtkill +Same as +.Cm echoke . +.It Cm ctlecho Pq Fl ctlecho +Same as +.Cm echoctl . +.It Cm decctlq Pq Fl decctlq +The converse of +.Cm ixany . +.It Cm everything +Same as +.Cm all . +.It Cm flush Ar value +Same as the control character +.Cm discard . +.It Cm litout Pq Fl litout +The converse of +.Cm opost . +.It Cm new +Same as +.Cm tty . +.It Cm newcrt Pq Fl newcrt +Same as +.Cm crt . +.It Cm old +Same as +.Cm tty . +.It Cm pass8 +The converse of +.Cm parity . +.It Cm prterase Pq Fl prterase +Same as +.Cm echoprt . +.It Cm rprnt Ar value +Same as the control character +.Cm reprint . +.It Cm tabs Pq Fl tabs +The converse of +.Cm oxtabs . +.It Cm tandem Pq Fl tandem +Same as +.Cm ixoff . +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh LEGACY DESCRIPTION +In legacy operation, the +.Cm bs[01] , +.Cm cr[0-3] , +.Cm ff[01] , +.Cm nl[01] , +.Cm tab[0-3] , +and +.Cm vt[01] +control modes are not accepted, nor are +.Cm ocrnl Pq Fl ocrnl , +.Cm ofdel Pq Fl ofdel , +.Cm ofill Pq Fl ofill , +.Cm onlret Pq Fl onlret , +and +.Cm onocr Pq Fl onocr . +.Pp +For more information about legacy mode, see +.Xr compat 5 . +.Sh SEE ALSO +.Xr termios 4 , +.Xr compat 5 +.Sh STANDARDS +The +.Nm +utility is expected to be +.St -p1003.2 +compatible. The flags +.Fl e +and +.Fl f +are +extensions to the standard. diff --git a/adv_cmds/stty/stty.c b/adv_cmds/stty/stty.c new file mode 100644 index 0000000..a7feaf0 --- /dev/null +++ b/adv_cmds/stty/stty.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 1989, 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 const copyright[] = +"@(#) Copyright (c) 1989, 1991, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)stty.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/stty.c,v 1.20 2002/06/30 05:15:04 obrien Exp $"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +int +main(int argc, char *argv[]) +{ + struct info i; + enum FMT fmt; + int ch; + + fmt = NOTSET; + i.fd = STDIN_FILENO; + + opterr = 0; + while (optind < argc && + strspn(argv[optind], "-aefg") == strlen(argv[optind]) && + (ch = getopt(argc, argv, "aef:g")) != -1) + switch(ch) { + case 'a': /* undocumented: POSIX compatibility */ + fmt = POSIX; + break; + case 'e': + fmt = BSD; + break; + case 'f': + if ((i.fd = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) + err(1, "%s", optarg); + break; + case 'g': + fmt = GFLAG; + break; + case '?': + default: + goto args; + } + +args: argc -= optind; + argv += optind; + + if (tcgetattr(i.fd, &i.t) < 0) + errx(1, "stdin isn't a terminal"); + if (ioctl(i.fd, TIOCGETD, &i.ldisc) < 0) + err(1, "TIOCGETD"); + if (ioctl(i.fd, TIOCGWINSZ, &i.win) < 0) + warn("TIOCGWINSZ"); + + checkredirect(); /* conversion aid */ + + switch(fmt) { + case NOTSET: + if (*argv) + break; + /* FALLTHROUGH */ + case BSD: + case POSIX: + print(&i.t, &i.win, i.ldisc, fmt); + break; + case GFLAG: + gprint(&i.t, &i.win, i.ldisc); + break; + } + + for (i.set = i.wset = 0; *argv; ++argv) { + if (ksearch(&argv, &i)) + continue; + + if (csearch(&argv, &i)) + continue; + + if (msearch(&argv, &i)) + continue; + + if (isdigit(**argv)) { + speed_t speed; + + speed = atoi(*argv); + cfsetospeed(&i.t, speed); + cfsetispeed(&i.t, speed); + i.set = 1; + continue; + } + + if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { + gread(&i.t, *argv + sizeof("gfmt1") - 1); + i.set = 1; + continue; + } + + warnx("illegal option -- %s", *argv); + usage(); + } + + if (i.set && tcsetattr(i.fd, 0, &i.t) < 0) + err(1, "tcsetattr"); + if (i.wset && ioctl(i.fd, TIOCSWINSZ, &i.win) < 0) + warn("TIOCSWINSZ"); + exit(0); +} + +void +usage(void) +{ + + (void)fprintf(stderr, "usage: stty [-a|-e|-g] [-f file] [options]\n"); + exit (1); +} diff --git a/adv_cmds/stty/stty.h b/adv_cmds/stty/stty.h new file mode 100644 index 0000000..91c710f --- /dev/null +++ b/adv_cmds/stty/stty.h @@ -0,0 +1,59 @@ +/*- + * 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. + * + * @(#)stty.h 8.1 (Berkeley) 5/31/93 + * $FreeBSD: src/bin/stty/stty.h,v 1.8 2001/05/18 11:04:19 kris Exp $ + */ + +#include +#include + +struct info { + int fd; /* file descriptor */ + int ldisc; /* line discipline */ + int off; /* turn off */ + int set; /* need set */ + int wset; /* need window set */ + const char *arg; /* argument */ + struct termios t; /* terminal info */ + struct winsize win; /* window info */ +}; + +struct cchar { + const char *name; + int sub; + u_char def; +}; + +enum FMT { NOTSET, GFLAG, BSD, POSIX }; + +#define LINELENGTH 72 diff --git a/adv_cmds/stty/util.c b/adv_cmds/stty/util.c new file mode 100644 index 0000000..9695365 --- /dev/null +++ b/adv_cmds/stty/util.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#if 0 +static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/bin/stty/util.c,v 1.10 2002/06/30 05:15:04 obrien Exp $"); + +#include +#include + +#include +#include +#include +#include + +#include "stty.h" +#include "extern.h" + +/* + * Gross, but since we're changing the control descriptor from 1 to 0, most + * users will be probably be doing "stty > /dev/sometty" by accident. If 1 + * and 2 are both ttys, but not the same, assume that 1 was incorrectly + * redirected. + */ +void +checkredirect(void) +{ + struct stat sb1, sb2; + + if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) && + !fstat(STDOUT_FILENO, &sb1) && !fstat(STDERR_FILENO, &sb2) && + (sb1.st_rdev != sb2.st_rdev)) +warnx("stdout appears redirected, but stdin is the control descriptor"); +} diff --git a/adv_cmds/tabs/tabs.1 b/adv_cmds/tabs/tabs.1 new file mode 100644 index 0000000..b2f8523 --- /dev/null +++ b/adv_cmds/tabs/tabs.1 @@ -0,0 +1,160 @@ +.\" Copyright (c) 2002 Tim J. Robbins. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/usr.bin/tabs/tabs.1,v 1.7 2005/01/17 07:44:29 ru Exp $ +.\" +.Dd May 20, 2002 +.Dt TABS 1 +.Os +.Sh NAME +.Nm tabs +.Nd set terminal tabs +.Sh SYNOPSIS +.Nm +.Op Fl Ar n | Fl a | a2 | c | c2 | c3 | f | p | s | u +.Op Cm +m Ns Op Ar n +.Op Fl T Ar type +.Nm +.Op Fl T Ar type +.Op Cm + Ns Op Ar n +.Ar n1 Ns Op Ns , Ns Ar n2 , Ns ... +.Sh DESCRIPTION +The +.Nm +utility displays a series of characters that clear the hardware terminal +tab settings then initialises tab stops at specified positions, and +optionally adjusts the margin. +.Pp +In the first synopsis form, the tab stops set depend on the command line +options used, and may be one of the predefined formats or at regular +intervals. +.Pp +In the second synopsis form, tab stops are set at positions +.Ar n1 , n2 , +etc. +If a position is preceded by a +.Ql + , +it is relative to the previous position set. +No more than 20 positions may be specified. +.Pp +If no tab stops are specified, the +.Dq standard +.Ux +tab width of 8 is used. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl Ar n +Set a tab stop every +.Ar n +columns. +If +.Ar n +is 0, the tab stops are cleared but no new ones are set. +.It Fl a +Assembler format (columns 1, 10, 16, 36, 72). +.It Fl a2 +Assembler format (columns 1, 10, 16, 40, 72). +.It Fl c +.Tn COBOL +normal format (columns 1, 8, 12, 16, 20, 55) +.It Fl c2 +.Tn COBOL +compact format (columns 1, 6, 10, 14, 49) +.It Fl c3 +.Tn COBOL +compact format (columns 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, +50, 54, 58, 62, 67). +.It Fl f +.Tn FORTRAN +format (columns 1, 7, 11, 15, 19, 23). +.It Fl p +.Tn PL/1 +format (columns 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, +57, 61). +.It Fl s +.Tn SNOBOL +format (columns 1, 10, 55). +.It Fl u +Assembler format (columns 1, 12, 20, 44). +.It Xo +.Cm +m Ns Op Ar n , +.Cm + Ns Op Ar n +.Xc +Set an +.Ar n +character left margin, or 10 if +.Ar n +is omitted. +.It Fl T Ar type +Output escape sequence for the terminal type +.Ar type . +.El +.Sh ENVIRONMENT +The +.Ev LANG , LC_ALL , LC_CTYPE +and +.Ev TERM +environment variables affect the execution of +.Nm +as described in +.Xr environ 7 . +.Pp +The +.Fl T +option overrides the setting of the +.Ev TERM +environment variable. +If neither +.Ev TERM +nor the +.Fl T +option are present, +.Nm +will fail. +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr expand 1 , +.Xr stty 1 , +.Xr tput 1 , +.Xr unexpand 1 , +.Xr termcap 5 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1-2001 . +.Sh HISTORY +A +.Nm +utility appeared in PWB UNIX. +This implementation was introduced in +.Fx 5.0 . +.Sh BUGS +The current +.Xr termcap 5 +database does not define the +.Ql ML +(set left soft margin) capability for any terminals. diff --git a/adv_cmds/tabs/tabs.c b/adv_cmds/tabs/tabs.c new file mode 100644 index 0000000..8130b8b --- /dev/null +++ b/adv_cmds/tabs/tabs.c @@ -0,0 +1,240 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * tabs -- set terminal tabs + * + * This utility displays a series of characters that clears the terminal + * hardware tab settings, then initialises them to specified values, + * and optionally sets a soft margin. + */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/tabs/tabs.c,v 1.3 2002/06/08 11:33:22 tjr Exp $"); + +#ifdef __APPLE__ +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum number of tab stops allowed in table. */ +#define NSTOPS 20 + +#define NELEMS(a) (sizeof(a) / sizeof(a[0])) + +/* Predefined formats, taken from IEEE Std 1003.1-2001. */ +static const struct { + const char *name; /* Format name used on cmd. line */ + long stops[NSTOPS]; /* Column positions */ +} formats[] = { + { "a", { 1, 10, 16, 36, 72 } }, + { "a2", { 1, 10, 16, 40, 72 } }, + { "c", { 1, 8, 12, 16, 20, 55 } }, + { "c2", { 1, 6, 10, 14, 49 } }, + { "c3", { 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, + 62, 67 } }, + { "f", { 1, 7, 11, 15, 19, 23 } }, + { "p", { 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, + 61 } }, + { "s", { 1, 10, 55 } }, + { "u", { 1, 12, 20, 44 } } +}; + +static void gettabs(char *, long *, long *); +static int ttywidth(void); +static void usage(void); + +int +main(int argc __unused, char *argv[]) +{ + long cols, i, inc, j, margin, nstops, stops[NSTOPS]; + const char *cr, *ct, *st, *ML; + char area[1024], *ap, *arg, *end; + + setlocale(LC_ALL, ""); + + inc = 8; + margin = 0; + nstops = -1; + while ((arg = *++argv) != NULL && (*arg == '-' || *arg == '+')) { + if (*arg == '+') { + /* +m[n] or +[n] */ + if (*++arg == 'm') + arg++; + if (*arg != '\0') { + errno = 0; + margin = strtol(arg, &end, 10); + if (errno != 0 || *end != '\0' || margin < 0) + errx(1, "%s: invalid margin width", + arg); + } else + margin = 10; + } else if (isdigit(arg[1])) { + /* -n */ + errno = 0; + inc = strtol(arg + 1, &end, 10); + if (errno != 0 || *end != '\0' || inc < 0) + errx(1, "%s: invalid increment", arg + 1); + } else if (arg[1] == 'T') { + /* -Ttype or -T type */ + if (arg[2] != '\0') + setenv("TERM", arg + 2, 1); + else { + if ((arg = *++argv) == NULL) + usage(); + setenv("TERM", arg, 1); + } + } else if (arg[1] == '-') { + arg = *++argv; + break; + } else { + /* Predefined format */ + for (i = 0; i < (int)NELEMS(formats); i++) + if (strcmp(formats[i].name, arg + 1) == 0) + break; + if (i == NELEMS(formats)) + usage(); + for (j = nstops = 0; j < NSTOPS && + formats[i].stops[j] != 0; j++) + stops[nstops++] = formats[i].stops[j]; + } + } + + if (arg != NULL) { + if (nstops != -1) + usage(); + gettabs(arg, stops, &nstops); + } + + /* Initialise terminal, get the strings we need */ + setupterm(NULL, 1, NULL); + ap = area; + if ((ct = tgetstr("ct", &ap)) == NULL) + errx(1, "terminal cannot clear tabs"); + if ((st = tgetstr("st", &ap)) == NULL) + errx(1, "terminal cannot set tabs"); + if ((cr = tgetstr("cr", &ap)) == NULL) + cr = "\r"; + ML = tgetstr("ML", &ap); + cols = ttywidth(); + + /* Clear all tabs. */ + putp(cr); + putp(ct); + + /* + * Set soft margin. + * XXX Does this actually work? + */ + if (ML != NULL) { + printf("%*s", (int)margin, ""); + putp(ML); + } else if (margin != 0) + warnx("terminal cannot set left margin"); + + /* Optionally output new tab stops. */ + if (nstops >= 0) { + printf("%*s", (int)stops[0] - 1, ""); + putp(st); + for (i = 1; i < nstops; i++) { + printf("%*s", (int)(stops[i] - stops[i - 1]), ""); + putp(st); + } + } else if (inc > 0) { + for (i = 0; i < cols / inc; i++) { + putp(st); + printf("%*s", (int)inc, ""); + } + putp(st); + } + putp(cr); + + exit(0); +} + +static void +usage(void) +{ + + fprintf(stderr, +"usage: tabs [-n|-a|-a2|-c|-c2|-c3|-f|-p|-s|-u] [+m[n]] [-T type]\n"); + fprintf(stderr, +" tabs [-T type] [+[n]] n1,[n2,...]\n"); + exit(1); +} + +static void +gettabs(char *arg, long stops[], long *nstops) +{ + char *tok, *end; + long last, stop; + + for (last = *nstops = 0, tok = strtok(arg, ","); tok != NULL; + tok = strtok(NULL, ",")) { + if (*nstops >= NSTOPS) + errx(1, "too many tab stops (limit %d)", NSTOPS); + errno = 0; + stop = strtol(tok, &end, 10); + if (errno != 0 || *end != '\0' || stop <= 0) + errx(1, "%s: invalid tab stop", tok); + if (*tok == '+') { + if (tok == arg) + errx(1, "%s: first tab may not be relative", + tok); + stop += last; + } + if (last > stop) + errx(1, "cannot go backwards"); + last = stops[(*nstops)++] = stop; + } +} + +static int +ttywidth(void) +{ + struct winsize ws; + int width; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) + width = ws.ws_col; + else if ((width = tgetnum("co")) == 0) { + width = 80; + warnx("cannot find terminal width; defaulted to %d", width); + } + + return (width); +} diff --git a/adv_cmds/tty/tty.1 b/adv_cmds/tty/tty.1 new file mode 100644 index 0000000..1fd66b8 --- /dev/null +++ b/adv_cmds/tty/tty.1 @@ -0,0 +1,87 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed 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. +.\" +.\" @(#)tty.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/tty/tty.1,v 1.9 2006/12/13 20:15:49 ru Exp $ +.\" +.Dd June 6, 1993 +.Dt TTY 1 +.Os +.Sh NAME +.Nm tty +.Nd return user's terminal name +.Sh SYNOPSIS +.Nm +.Op Fl s +.Sh DESCRIPTION +The +.Nm +utility writes the name of the terminal attached to standard input +to standard output. +The name that is written is the string returned by +.Xr ttyname 3 . +If the standard input is not a terminal, the message +.Dq Li "not a tty" +is written. +The options are as follows: +.Bl -tag -width indent +.It Fl s +Do not write the terminal name; only the exit status is affected +when this option is specified. +The +.Fl s +option is deprecated in favor of the +.Dq Li "test -t 0" +command. +.El +.Sh EXIT STATUS +The +.Nm +utility +exits 0 if the standard input is a terminal, 1 if the standard input is +not a terminal, and >1 if an error occurs. +.Sh SEE ALSO +.Xr test 1 , +.Xr ttyname 3 +.Sh STANDARDS +The +.Nm +utility is expected to be +.St -p1003.2 +compatible. +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . diff --git a/adv_cmds/tty/tty.c b/adv_cmds/tty/tty.c new file mode 100644 index 0000000..806fe4b --- /dev/null +++ b/adv_cmds/tty/tty.c @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/6/93"; +#endif +#endif /* not lint */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/tty/tty.c,v 1.9 2002/05/29 17:12:30 jmallett Exp $"); + +#include +#include +#include + +static void usage(void); + +int +main(int argc, char *argv[]) +{ + int ch, sflag; + char *t; + + sflag = 0; + while ((ch = getopt(argc, argv, "s")) != -1) + switch (ch) { + case 's': + sflag = 1; + break; + case '?': + default: + usage(); + } + + t = ttyname(0); + if (!sflag) + puts(t ? t : "not a tty"); + exit(t ? 0 : 1); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: tty [-s]\n"); + exit(2); +} diff --git a/adv_cmds/whois/whois.1 b/adv_cmds/whois/whois.1 new file mode 100644 index 0000000..0177b48 --- /dev/null +++ b/adv_cmds/whois/whois.1 @@ -0,0 +1,287 @@ +.\" 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. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (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: @(#)whois.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD$ +.\" +.Dd April 25, 2016 +.Dt WHOIS 1 +.Os +.Sh NAME +.Nm whois +.Nd "Internet domain name and network number directory service" +.Sh SYNOPSIS +.Nm +.Op Fl aAbfgiIklmPQrRS +.Op Fl c Ar TLD | Fl h Ar host +.Op Fl p Ar port +.Op Fl - +.Ar name ... +.Sh DESCRIPTION +The +.Nm +utility looks up records in the databases maintained by several +Network Information Centers +.Pq Tn NICs . +.Pp +By default +.Nm +starts by querying the Internet Assigned Numbers Authority (IANA) whois server, +and follows referrals to whois servers +that have more specific details about the query +.Ar name . +The IANA whois server knows about +IP address and AS numbers +as well as domain names. +.Pp +There are a few special cases where referrals do not work, so +.Nm +goes directly to the appropriate server. +These include point-of-contact handles for ARIN, +.Pa nic.at , +NORID, and RIPE, +and domain names under +.Pa ac.uk . +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a +Use the American Registry for Internet Numbers +.Pq Tn ARIN +database. +It contains network numbers used in those parts of the world covered neither by +.Tn APNIC , AfriNIC , LACNIC , +nor by +.Tn RIPE . +The query syntax is documented at +.Pa https://www.arin.net/resources/whoisrws/whois_api.html#nicname +.It Fl A +Use the Asia/Pacific Network Information Center +.Pq Tn APNIC +database. +It contains network numbers used in East Asia, Australia, +New Zealand, and the Pacific islands. +Get query syntax documentation using +.Ic whois -A help +.It Fl b +Use the Network Abuse Clearinghouse database. +It contains addresses to which network abuse should be reported, +indexed by domain name. +.It Fl c Ar TLD +This is the equivalent of using the +.Fl h +option with an argument of +.Qq Ar TLD Ns Li .whois-servers.net . +This can be helpful for locating country-class TLD whois servers. +.It Fl f +Use the African Network Information Centre +.Pq Tn AfriNIC +database. +It contains network numbers used in Africa and the islands of the +western Indian Ocean. +Get query syntax documentation using +.Ic whois -f help +.It Fl g +Use the US non-military federal government database, which contains points of +contact for subdomains of +.Pa .GOV . +.It Fl h Ar host +Use the specified host instead of the default. +Either a host name or an IP address may be specified. +.It Fl i +Use the traditional Network Information Center (InterNIC) +.Pq Pa whois.internic.net +database. +This now contains only registrations for domain names under +.Pa .COM , +.Pa .NET , +.Pa .EDU . +You can specify the type of object to search for like +.Ic whois -i ' Ns Ar type Ar name Ns Ic ' +where +.Ar type +can be +.Nm domain , nameserver , registrar . +The +.Ar name +can contain +.Li * +wildcards. +.It Fl I +Use the Internet Assigned Numbers Authority +.Pq Tn IANA +database. +.It Fl k +Use the National Internet Development Agency of Korea's +.Pq Tn KRNIC +database. +It contains network numbers and domain contact information +for Korea. +.It Fl l +Use the Latin American and Caribbean IP address Regional Registry +.Pq Tn LACNIC +database. +It contains network numbers used in much of Latin America and the +Caribbean. +.It Fl m +Use the Route Arbiter Database +.Pq Tn RADB +database. +It contains route policy specifications for a large +number of operators' networks. +.It Fl p Ar port +Connect to the whois server on +.Ar port . +If this option is not specified, +.Nm +defaults to port 43. +.It Fl P +Use the PeeringDB database of AS numbers. +It contains details about presence at internet peering points +for many network operators. +.It Fl Q +Do a quick lookup; +.Nm +will not attempt to follow referrals to other whois servers. +This is the default if a server is explicitly specified +using one of the other options or in an environment variable. +See also the +.Fl R +option. +.It Fl r +Use the R\(aaeseaux IP Europ\(aaeens +.Pq Tn RIPE +database. +It contains network numbers and domain contact information +for Europe. +Get query syntax documentation using +.Ic whois -r help +.It Fl R +Do a recursive lookup; +.Nm +will attempt to follow referrals to other whois servers. +This is the default if no server is explicitly specified. +See also the +.Fl Q +option. +.It Fl S +By default +.Nm +adjusts simple queries (without spaces) to produce more useful output +from certain whois servers, +and it suppresses some uninformative output. +With the +.Fl S +option, +.Nm +sends the query and prints the output verbatim. +.El +.Pp +The operands specified to +.Nm +are treated independently and may be used +as queries on different whois servers. +.Sh ENVIRONMENT +.Bl -tag -width WHOIS_SERVER +.It Ev WHOIS_SERVER +The primary default whois server. +If this is unset, +.Nm +uses the +.Ev RA_SERVER +environment variable. +.It Ev RA_SERVER +The secondary default whois server. +If this is unset, +.Nm +will use +.Pa whois.iana.org . +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +To obtain contact information about an +administrator located in the Russian +.Tn TLD +domain +.Qq Li RU , +use the +.Fl c +option as shown in the following example, where +.Ar CONTACT-ID +is substituted with the actual contact identifier. +.Pp +.Dl Ic whois -c RU CONTACT-ID +.Pp +(Note: This example is specific to the +.Tn TLD +.Qq Li RU , +but other +.Tn TLDs +can be queried by using a similar syntax.) +.Pp +The following example demonstrates how to query +a whois server using a non-standard port, where +.Dq Li query-data +is the query to be sent to +.Dq Li whois.example.com +on port +.Dq Li rwhois +(written numerically as 4321). +.Pp +.Dl Ic whois -h whois.example.com -p rwhois query-data +.Pp +Some whois servers support complex queries +with dash-letter options. +You can use the +.Fl - +option to separate +.Nm +command options from whois server query options. +A query containing spaces must be quoted as one +argument to the +.Nm +command. +The following example asks the RIPE whois server +to return a brief description of its +.Dq Li domain +object type: +.Pp +.Dl Ic whois -r -- '-t domain' +.Sh SEE ALSO +.Rs +.%A Ken Harrenstien +.%A Vic White +.%T NICNAME/WHOIS +.%D 1 March 1982 +.%O RFC 812 +.Re +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/adv_cmds/whois/whois.c b/adv_cmds/whois/whois.c new file mode 100644 index 0000000..a6c4f6c --- /dev/null +++ b/adv_cmds/whois/whois.c @@ -0,0 +1,629 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 const char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif +#ifndef INFTIM +#define INFTIM -1 +#endif +#endif + +#define ABUSEHOST "whois.abuse.net" +#define ANICHOST "whois.arin.net" +#define DENICHOST "whois.denic.de" +#define DKNICHOST "whois.dk-hostmaster.dk" +#define FNICHOST "whois.afrinic.net" +#define GNICHOST "whois.nic.gov" +#define IANAHOST "whois.iana.org" +#define INICHOST "whois.internic.net" +#define KNICHOST "whois.krnic.net" +#define LNICHOST "whois.lacnic.net" +#define MNICHOST "whois.ra.net" +#define PDBHOST "whois.peeringdb.com" +#define PNICHOST "whois.apnic.net" +#define QNICHOST_TAIL ".whois-servers.net" +#define RNICHOST "whois.ripe.net" +#define VNICHOST "whois.verisign-grs.com" + +#ifdef __APPLE__ +#define DEFAULT_PORT "nicname" +#else +#define DEFAULT_PORT "whois" +#endif + +#define WHOIS_RECURSE 0x01 +#define WHOIS_QUICK 0x02 +#define WHOIS_SPAM_ME 0x04 + +#define CHOPSPAM ">>> Last update of WHOIS database:" + +#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') + +#define SCAN(p, end, check) \ + while ((p) < (end)) \ + if (check) ++(p); \ + else break + +static struct { + const char *suffix, *server; +} whoiswhere[] = { + /* Various handles */ + { "-ARIN", ANICHOST }, + { "-NICAT", "at" QNICHOST_TAIL }, + { "-NORID", "no" QNICHOST_TAIL }, + { "-RIPE", RNICHOST }, + /* Nominet's whois server doesn't return referrals to JANET */ + { ".ac.uk", "ac.uk" QNICHOST_TAIL }, + { ".gov.uk", "ac.uk" QNICHOST_TAIL }, + { "", IANAHOST }, /* default */ + { NULL, NULL } /* safety belt */ +}; + +#define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 } +static struct { + const char *prefix; + size_t len; +} whois_referral[] = { + WHOIS_REFERRAL("whois:"), /* IANA */ + WHOIS_REFERRAL("Whois Server:"), + WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */ + WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */ + WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */ + { NULL, 0 } +}; + +/* + * We have a list of patterns for RIRs that assert ignorance rather than + * providing referrals. If that happens, we guess that ARIN will be more + * helpful. But, before following a referral to an RIR, we check if we have + * asked that RIR already, and if so we make another guess. + */ +static const char *actually_arin[] = { + "netname: ERX-NETBLOCK\n", /* APNIC */ + "netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n", + NULL +}; + +static struct { + int loop; + const char *host; +} try_rir[] = { + { 0, ANICHOST }, + { 0, RNICHOST }, + { 0, PNICHOST }, + { 0, FNICHOST }, + { 0, LNICHOST }, + { 0, NULL } +}; + +static void +reset_rir(void) { + int i; + + for (i = 0; try_rir[i].host != NULL; i++) + try_rir[i].loop = 0; +} + +static const char *port = DEFAULT_PORT; + +static const char *choose_server(char *); +static struct addrinfo *gethostinfo(char const *host, int exitnoname); +#ifdef __APPLE__ +static void s_asprintf(char **ret, const char *format, ...) __attribute__((__format__(printf, 2, 3))); +#else +static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3); +#endif +static void usage(void); +static void whois(const char *, const char *, int); + +int +main(int argc, char *argv[]) +{ + const char *country, *host; + int ch, flags; + +#ifdef SOCKS + SOCKSinit(argv[0]); +#endif + + country = host = NULL; + flags = 0; + while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) { + switch (ch) { + case 'a': + host = ANICHOST; + break; + case 'A': + host = PNICHOST; + break; + case 'b': + host = ABUSEHOST; + break; + case 'c': + country = optarg; + break; + case 'f': + host = FNICHOST; + break; + case 'g': + host = GNICHOST; + break; + case 'h': + host = optarg; + break; + case 'i': + host = INICHOST; + break; + case 'I': + host = IANAHOST; + break; + case 'k': + host = KNICHOST; + break; + case 'l': + host = LNICHOST; + break; + case 'm': + host = MNICHOST; + break; + case 'p': + port = optarg; + break; + case 'P': + host = PDBHOST; + break; + case 'Q': + flags |= WHOIS_QUICK; + break; + case 'r': + host = RNICHOST; + break; + case 'R': + flags |= WHOIS_RECURSE; + break; + case 'S': + flags |= WHOIS_SPAM_ME; + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (!argc || (country != NULL && host != NULL)) + usage(); + + /* + * If no host or country is specified, rely on referrals from IANA. + */ + if (host == NULL && country == NULL) { + if ((host = getenv("WHOIS_SERVER")) == NULL && + (host = getenv("RA_SERVER")) == NULL) { + if (!(flags & WHOIS_QUICK)) + flags |= WHOIS_RECURSE; + } + } + while (argc-- > 0) { + if (country != NULL) { + char *qnichost; + s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL); + whois(*argv, qnichost, flags); + free(qnichost); + } else + whois(*argv, host != NULL ? host : + choose_server(*argv), flags); + reset_rir(); + argv++; + } + exit(0); +} + +static const char * +choose_server(char *domain) +{ + size_t len = strlen(domain); + int i; + + for (i = 0; whoiswhere[i].suffix != NULL; i++) { + size_t suffix_len = strlen(whoiswhere[i].suffix); + if (len > suffix_len && + strcasecmp(domain + len - suffix_len, + whoiswhere[i].suffix) == 0) + return (whoiswhere[i].server); + } + errx(EX_SOFTWARE, "no default whois server"); +} + +static struct addrinfo * +gethostinfo(char const *host, int exit_on_noname) +{ + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + res = NULL; + error = getaddrinfo(host, port, &hints, &res); + if (error && (exit_on_noname || error != EAI_NONAME)) + err(EX_NOHOST, "%s: %s", host, gai_strerror(error)); + return (res); +} + +/* + * Wrapper for asprintf(3) that exits on error. + */ +static void +s_asprintf(char **ret, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (vasprintf(ret, format, ap) == -1) { + va_end(ap); + err(EX_OSERR, "vasprintf()"); + } + va_end(ap); +} + +static int +connect_to_any_host(struct addrinfo *hostres) +{ + struct addrinfo *res; + nfds_t i, j; + size_t count; + struct pollfd *fds; + int timeout = 180, s = -1; + + for (res = hostres, count = 0; res; res = res->ai_next) + count++; + fds = calloc(count, sizeof(*fds)); + if (fds == NULL) + err(EX_OSERR, "calloc()"); + + /* + * Traverse the result list elements and make non-block + * connection attempts. + */ + count = i = 0; + for (res = hostres; res != NULL; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK, + res->ai_protocol); + if (s < 0) + continue; +#ifdef __APPLE__ + int flags = fcntl(s, F_GETFL, 0); + if (flags < 0) { + close(s); + continue; + } + flags |= O_NONBLOCK; + if (fcntl(s, F_SETFL, flags) != 0) { + close(s); + continue; + } +#endif + if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + if (errno == EINPROGRESS) { + /* Add the socket to poll list */ + fds[i].fd = s; + fds[i].events = POLLERR | POLLHUP | + POLLIN | POLLOUT; + /* + * From here until a socket connects, the + * socket fd is owned by the fds[] poll array. + */ + s = -1; + count++; + i++; + } else { + close(s); + s = -1; + + /* + * Poll only if we have something to poll, + * otherwise just go ahead and try next + * address + */ + if (count == 0) + continue; + } + } else + goto done; + + /* + * If we are at the last address, poll until a connection is + * established or we failed all connection attempts. + */ + if (res->ai_next == NULL) + timeout = INFTIM; + + /* + * Poll the watched descriptors for successful connections: + * if we still have more untried resolved addresses, poll only + * once; otherwise, poll until all descriptors have errors, + * which will be considered as ETIMEDOUT later. + */ + do { + int n; + + n = poll(fds, i, timeout); + if (n == 0) { + /* + * No event reported in time. Try with a + * smaller timeout (but cap at 2-3ms) + * after a new host have been added. + */ + if (timeout >= 3) + timeout >>= 1; + + break; + } else if (n < 0) { + /* + * errno here can only be EINTR which we would + * want to clean up and bail out. + */ + s = -1; + goto done; + } + + /* + * Check for the event(s) we have seen. + */ + for (j = 0; j < i; j++) { + if (fds[j].fd == -1 || fds[j].events == 0 || + fds[j].revents == 0) + continue; + if (fds[j].revents & ~(POLLIN | POLLOUT)) { + close(fds[j].fd); + fds[j].fd = -1; + fds[j].events = 0; + count--; + continue; + } else if (fds[j].revents & (POLLIN | POLLOUT)) { + /* Connect succeeded. */ + s = fds[j].fd; + fds[j].fd = -1; + + goto done; + } + + } + } while (timeout == INFTIM && count != 0); + } + + /* All attempts were failed */ + s = -1; + if (count == 0) + errno = ETIMEDOUT; + +done: + /* Close all watched fds except the succeeded one */ + for (j = 0; j < i; j++) + if (fds[j].fd != -1) + close(fds[j].fd); + free(fds); + return (s); +} + +static void +whois(const char *query, const char *hostname, int flags) +{ + FILE *fp; + struct addrinfo *hostres; + char *buf, *host, *nhost, *p; + int comment, s, f; + size_t len, i; + + hostres = gethostinfo(hostname, 1); + s = connect_to_any_host(hostres); + if (s == -1) + err(EX_OSERR, "connect()"); + + /* Restore default blocking behavior. */ + if ((f = fcntl(s, F_GETFL)) == -1) + err(EX_OSERR, "fcntl()"); + f &= ~O_NONBLOCK; + if (fcntl(s, F_SETFL, f) == -1) + err(EX_OSERR, "fcntl()"); + + fp = fdopen(s, "r+"); + if (fp == NULL) + err(EX_OSERR, "fdopen()"); + + if (!(flags & WHOIS_SPAM_ME) && + (strcasecmp(hostname, DENICHOST) == 0 || + strcasecmp(hostname, "de" QNICHOST_TAIL) == 0)) { + const char *q; + int idn = 0; + for (q = query; *q != '\0'; q++) + if (!isascii(*q)) + idn = 1; + fprintf(fp, "-T dn%s %s\r\n", idn ? "" : ",ace", query); + } else if (!(flags & WHOIS_SPAM_ME) && + (strcasecmp(hostname, DKNICHOST) == 0 || + strcasecmp(hostname, "dk" QNICHOST_TAIL) == 0)) + fprintf(fp, "--show-handles %s\r\n", query); + else if ((flags & WHOIS_SPAM_ME) || + strchr(query, ' ') != NULL) + fprintf(fp, "%s\r\n", query); + else if (strcasecmp(hostname, ANICHOST) == 0) { + if (strncasecmp(query, "AS", 2) == 0 && + strspn(query+2, "0123456789") == strlen(query+2)) + fprintf(fp, "+ a %s\r\n", query+2); + else + fprintf(fp, "+ %s\r\n", query); + } else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0) + fprintf(fp, "domain %s\r\n", query); + else + fprintf(fp, "%s\r\n", query); + fflush(fp); + + comment = 0; + if (!(flags & WHOIS_SPAM_ME) && + (strcasecmp(hostname, ANICHOST) == 0 || + strcasecmp(hostname, RNICHOST) == 0)) { + comment = 2; + } + + nhost = NULL; + while ((buf = fgetln(fp, &len)) != NULL) { + /* Nominet */ + if (!(flags & WHOIS_SPAM_ME) && + len == 5 && strncmp(buf, "-- \r\n", 5) == 0) + break; + /* RIRs */ + if (comment == 1 && buf[0] == '#') + break; + else if (comment == 2) { + if (strchr("#%\r\n", buf[0]) != NULL) + continue; + else + comment = 1; + } + + printf("%.*s", (int)len, buf); + + if ((flags & WHOIS_RECURSE) && nhost == NULL) { + for (i = 0; whois_referral[i].prefix != NULL; i++) { + p = buf; + SCAN(p, buf+len, *p == ' '); + if (strncasecmp(p, whois_referral[i].prefix, + whois_referral[i].len) != 0) + continue; + p += whois_referral[i].len; + SCAN(p, buf+len, *p == ' '); + host = p; + SCAN(p, buf+len, ishost(*p)); + if (p > host) + s_asprintf(&nhost, "%.*s", + (int)(p - host), host); + break; + } + for (i = 0; actually_arin[i] != NULL; i++) { + if (strncmp(buf, actually_arin[i], len) == 0) { + s_asprintf(&nhost, "%s", ANICHOST); + break; + } + } + } + /* Verisign etc. */ + if (!(flags & WHOIS_SPAM_ME) && + len >= sizeof(CHOPSPAM)-1 && + (strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 || + strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) { + printf("\n"); + break; + } + } + fclose(fp); + freeaddrinfo(hostres); + + f = 0; + for (i = 0; try_rir[i].host != NULL; i++) { + /* Remember visits to RIRs */ + if (try_rir[i].loop == 0 && + strcasecmp(try_rir[i].host, hostname) == 0) + try_rir[i].loop = 1; + /* Do we need to find an alternative RIR? */ + if (try_rir[i].loop != 0 && nhost != NULL && + strcasecmp(try_rir[i].host, nhost) == 0) { + free(nhost); + nhost = NULL; + f = 1; + } + } + if (f) { + /* Find a replacement RIR */ + for (i = 0; try_rir[i].host != NULL; i++) { + if (try_rir[i].loop == 0) { + s_asprintf(&nhost, "%s", + try_rir[i].host); + break; + } + } + } + if (nhost != NULL) { + /* Ignore self-referrals */ + if (strcasecmp(hostname, nhost) != 0) { + printf("# %s\n\n", nhost); + whois(query, nhost, flags); + } + free(nhost); + } +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: whois [-aAbfgiIklmPQrRS] [-c country-code | -h hostname] " + "[-p port] name ...\n"); + exit(EX_USAGE); +} diff --git a/adv_cmds/xcodescripts/variant_links.sh b/adv_cmds/xcodescripts/variant_links.sh new file mode 100644 index 0000000..523c755 --- /dev/null +++ b/adv_cmds/xcodescripts/variant_links.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# Variant links cannot be created in the actual target, because Strip/CodeSign/etc are +# after all other phases. Running it in the aggregate target guarantees that the variants +# are really linked to the actual stripped/signed binary. +# + +set -ex + +ln ${DSTROOT}/usr/bin/pkill ${DSTROOT}/usr/bin/pgrep +ln ${DSTROOT}/usr/share/man/man1/pkill.1 ${DSTROOT}/usr/share/man/man1/pgrep.1 diff --git a/basic_cmds/basic_cmds.xcodeproj/project.pbxproj b/basic_cmds/basic_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..093906e --- /dev/null +++ b/basic_cmds/basic_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,546 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 721D59C60FC5FA20009D810A /* Build All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 721D59C90FC5FA4E009D810A /* Build configuration list for PBXAggregateTarget "Build All" */; + buildPhases = ( + ); + dependencies = ( + 721D59D50FC5FB18009D810A /* PBXTargetDependency */, + 721D59D30FC5FB18009D810A /* PBXTargetDependency */, + 721D59D10FC5FB18009D810A /* PBXTargetDependency */, + 721D59CF0FC5FB18009D810A /* PBXTargetDependency */, + ); + name = "Build All"; + productName = "Build All"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 721D59850FC5F414009D810A /* mesg.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59840FC5F414009D810A /* mesg.c */; }; + 721D598D0FC5F49F009D810A /* mesg.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59830FC5F414009D810A /* mesg.1 */; }; + 721D59920FC5F53E009D810A /* write.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59900FC5F533009D810A /* write.c */; }; + 721D59940FC5F566009D810A /* write.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D598F0FC5F533009D810A /* write.1 */; }; + 721D599C0FC5F593009D810A /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D599A0FC5F593009D810A /* base64.c */; }; + 721D599D0FC5F593009D810A /* uudecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D599B0FC5F593009D810A /* uudecode.c */; }; + 721D59A10FC5F5C3009D810A /* uudecode.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D599F0FC5F5A8009D810A /* uudecode.1 */; }; + 721D59B30FC5F6D9009D810A /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59AF0FC5F6D9009D810A /* base64.c */; }; + 721D59B40FC5F6D9009D810A /* uuencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 721D59B20FC5F6D9009D810A /* uuencode.c */; }; + 721D59B60FC5F6F4009D810A /* uuencode.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59B00FC5F6D9009D810A /* uuencode.1 */; }; + 721D59B70FC5F6F4009D810A /* uuencode.5 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721D59B10FC5F6D9009D810A /* uuencode.5 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 721D59CE0FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D597C0FC5F36F009D810A; + remoteInfo = write; + }; + 721D59D00FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D59730FC5F347009D810A; + remoteInfo = mesg; + }; + 721D59D20FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D596C0FC5F33E009D810A; + remoteInfo = uudecode; + }; + 721D59D40FC5FB18009D810A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 721D59560FC5F325009D810A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 721D59630FC5F336009D810A; + remoteInfo = uuencode; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 721D598C0FC5F43F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D598D0FC5F49F009D810A /* mesg.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59980FC5F56F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59940FC5F566009D810A /* write.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59A40FC5F5CA009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59A10FC5F5C3009D810A /* uudecode.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59BC0FC5F70F009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 721D59B60FC5F6F4009D810A /* uuencode.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 721D59CD0FC5FA9D009D810A /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man5; + dstSubfolderSpec = 0; + files = ( + 721D59B70FC5F6F4009D810A /* uuencode.5 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 721D59640FC5F336009D810A /* uuencode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = uuencode; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D596D0FC5F33E009D810A /* uudecode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = uudecode; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D59740FC5F347009D810A /* mesg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mesg; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D597D0FC5F370009D810A /* write */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = write; sourceTree = BUILT_PRODUCTS_DIR; }; + 721D59830FC5F414009D810A /* mesg.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mesg.1; sourceTree = ""; }; + 721D59840FC5F414009D810A /* mesg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mesg.c; sourceTree = ""; }; + 721D598F0FC5F533009D810A /* write.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = write.1; sourceTree = ""; }; + 721D59900FC5F533009D810A /* write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = write.c; sourceTree = ""; }; + 721D599A0FC5F593009D810A /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; }; + 721D599B0FC5F593009D810A /* uudecode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uudecode.c; sourceTree = ""; }; + 721D599F0FC5F5A8009D810A /* uudecode.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = uudecode.1; sourceTree = ""; }; + 721D59AF0FC5F6D9009D810A /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; }; + 721D59B00FC5F6D9009D810A /* uuencode.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = uuencode.1; sourceTree = ""; }; + 721D59B10FC5F6D9009D810A /* uuencode.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = uuencode.5; sourceTree = ""; }; + 721D59B20FC5F6D9009D810A /* uuencode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uuencode.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 721D59620FC5F336009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D596B0FC5F33E009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D59720FC5F347009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D597B0FC5F36F009D810A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 721D59540FC5F325009D810A = { + isa = PBXGroup; + children = ( + 721D59A70FC5F613009D810A /* uuencode */, + 721D59970FC5F56F009D810A /* uudecode */, + 721D59810FC5F38E009D810A /* mesg */, + 721D598E0FC5F4AC009D810A /* write */, + 721D59650FC5F336009D810A /* Products */, + ); + sourceTree = ""; + }; + 721D59650FC5F336009D810A /* Products */ = { + isa = PBXGroup; + children = ( + 721D59640FC5F336009D810A /* uuencode */, + 721D596D0FC5F33E009D810A /* uudecode */, + 721D59740FC5F347009D810A /* mesg */, + 721D597D0FC5F370009D810A /* write */, + ); + name = Products; + sourceTree = ""; + }; + 721D59810FC5F38E009D810A /* mesg */ = { + isa = PBXGroup; + children = ( + 721D59830FC5F414009D810A /* mesg.1 */, + 721D59840FC5F414009D810A /* mesg.c */, + ); + path = mesg; + sourceTree = ""; + }; + 721D598E0FC5F4AC009D810A /* write */ = { + isa = PBXGroup; + children = ( + 721D598F0FC5F533009D810A /* write.1 */, + 721D59900FC5F533009D810A /* write.c */, + ); + path = write; + sourceTree = ""; + }; + 721D59970FC5F56F009D810A /* uudecode */ = { + isa = PBXGroup; + children = ( + 721D599A0FC5F593009D810A /* base64.c */, + 721D599F0FC5F5A8009D810A /* uudecode.1 */, + 721D599B0FC5F593009D810A /* uudecode.c */, + ); + path = uudecode; + sourceTree = ""; + }; + 721D59A70FC5F613009D810A /* uuencode */ = { + isa = PBXGroup; + children = ( + 721D59AF0FC5F6D9009D810A /* base64.c */, + 721D59B00FC5F6D9009D810A /* uuencode.1 */, + 721D59B10FC5F6D9009D810A /* uuencode.5 */, + 721D59B20FC5F6D9009D810A /* uuencode.c */, + ); + path = uuencode; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 721D59630FC5F336009D810A /* uuencode */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59690FC5F337009D810A /* Build configuration list for PBXNativeTarget "uuencode" */; + buildPhases = ( + 721D59610FC5F336009D810A /* Sources */, + 721D59620FC5F336009D810A /* Frameworks */, + 721D59BC0FC5F70F009D810A /* CopyFiles */, + 721D59CD0FC5FA9D009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = uuencode; + productName = uuencode; + productReference = 721D59640FC5F336009D810A /* uuencode */; + productType = "com.apple.product-type.tool"; + }; + 721D596C0FC5F33E009D810A /* uudecode */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59780FC5F348009D810A /* Build configuration list for PBXNativeTarget "uudecode" */; + buildPhases = ( + 721D596A0FC5F33E009D810A /* Sources */, + 721D596B0FC5F33E009D810A /* Frameworks */, + 721D59A40FC5F5CA009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = uudecode; + productName = uudecode; + productReference = 721D596D0FC5F33E009D810A /* uudecode */; + productType = "com.apple.product-type.tool"; + }; + 721D59730FC5F347009D810A /* mesg */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59790FC5F348009D810A /* Build configuration list for PBXNativeTarget "mesg" */; + buildPhases = ( + 721D59710FC5F347009D810A /* Sources */, + 721D59720FC5F347009D810A /* Frameworks */, + 721D598C0FC5F43F009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = mesg; + productName = mesg; + productReference = 721D59740FC5F347009D810A /* mesg */; + productType = "com.apple.product-type.tool"; + }; + 721D597C0FC5F36F009D810A /* write */ = { + isa = PBXNativeTarget; + buildConfigurationList = 721D59820FC5F38E009D810A /* Build configuration list for PBXNativeTarget "write" */; + buildPhases = ( + 721D597A0FC5F36F009D810A /* Sources */, + 721D597B0FC5F36F009D810A /* Frameworks */, + 721D59980FC5F56F009D810A /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = write; + productName = write; + productReference = 721D597D0FC5F370009D810A /* write */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 721D59560FC5F325009D810A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = 721D59590FC5F325009D810A /* Build configuration list for PBXProject "basic_cmds" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 721D59540FC5F325009D810A; + productRefGroup = 721D59650FC5F336009D810A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 721D59C60FC5FA20009D810A /* Build All */, + 721D59630FC5F336009D810A /* uuencode */, + 721D596C0FC5F33E009D810A /* uudecode */, + 721D59730FC5F347009D810A /* mesg */, + 721D597C0FC5F36F009D810A /* write */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 721D59610FC5F336009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59B30FC5F6D9009D810A /* base64.c in Sources */, + 721D59B40FC5F6D9009D810A /* uuencode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D596A0FC5F33E009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D599C0FC5F593009D810A /* base64.c in Sources */, + 721D599D0FC5F593009D810A /* uudecode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D59710FC5F347009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59850FC5F414009D810A /* mesg.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 721D597A0FC5F36F009D810A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 721D59920FC5F53E009D810A /* write.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 721D59CF0FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D597C0FC5F36F009D810A /* write */; + targetProxy = 721D59CE0FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D10FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D59730FC5F347009D810A /* mesg */; + targetProxy = 721D59D00FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D30FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D596C0FC5F33E009D810A /* uudecode */; + targetProxy = 721D59D20FC5FB18009D810A /* PBXContainerItemProxy */; + }; + 721D59D50FC5FB18009D810A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 721D59630FC5F336009D810A /* uuencode */; + targetProxy = 721D59D40FC5FB18009D810A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 721D59580FC5F325009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + INSTALL_MODE_FLAG = "gou-w,a+rX"; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + USE_HEADERMAP = NO; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_BUILDER = "$(USER)"; + VERSION_INFO_FILE = "$(PRODUCT_NAME)_vers.c"; + VERSION_INFO_PREFIX = __; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59680FC5F337009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = uuencode; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59700FC5F33F009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = uudecode; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59770FC5F348009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = mesg; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59800FC5F370009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_GROUP = tty; + INSTALL_MODE_FLAG = "gou-w,a+rX,g+s"; + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = write; + ZERO_LINK = NO; + }; + name = Release; + }; + 721D59C80FC5FA20009D810A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = basic_cmds; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 721D59590FC5F325009D810A /* Build configuration list for PBXProject "basic_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59580FC5F325009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59690FC5F337009D810A /* Build configuration list for PBXNativeTarget "uuencode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59680FC5F337009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59780FC5F348009D810A /* Build configuration list for PBXNativeTarget "uudecode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59700FC5F33F009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59790FC5F348009D810A /* Build configuration list for PBXNativeTarget "mesg" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59770FC5F348009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59820FC5F38E009D810A /* Build configuration list for PBXNativeTarget "write" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59800FC5F370009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 721D59C90FC5FA4E009D810A /* Build configuration list for PBXAggregateTarget "Build All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 721D59C80FC5FA20009D810A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 721D59560FC5F325009D810A /* Project object */; +} diff --git a/basic_cmds/mesg/mesg.1 b/basic_cmds/mesg/mesg.1 new file mode 100644 index 0000000..de2f7a4 --- /dev/null +++ b/basic_cmds/mesg/mesg.1 @@ -0,0 +1,112 @@ +.\" Copyright (c) 1987, 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. +.\" +.\" @(#)mesg.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/mesg/mesg.1,v 1.10 2002/07/25 05:16:49 tjr Exp $ +.\" +.Dd May 5, 2002 +.Dt MESG 1 +.Os +.Sh NAME +.Nm mesg +.Nd display (do not display) messages from other users +.Sh SYNOPSIS +.Nm +.Op Cm n | Cm y +.Sh DESCRIPTION +The +.Nm +utility is invoked by a user to control write access others +have to a terminal device. +Write access is allowed by default, and programs such as +.Xr talk 1 +and +.Xr write 1 +may display messages on the terminal. +.Pp +The first terminal device in the sequence of devices associated with standard +input, standard output and standard error is affected. +.Pp +Options available: +.Bl -tag -width flag +.It Cm n +Disallows messages. +.It Cm y +Permits messages to be displayed. +.El +.Pp +If no arguments are given, +.Nm +displays the present message status to the standard output. +.Sh EXAMPLES +Disallow messages from other users to the current terminal: +.Pp +.Dl "mesg n" +.Pp +Allow messages from other users to +.Pa ttyp1 +(assuming you are also logged in on that terminal): +.Pp +.Dl "mesg y 1" +An error has occurred. +.El +.Sh COMPATIBILITY +Previous versions of the +.Nm +utility wrote the message status to the standard error output and +affected the terminal attached to standard error without first trying the +standard input or output devices. +.Sh SEE ALSO +.Xr biff 1 , +.Xr talk 1 , +.Xr wall 1 , +.Xr write 1 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1-2001 . +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . diff --git a/basic_cmds/mesg/mesg.c b/basic_cmds/mesg/mesg.c new file mode 100644 index 0000000..b66980b --- /dev/null +++ b/basic_cmds/mesg/mesg.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 const char copyright[] = +"@(#) Copyright (c) 1987, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)mesg.c 8.2 (Berkeley) 1/21/94"; +#endif +#endif /* not lint */ +#include +__RCSID("$FreeBSD: src/usr.bin/mesg/mesg.c,v 1.8 2002/09/04 23:29:04 dwmalone Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +static void usage(void); + +int +main(int argc, char *argv[]) +{ + struct stat sb; + char *tty; + int ch; + + while ((ch = getopt(argc, argv, "")) != -1) + switch (ch) { + case '?': + default: + usage(); + } +// argc -= optind; + argv += optind; + + if ((tty = ttyname(STDIN_FILENO)) == NULL && + (tty = ttyname(STDOUT_FILENO)) == NULL && + (tty = ttyname(STDERR_FILENO)) == NULL) + err(2, "ttyname"); + if (stat(tty, &sb) < 0) + err(2, "%s", tty); + + if (*argv == NULL) { + if (sb.st_mode & S_IWGRP) { + (void)puts("is y"); + exit(0); + } + (void)puts("is n"); + exit(1); + } + + switch (*argv[0]) { + case 'y': + if (chmod(tty, sb.st_mode | S_IWGRP) < 0) + err(2, "%s", tty); + exit(0); + case 'n': + if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) + err(2, "%s", tty); + exit(1); + } + + usage(); + return(0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: mesg [y | n]\n"); + exit(2); +} diff --git a/basic_cmds/uudecode/base64.c b/basic_cmds/uudecode/base64.c new file mode 100644 index 0000000..b537171 --- /dev/null +++ b/basic_cmds/uudecode/base64.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +#include +__unused static char rcsid[] = "$FreeBSD: src/lib/libc/net/base64.c,v 1.4 1999/11/04 04:30:43 ache Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/basic_cmds/uudecode/uudecode.1 b/basic_cmds/uudecode/uudecode.1 new file mode 100644 index 0000000..ace1742 --- /dev/null +++ b/basic_cmds/uudecode/uudecode.1 @@ -0,0 +1 @@ +.so man1/uuencode.1 diff --git a/basic_cmds/uudecode/uudecode.c b/basic_cmds/uudecode/uudecode.c new file mode 100644 index 0000000..4831cab --- /dev/null +++ b/basic_cmds/uudecode/uudecode.c @@ -0,0 +1,504 @@ +/*- + * 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. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: head/usr.bin/uudecode/uudecode.c 214010 2010-10-18 05:44:11Z edwin $"); + +/* + * uudecode [file ...] + * + * create the specified file, decoding as you go. + * used with uuencode. + */ +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *infile, *outfile; +static FILE *infp, *outfp; +static int base64, cflag, iflag, oflag, pflag, rflag, sflag; + +static void usage(void); +static int decode(void); +static int decode2(void); +static int uu_decode(void); +static int base64_decode(void); + +int +main(int argc, char *argv[]) +{ + int rval, ch; + + if (strcmp(basename(argv[0]), "b64decode") == 0) + base64 = 1; + + while ((ch = getopt(argc, argv, "cimo:prs")) != -1) { + switch (ch) { + case 'c': + if (oflag || rflag) + usage(); + cflag = 1; /* multiple uudecode'd files */ + break; + case 'i': + iflag = 1; /* ask before override files */ + break; + case 'm': + base64 = 1; + break; + case 'o': + if (cflag || pflag || rflag || sflag) + usage(); + oflag = 1; /* output to the specified file */ + sflag = 1; /* do not strip pathnames for output */ + outfile = optarg; /* set the output filename */ + break; + case 'p': + if (oflag) + usage(); + pflag = 1; /* print output to stdout */ + break; + case 'r': + if (cflag || oflag) + usage(); + rflag = 1; /* decode raw data */ + break; + case 's': + if (oflag) + usage(); + sflag = 1; /* do not strip pathnames for output */ + break; + default: + usage(); + } + } +// argc -= optind; + argv += optind; + + if (*argv != NULL) { + rval = 0; + do { + infp = fopen(infile = *argv, "r"); + if (infp == NULL) { + warn("%s", *argv); + rval = 1; + continue; + } + rval |= decode(); + fclose(infp); + } while (*++argv); + } else { + infile = "stdin"; + infp = stdin; + rval = decode(); + } + exit(rval); +} + +static int +decode(void) +{ + int r, v; + + if (rflag) { + /* relaxed alternative to decode2() */ + outfile = "/dev/stdout"; + outfp = stdout; + if (base64) + return (base64_decode()); + else + return (uu_decode()); + } + v = decode2(); + if (v == EOF) { + warnx("%s: missing or bad \"begin\" line", infile); + return (1); + } + for (r = v; cflag; r |= v) { + v = decode2(); + if (v == EOF) + break; + } + return (r); +} + +static int +decode2(void) +{ + int flags, fd, mode; + size_t n, m; + char *p, *q = NULL, *orig_outfile = NULL; + void *handle; + struct passwd *pw; + struct stat st; + char buf[MAXPATHLEN + 1]; + + base64 = 0; + /* search for header line */ + for (;;) { + if (fgets(buf, sizeof(buf), infp) == NULL) + return (EOF); + p = buf; + if (strncmp(p, "begin-base64 ", 13) == 0) { + base64 = 1; + p += 13; + } else if (strncmp(p, "begin ", 6) == 0) + p += 6; + else + continue; + /* p points to mode */ + q = strchr(p, ' '); + if (q == NULL) + continue; + *q++ = '\0'; + /* q points to filename */ + n = strlen(q); + while (n > 0 && (q[n-1] == '\n' || q[n-1] == '\r')) + q[--n] = '\0'; + /* found valid header? */ + if (n > 0) + break; + } + orig_outfile = q; + handle = setmode(p); + if (handle == NULL) { + warnx("%s: unable to parse file mode", infile); + return (1); + } + mode = getmode(handle, 0); + free(handle); + + if (sflag) { + /* don't strip, so try ~user/file expansion */ + p = NULL; + pw = NULL; + if (*q == '~') + p = strchr(q, '/'); + if (p != NULL) { + *p = '\0'; + pw = getpwnam(q + 1); + *p = '/'; + } + if (pw != NULL) { + n = strlen(pw->pw_dir); + if (buf + n > p) { + /* make room */ + m = strlen(p); + if (sizeof(buf) < n + m) { + warnx("%s: bad output filename", + infile); + return (1); + } + p = memmove(buf + n, p, m); + } + q = memcpy(p - n, pw->pw_dir, n); + } + } else { + /* strip down to leaf name */ + p = strrchr(q, '/'); + if (p != NULL) + q = p + 1; + } + if (!oflag) { + outfile = q ? strdup(q) : q; + } + + /* POSIX says "/dev/stdout" is a 'magic cookie' not a special file. */ + if (pflag || (strcmp(oflag ? outfile : orig_outfile, "/dev/stdout") == 0)) { + outfp = stdout; + } else { + char pwd[MAXPATHLEN] = ""; + char targetpath[MAXPATHLEN]; + flags = O_WRONLY | O_CREAT | O_EXCL; + if (lstat(outfile, &st) == 0) { + if (iflag && !S_ISFIFO(st.st_mode)) { + warnc(EEXIST, "%s: %s", infile, outfile); + return (0); + } + + flags = O_RDWR; + switch (st.st_mode & S_IFMT) { + case S_IFREG: + flags |= O_NOFOLLOW | O_TRUNC; + break; + case S_IFLNK: + if (NULL == realpath(".", pwd)) { + warn("Unable to get realpath for ."); + return (1); + } + flags |= O_CREAT; // for dangling symlinks + break; + case S_IFDIR: + warnc(EISDIR, "%s: %s", infile, outfile); + return (1); + case S_IFIFO: + flags &= ~O_EXCL; + break; + default: + if (oflag) { + /* trust command-line names */ + flags &= ~O_EXCL; + break; + } + warnc(EEXIST, "%s: %s", infile, outfile); + return (1); + } + } else if (errno != ENOENT) { + warn("%s: %s", infile, outfile); + return (1); + } + fd = open(outfile, flags, mode); + if (fd < 0) { + warn("%s: %s", infile, outfile); + return (1); + } + if (pwd[0]) { + if (-1 != fcntl(fd, F_GETPATH, targetpath)) { + if (strstr(targetpath, pwd) != targetpath) { + warnx("Target path %s is not based at %s", targetpath, pwd); + close(fd); + return (1); + } + ftruncate(fd, 0); + } else { + close(fd); + warn("Unable to get path for target: %s", outfile); + return (1); + } + } + if ((outfp = fdopen(fd, "w")) == NULL) { + warn("%s: %s", infile, outfile); + close(fd); + return (1); + } + if (fchmod(fileno(outfp), mode) && (EPERM != errno)) { + warn("%s: %s", infile, outfile); + close(fd); + return 1; + } + } + if (base64) + return (base64_decode()); + else + return (uu_decode()); +} + +static int +uugetline(char *buf, size_t size) +{ + + if (fgets(buf, size, infp) != NULL) + return (2); + if (rflag) + return (0); + warnx("%s: %s: short file", infile, outfile); + return (1); +} + +static int +checkend(const char *ptr, const char *end, const char *msg) +{ + size_t n; + + n = strlen(end); + if (strncmp(ptr, end, n) != 0 || + strspn(ptr + n, " \t\r\n") != strlen(ptr + n)) { + warnx("%s: %s: %s", infile, outfile, msg); + return (1); + } + if (fclose(outfp) != 0) { + warn("%s: %s", infile, outfile); + return (1); + } + return (0); +} + +static int +uu_decode(void) +{ + int i, ch; + char *p; + char buf[MAXPATHLEN+1]; + + /* for each input line */ + for (;;) { + switch (uugetline(buf, sizeof(buf))) { + case 0: + return (0); + case 1: + return (1); + } + +#define DEC(c) (((c) - ' ') & 077) /* single character decode */ +#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) + +#define OUT_OF_RANGE do { \ + warnx("%s: %s: character out of range: [%d-%d]", \ + infile, outfile, 1 + ' ', 077 + ' ' + 1); \ + return (1); \ +} while (0) + + /* + * `i' is used to avoid writing out all the characters + * at the end of the file. + */ + p = buf; + if ((i = DEC(*p)) <= 0) + break; + for (++p; i > 0; p += 4, i -= 3) + if (i >= 3) { + if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) && + IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) + OUT_OF_RANGE; + + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putc(ch, outfp); + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putc(ch, outfp); + ch = DEC(p[2]) << 6 | DEC(p[3]); + putc(ch, outfp); + } else { + if (i >= 1) { + if (!(IS_DEC(*p) && IS_DEC(*(p + 1)))) + OUT_OF_RANGE; + ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; + putc(ch, outfp); + } + if (i >= 2) { + if (!(IS_DEC(*(p + 1)) && + IS_DEC(*(p + 2)))) + OUT_OF_RANGE; + + ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + putc(ch, outfp); + } + if (i >= 3) { + if (!(IS_DEC(*(p + 2)) && + IS_DEC(*(p + 3)))) + OUT_OF_RANGE; + ch = DEC(p[2]) << 6 | DEC(p[3]); + putc(ch, outfp); + } + } + } + switch (uugetline(buf, sizeof(buf))) { + case 0: + return (0); + case 1: + return (1); + default: + return (checkend(buf, "end", "no \"end\" line")); + } +} + +static int +base64_decode(void) +{ + int n, count, count4; + char inbuf[MAXPATHLEN + 1], *p; + unsigned char outbuf[MAXPATHLEN * 4]; + char leftover[MAXPATHLEN + 1]; + + leftover[0] = '\0'; + for (;;) { + strcpy(inbuf, leftover); + switch (uugetline(inbuf + strlen(inbuf), + sizeof(inbuf) - strlen(inbuf))) { + case 0: + return (0); + case 1: + return (1); + } + + count = 0; + count4 = -1; + p = inbuf; + while (*p != '\0') { + /* + * Base64 encoded strings have the following + * characters in them: A-Z, a-z, 0-9 and +, / and = + */ + if (isalnum(*p) || *p == '+' || *p == '/' || *p == '=') + count++; + if (count % 4 == 0) + count4 = p - inbuf; + p++; + } + + strcpy(leftover, inbuf + count4 + 1); + inbuf[count4 + 1] = 0; + + n = b64_pton(inbuf, outbuf, sizeof(outbuf)); + + if (n < 0) + break; + fwrite(outbuf, 1, n, outfp); + } + return (checkend(inbuf, "====", "error decoding base64 input stream")); +} + +static void +usage(void) +{ + + (void)fprintf(stderr, + "usage: uudecode [-cimprs] [file ...]\n" + " uudecode [-i] -o output_file [file]\n" + " b64decode [-cimprs] [file ...]\n" + " b64decode [-i] -o output_file [file]\n"); + exit(1); +} diff --git a/basic_cmds/uuencode/base64.c b/basic_cmds/uuencode/base64.c new file mode 100644 index 0000000..b537171 --- /dev/null +++ b/basic_cmds/uuencode/base64.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +#include +__unused static char rcsid[] = "$FreeBSD: src/lib/libc/net/base64.c,v 1.4 1999/11/04 04:30:43 ache Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/basic_cmds/uuencode/uuencode.1 b/basic_cmds/uuencode/uuencode.1 new file mode 100644 index 0000000..20a8bf4 --- /dev/null +++ b/basic_cmds/uuencode/uuencode.1 @@ -0,0 +1,192 @@ +.\" Copyright (c) 1980, 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. +.\" +.\" @(#)uuencode.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/uuencode/uuencode.1,v 1.9.2.6 2002/04/27 01:55:11 jmallett Exp $ +.\" +.Dd January 27, 2002 +.Dt UUENCODE 1 +.Os +.Sh NAME +.Nm uudecode , +.Nm uuencode +.Nd encode/decode a binary file +.Sh SYNOPSIS +.Nm uuencode +.Op Fl m +.Op Fl o Ar output_file +.Op Ar file +.Ar name +.Nm uudecode +.Op Fl cips +.Op Ar +.Nm uudecode +.Op Fl i +.Fl o Ar output_file +.Op Ar file +.Sh DESCRIPTION +The +.Nm uuencode +and +.Nm uudecode +utilities are used to transmit binary files over transmission mediums +that do not support other than simple +.Tn ASCII +data. +.Pp +The +.Nm uuencode +utility reads +.Ar file +(or by default the standard input) and writes an encoded version +to the standard output, or +.Ar output_file +if one has been specified. +The encoding uses only printing +.Tn ASCII +characters and includes the +mode of the file and the operand +.Ar name +for use by +.Nm uudecode . +.Pp +The +.Nm uudecode +utility transforms +.Em uuencoded +files (or by default, the standard input) into the original form. +The resulting file is named either +.Ar name +or (depending on options passed to +.Nm uudecode ) +.Ar output_file +and will have the mode of the original file except that setuid +and execute bits are not retained. +The +.Nm uudecode +utility ignores any leading and trailing lines. +.Pp +The following options are available for +.Nm uuencode : +.Bl -tag -width ident +.It Fl m +Use the Base64 method of encoding, rather than the traditional +.Nm uuencode +algorithm. +.It Fl o Ar output_file +Output to +.Ar output_file +instead of standard output. +.El +.Pp +The following options are available for +.Nm uudecode : +.Bl -tag -width ident +.It Fl c +Decode more than one uuencode'd file from +.Ar file +if possible. +.It Fl i +Do not overwrite files. +.It Fl o Ar output_file +Output to +.Ar output_file +instead of any pathname contained in the input data. +.It Fl p +Decode +.Ar file +and write output to standard output. +.It Fl s +Do not strip output pathname to base filename. +By default +.Nm uudecode +deletes any prefix ending with the last slash '/' for security +purpose. +.El +.Sh EXAMPLES +The following example packages up a source tree, compresses it, +uuencodes it and mails it to a user on another system. +When +.Nm uudecode +is run on the target system, the file ``src_tree.tar.Z'' will be +created which may then be uncompressed and extracted into the original +tree. +.Pp +.Bd -literal -offset indent -compact +tar cf \- src_tree \&| compress \&| +uuencode src_tree.tar.Z \&| mail sys1!sys2!user +.Ed +.Pp +The following example unpack all uuencode'd +files from your mailbox into your current working directory. +.Pp +.Bd -literal -offset indent -compact +uudecode -c < $MAIL +.Ed +.Pp +The following example extract a compress'ed tar +archive from your mailbox +.Pp +.Bd -literal -offset indent -compact +uudecode -o /dev/stdout < $MAIL | zcat | tar xfv - +.Ed +.Sh LEGACY DESCRIPTION +In legacy operation, +.Nm uudecode +masks file modes with 0666, +preventing the creation of executable files. +.Pp +.Nm uudecode +cannot change the mode of a created file +which is not owned by the current user (unless that user is root). +In legacy operation, +.Xr fchmod 2 +allows the mode to be changed. +.Pp +For more information about legacy mode, see +.Xr compat 5 . +.Sh SEE ALSO +.Xr basename 1 , +.Xr compress 1 , +.Xr mail 1 , +.Xr uucp 1 , +.Xr fchmod 2 , +.Xr uuencode 5 +.Sh BUGS +Files encoded using the traditional algorithm are expanded by 35% +(3 bytes become 4, plus control information). +.Sh HISTORY +The +.Nm uudecode +and +.Nm uuencode +utilities appeared in +.Bx 4.0 . diff --git a/basic_cmds/uuencode/uuencode.5 b/basic_cmds/uuencode/uuencode.5 new file mode 100644 index 0000000..3914dad --- /dev/null +++ b/basic_cmds/uuencode/uuencode.5 @@ -0,0 +1,100 @@ +.TH uuencode 5 "May, 2001" "Apple Computer, Inc." +.SH NAME +uuencode file format +.NM uuencode +.ND description of the uuencode file format +.SH DESCRIPTION + +The +.XR uuencode 1 +command generates files in a format that allows them to be successfully +transferred by systems which strip the high bit from an 8-bit byte. +.XR uudecode 1 +decodes uuencoded files. + +.PP +The uuencode file format consists of three sections: header, body, and trailer. +The header is a line is of the form: + +.PP +begin 644 "filename.ext" + +.PP +where "644" is a +.XR chmod 1 +-format permissions byte for the file and "filename.ext" is the name of +the encoded file. + +.PP +The body section is the encoded representation of the source file. Three +bytes of input file data are encoded into four bytes of output data. +.PP +The 24 input bits are divided up into four pieces of six bits +each. The integer value 32 (the ASCII value for the space character) is +added to each of these pieces to move them outside of the range of control +characters. To avoid using the space character in the encoding, pieces with +value zero are encoded using backquote (ASCII value 96) instead of zero. The +resulting character is one of the this set (ASCII values 96,33-95): + +.DQ `!"#$%&'()*+,-./012356789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ + +.PP +A line itself contains three segments: a length character (encoded using +the "add a space" algorithm described above), the body of the line, +typically (although not required to be) 60 output characters long, +representing 45 input bytes, and (of course) a linefeed. The length +character specifies the number of valid input bytes on the line (so, for +a line which is 60 encoded bytes, the length value would be 45). +Decoding programs should decode no further than the specified length on +a single line. + +.PP +The trailer, which must exist, consists of a single backquote +("`", ASCII 96) character on a line by itself, directly followed by +.DQ end +on a line by itself. + +.PP +.DQ .uue +is the canonical filename extension for uuencoded files. + +.SH BUGS +uudecode does not read all permutations of the file format described in +this man page. + +.PP +Ancient versions of uuencode used a space character (ASCII 32) in the +encoding to represent zero. Many (arguably broken) mailers and transport +agents stripped, rewrapped, or otherwise mangled this format, so the space +was later changed to the backquote, ASCII 96. Decoders may attempt to +read the older format if they wish, though it's unlikely to be encountered +in practice at this point in time. + +.PP +The uuencode encoding method is highly ASCII-centric. In particular, the +character set used doesn't work well on EBCDIC-based systems. (EBCDIC, +generally used by IBM mainframes, is an old alternative character encoding; +most computers use ASCII instead). + +.PP +Many variants of uuencode on various platforms generate different forms +of line checksums, using to represent the checksum one or more encoded +characters after the last counted character in a line. Because these +formats are different and impossible to distinguish (with certainty), +such characters should be ignored by decoding implementations. + +.PP +The uuencode encoding format has no provisions for segmented files. +Writers of segmenting utilities should be careful to avoid using +character sequences that may naturally occur in the encoding (such +as sequences of dashes ("---")) to divide sections. + +.SH SEE ALSO +The MIME Base64 encoding (documented in RFC 2045) is a consistent, +cross-platform-savvy message encoding which should be used in place of +UUEncode wherever possible. + +.PP +The Unix-Hater's Handbook (IDG, 1994) identifies the folly of the +older zero-encoded-as-space versions of uuencode. + diff --git a/basic_cmds/uuencode/uuencode.c b/basic_cmds/uuencode/uuencode.c new file mode 100644 index 0000000..bb528a6 --- /dev/null +++ b/basic_cmds/uuencode/uuencode.c @@ -0,0 +1,226 @@ +/*- + * 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. + */ + +#ifndef lint +#include +__unused static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94"; +#endif +__unused static const char rcsid[] = + "$FreeBSD: src/usr.bin/uuencode/uuencode.c,v 1.4.2.4 2002/06/17 05:01:46 jmallett Exp $"; +#endif /* not lint */ + +/* + * uuencode [input] output + * + * Encode a file so it can be mailed to a remote system. + */ +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +int b64_ntop __P((u_char const *, size_t, char *, size_t)); +int b64_pton __P((char const *, u_char *, size_t)); +void encode(void); +void base64_encode(void); +static void usage(void); + +FILE *output; +int mode; +char **av; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct stat sb; + int base64; + char ch; + char *outfile; + + base64 = 0; + outfile = NULL; + + while ((ch = getopt(argc, argv, "mo:")) != -1) { + switch (ch) { + case 'm': + base64 = 1; + break; + case 'o': + outfile = optarg; + break; + case '?': + default: + usage(); + } + } + argv += optind; + argc -= optind; + + switch(argc) { + case 2: /* optional first argument is input file */ + if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) + err(1, "%s", *argv); +#define RWX (S_IRWXU|S_IRWXG|S_IRWXO) + mode = sb.st_mode & RWX; + ++argv; + break; + case 1: +#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + mode = RW & ~umask(RW); + break; + case 0: + default: + usage(); + } + + av = argv; + + if (outfile != NULL) { + output = fopen(outfile, "w+"); + if (output == NULL) + err(1, "unable to open %s for output", outfile); + } else + output = stdout; + if (base64) + base64_encode(); + else + encode(); + if (ferror(output)) + errx(1, "write error"); + exit(0); +} + +/* ENC is the basic 1 character encoding function to make a char printing */ +#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') + +/* + * Copy from in to out, encoding in base64 as you go along. + */ +void +base64_encode() +{ + /* + * Output must fit into 80 columns, chunks come in 4, leave 1. + */ +#define GROUPS ((80 / 4) - 1) + unsigned char buf[3]; + char buf2[sizeof(buf) * 2 + 1]; + size_t n; + int rv, sequence; + + sequence = 0; + + fprintf(output, "begin-base64 %o %s\n", mode, *av); + while ((n = fread(buf, 1, sizeof(buf), stdin))) { + ++sequence; + rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0]))); + if (rv == -1) + errx(1, "b64_ntop: error encoding base64"); + fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); + } + if (sequence % GROUPS) + fprintf(output, "\n"); + fprintf(output, "====\n"); +} + +/* + * Copy from in to out, encoding as you go along. + */ +void +encode() +{ + register int ch, n; + register char *p; + char buf[80]; + + (void)fprintf(output, "begin %o %s\n", mode, *av); + while ((n = fread(buf, 1, 45, stdin))) { + ch = ENC(n); + if (fputc(ch, output) == EOF) + break; + for (p = buf; n > 0; n -= 3, p += 3) { + /* Pad with nulls if not a multiple of 3. */ + if (n < 3) { + p[2] = '\0'; + if (n < 2) + p[1] = '\0'; + } + ch = *p >> 2; + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + ch = p[2] & 077; + ch = ENC(ch); + if (fputc(ch, output) == EOF) + break; + } + if (fputc('\n', output) == EOF) + break; + } + if (ferror(stdin)) + errx(1, "read error"); + (void)fprintf(output, "%c\nend\n", ENC('\0')); +} + +static void +usage() +{ + (void)fprintf(stderr,"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"); + exit(1); +} diff --git a/basic_cmds/write/write.1 b/basic_cmds/write/write.1 new file mode 100644 index 0000000..c7c2df1 --- /dev/null +++ b/basic_cmds/write/write.1 @@ -0,0 +1,106 @@ +.\" Copyright (c) 1989, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 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. +.\" +.\" @(#)write.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/write/write.1,v 1.10 2002/04/20 12:18:12 charnier Exp $ +.\" +.Dd June 6, 1993 +.Dt WRITE 1 +.Os +.Sh NAME +.Nm write +.Nd send a message to another user +.Sh SYNOPSIS +.Nm +.Ar user +.Op Ar ttyname +.Sh DESCRIPTION +The +.Nm +utility allows you to communicate with other users, by copying lines from +your terminal to theirs. +.Pp +When you run the +.Nm +command, the user you are writing to gets a message of the form: +.Pp +.Dl Message from yourname@yourhost on yourtty at hh:mm ... +.Pp +Any further lines you enter will be copied to the specified user's +terminal. +If the other user wants to reply, they must run +.Nm +as well. +.Pp +When you are done, type an end-of-file or interrupt character. +The other user will see the message +.Ql EOF +indicating that the +conversation is over. +.Pp +You can prevent people (other than the super-user) from writing to you +with the +.Xr mesg 1 +command. +.Pp +If the user you want to write to is logged in on more than one terminal, +you can specify which terminal to write to by specifying the terminal +name as the second operand to the +.Nm +command. +Alternatively, you can let +.Nm +select one of the terminals \- it will pick the one with the shortest +idle time. +This is so that if the user is logged in at work and also dialed up from +home, the message will go to the right place. +.Pp +The traditional protocol for writing to someone is that the string +.Ql \-o , +either at the end of a line or on a line by itself, means that it's the +other person's turn to talk. +The string +.Ql oo +means that the person believes the conversation to be +over. +.Sh SEE ALSO +.Xr mesg 1 , +.Xr talk 1 , +.Xr wall 1 , +.Xr who 1 +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . diff --git a/basic_cmds/write/write.c b/basic_cmds/write/write.c new file mode 100644 index 0000000..e3f2255 --- /dev/null +++ b/basic_cmds/write/write.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +__unused static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)write.c 8.1 (Berkeley) 6/6/93"; +#endif +#endif + +__RCSID("$FreeBSD: src/usr.bin/write/write.c,v 1.17 2002/09/04 23:29:09 dwmalone Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void done(int); +void do_write(char *, char *, uid_t); +static void usage(void); +int term_chk(char *, int *, time_t *, int); +void wr_fputs(unsigned char *s); +void search_utmp(char *, char *, char *, uid_t); +int utmp_chk(char *, char *); + +int +main(int argc, char **argv) +{ + char *cp; + time_t atime; + uid_t myuid; + int msgsok, myttyfd; + char tty[MAXPATHLEN], *mytty; + + (void)setlocale(LC_CTYPE, ""); + + while (getopt(argc, argv, "") != -1) + usage(); + argc -= optind; + argv += optind; + + /* check that sender has write enabled */ + if (isatty(fileno(stdin))) + myttyfd = fileno(stdin); + else if (isatty(fileno(stdout))) + myttyfd = fileno(stdout); + else if (isatty(fileno(stderr))) + myttyfd = fileno(stderr); + else + myttyfd=-1; + if(myttyfd == -1) + mytty = "tty??"; + else + { + if (!(mytty = ttyname(myttyfd))) + errx(1, "can't find your tty's name"); + if ((cp = rindex(mytty, '/'))) + mytty = cp + 1; + if (term_chk(mytty, &msgsok, &atime, 1)) + exit(1); + if (!msgsok) + errx(1, "you have write permission turned off"); + } + myuid = getuid(); + + /* check args */ + switch (argc) { + case 1: + search_utmp(argv[0], tty, mytty, myuid); + do_write(tty, mytty, myuid); + break; + case 2: + if (!strncmp(argv[1], _PATH_DEV, strlen(_PATH_DEV))) + argv[1] += strlen(_PATH_DEV); + if (utmp_chk(argv[0], argv[1])) + errx(1, "%s is not logged in on %s", argv[0], argv[1]); + if (term_chk(argv[1], &msgsok, &atime, 1)) + exit(1); + if (myuid && !msgsok) + errx(1, "%s has messages disabled on %s", argv[0], argv[1]); + do_write(argv[1], mytty, myuid); + break; + default: + usage(); + } + done(0); + return (0); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: write user [tty]\n"); + exit(1); +} + +/* + * utmp_chk - checks that the given user is actually logged in on + * the given tty + */ +int +utmp_chk(char *user, char *tty) +{ + struct utmpx *u; + + setutxent(); + while((u = getutxent()) != NULL) + if(strncmp(u->ut_line, tty, sizeof(u->ut_line)) == 0) { + if(u->ut_type == USER_PROCESS && + strncmp(u->ut_user, user, sizeof(u->ut_user)) == 0) { + endutxent(); + return 0; + } + break; + } + endutxent(); + return 1; +} + +/* + * search_utmp - search utmp for the "best" terminal to write to + * + * Ignores terminals with messages disabled, and of the rest, returns + * the one with the most recent access time. Returns as value the number + * of the user's terminals with messages enabled, or -1 if the user is + * not logged in at all. + * + * Special case for writing to yourself - ignore the terminal you're + * writing from, unless that's the only terminal with messages enabled. + */ +void +search_utmp(char *user, char *tty, char *mytty, uid_t myuid) +{ + struct utmpx ux, *u; + time_t bestatime, atime; + int nloggedttys, nttys, msgsok, user_is_me; + char atty[sizeof(ux.ut_line) + 1]; + + nloggedttys = nttys = 0; + bestatime = 0; + user_is_me = 0; + setutxent(); + while ((u = getutxent()) != NULL) { + if (u->ut_type != USER_PROCESS) + continue; + if (strncmp(user, u->ut_user, sizeof(u->ut_user)) == 0) { + ++nloggedttys; + (void)strlcpy(atty, u->ut_line, sizeof(atty)); + if (term_chk(atty, &msgsok, &atime, 0)) + continue; /* bad term? skip */ + if (myuid && !msgsok) + continue; /* skip ttys with msgs off */ + if (strcmp(atty, mytty) == 0) { + user_is_me = 1; + continue; /* don't write to yourself */ + } + ++nttys; + if (atime > bestatime) { + bestatime = atime; + (void)strcpy(tty, atty); + } + } + } + + endutxent(); + if (nloggedttys == 0) + errx(1, "%s is not logged in", user); + if (nttys == 0) { + if (user_is_me) { /* ok, so write to yourself! */ + (void)strcpy(tty, mytty); + return; + } + errx(1, "%s has messages disabled", user); + } else if (nttys > 1) { + warnx("%s is logged in more than once; writing to %s", user, tty); + } +} + +/* + * term_chk - check that a terminal exists, and get the message bit + * and the access time + */ +int +term_chk(char *tty, int *msgsokP, time_t *atimeP, int showerror) +{ + struct stat s; + char path[MAXPATHLEN]; + + (void)snprintf(path, sizeof(path), "%s%s", _PATH_DEV, tty); + if (stat(path, &s) < 0) { + if (showerror) + warn("%s", path); + return(1); + } + *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ + *atimeP = s.st_atime; + return(0); +} + +/* + * do_write - actually make the connection + */ +void +do_write(char *tty, char *mytty, uid_t myuid) +{ + const char *login; + char *nows; + struct passwd *pwd; + time_t now; + char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; + + /* Determine our login name before the we reopen() stdout */ + if ((login = getlogin()) == NULL) { + if ((pwd = getpwuid(myuid))) + login = pwd->pw_name; + else + login = "???"; + } + + (void)snprintf(path, sizeof(path), "%s%s", _PATH_DEV, tty); + if ((freopen(path, "w", stdout)) == NULL) + err(1, "%s", path); + + (void)signal(SIGINT, done); + (void)signal(SIGHUP, done); + + /* print greeting */ + if (gethostname(host, sizeof(host)) < 0) + (void)strcpy(host, "???"); + now = time((time_t *)NULL); + nows = ctime(&now); + nows[16] = '\0'; + (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", + login, host, mytty, nows + 11); + + while (fgets(line, sizeof(line), stdin) != NULL) + wr_fputs((unsigned char *)line); +} + +/* + * done - cleanup and exit + */ +void +done(int n) +{ + (void)printf("EOF\r\n"); + exit(0); +} + +/* + * wr_fputs - like fputs(), but makes control characters visible and + * turns \n into \r\n + */ +void +wr_fputs(unsigned char *s) +{ + +#define PUTC(c) if (putchar(c) == EOF) err(1, NULL); + + for (; *s != '\0'; ++s) { + if (*s == '\n') { + PUTC('\r'); + } else if (((*s & 0x80) && *s < 0xA0) || + /* disable upper controls */ + (!isprint(*s) && !isspace(*s) && + *s != '\a' && *s != '\b') + ) { + if (*s & 0x80) { + *s &= ~0x80; + PUTC('M'); + PUTC('-'); + } + if (iscntrl(*s)) { + *s ^= 0x40; + PUTC('^'); + } + } + PUTC(*s); + } + return; +#undef PUTC +} diff --git a/bootstrap_cmds/.gitignore b/bootstrap_cmds/.gitignore new file mode 100644 index 0000000..e073c02 --- /dev/null +++ b/bootstrap_cmds/.gitignore @@ -0,0 +1,6 @@ +BUILD/ +build/ +.DS_Store +/mig.xcodeproj/project.xcworkspace/ +/mig.xcodeproj/xcuserdata/ +*~ diff --git a/bootstrap_cmds/APPLE_LICENSE b/bootstrap_cmds/APPLE_LICENSE new file mode 100644 index 0000000..71fe6fd --- /dev/null +++ b/bootstrap_cmds/APPLE_LICENSE @@ -0,0 +1,335 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. By +downloading or using this software, you are agreeing to be bound by the terms +of this License. If you do not or cannot agree to the terms of this License, +please do not download or use the software. + +Apple Note: In January 2007, Apple changed its corporate name from "Apple +Computer, Inc." to "Apple Inc." This change has been reflected below and +copyright years updated, but no other changes have been made to the APSL 2.0. + +1. General; Definitions. This License applies to any program or other +work which Apple Inc. ("Apple") makes publicly available and which contains a +notice placed by Apple identifying such program or work as "Original Code" and +stating that it is subject to the terms of this Apple Public Source License +version 2.0 ("License"). As used in this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the +grantor of rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to Apple and (ii) that cover subject matter contained in +the Original Code, but only to the extent necessary to use, reproduce and/or +distribute the Original Code without infringement; and (b) in the case where +You are the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to You and (ii) that cover subject matter in +Your Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or contributes to +the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the combination +of Original Code and any Modifications, and/or any respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise +make Covered Code available, directly or indirectly, to anyone other than You; +and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way +to provide a service, including but not limited to delivery of content, through +electronic communication with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change to, +the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous Modifications, +and/or any respective portions thereof. When code is released as a series of +files, a Modification is: (a) any addition to or deletion from the contents of +a file containing Covered Code; and/or (b) any new file or other representation +of computer program statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other work as +originally made available by Apple under this License, including the Source +Code of any updates or upgrades to such programs or works made available by +Apple under this License, and that has been expressly identified by Apple as +such in the header file(s) of such work; and (b) the object code compiled from +such Source Code and originally made available by Apple under this License + +1.8 "Source Code" means the human readable form of a program or other work +that is suitable for making modifications to it, including all modules it +contains, plus any associated interface definition files, scripts used to +control compilation and installation of an executable (object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising rights +under this License. For legal entities, "You" or "Your" includes any entity +which controls, is controlled by, or is under common control with, You, where +"control" means (a) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (b) ownership +of fifty percent (50%) or more of the outstanding shares or beneficial +ownership of such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms and +conditions of this License, Apple hereby grants You, effective on the date You +accept this License and download the Original Code, a world-wide, royalty-free, +non-exclusive license, to the extent of Apple's Applicable Patent Rights and +copyrights covering the Original Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, internally +distribute within Your organization, and Externally Deploy verbatim, unmodified +copies of the Original Code, for commercial or non-commercial purposes, +provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as they appear +in the Original Code, and keep intact all notices in the Original Code that +refer to this License; and + +(b) You must include a copy of this License with every copy of Source Code +of Covered Code and documentation You distribute or Externally Deploy, and You +may not offer or impose any terms on such Source Code that alter or restrict +this License or the recipients' rights hereunder, except as permitted under +Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial or +non-commercial purposes, provided that in each instance You also meet all of +these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the notice +in Exhibit A in each file of the Source Code of all Your Modifications, and +cause the modified files to carry prominent notices stating that You changed +the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make Source Code +of all Your Externally Deployed Modifications either available to those to whom +You have Externally Deployed Your Modifications, or publicly available. Source +Code of Your Externally Deployed Modifications must be released under the terms +set forth in this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve (12) +months from the date of initial External Deployment, whichever is longer. You +should preferably distribute the Source Code of Your Externally Deployed +Modifications electronically (e.g. download from a web site). + +2.3 Distribution of Executable Versions. In addition, if You Externally +Deploy Covered Code (Original Code and/or Modifications) in object code, +executable form only, You must include a prominent notice, in the code itself +as well as in related documentation, stating that Source Code of the Covered +Code is available under the terms of this License with information on how and +where to obtain such Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that although +Apple and each Contributor grants the licenses to their respective portions of +the Covered Code set forth herein, no assurances are provided by Apple or any +Contributor that the Covered Code does not infringe the patent or other +intellectual property rights of any other entity. Apple and each Contributor +disclaim any liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, You hereby assume sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow You to +distribute the Covered Code, it is Your responsibility to acquire that license +before distributing the Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the licenses +granted to You under this License, You hereby grant to any person or entity +receiving or distributing Covered Code under this License a non-exclusive, +royalty-free, perpetual, irrevocable license, under Your Applicable Patent +Rights and other intellectual property rights (other than patent) owned or +controlled by You, to use, reproduce, display, perform, modify, sublicense, +distribute and Externally Deploy Your Modifications of the same scope and +extent as Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered Code +with other code not governed by the terms of this License and distribute the +Larger Work as a single product. In each such instance, You must make sure the +requirements of this License are fulfilled for the Covered Code or any portion +thereof. + +5. Limitations on Patent License. Except as expressly stated in Section +2, no other patent rights, express or implied, are granted by Apple herein. +Modifications and/or Larger Works may require additional patent licenses from +Apple which Apple may grant in its sole discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other rights +consistent with the scope of the license granted herein ("Additional Terms") to +one or more recipients of Covered Code. However, You may do so only on Your own +behalf and as Your sole responsibility, and not on behalf of Apple or any +Contributor. You must obtain the recipient's agreement that any such Additional +Terms are offered by You alone, and You hereby agree to indemnify, defend and +hold Apple and every Contributor harmless for any liability incurred by or +claims asserted against Apple or such Contributor by reason of any such +Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new versions +of this License from time to time. Each version will be given a distinguishing +version number. Once Original Code has been published under a particular +version of this License, You may continue to use it under the terms of that +version. You may also choose to use such Original Code under the terms of any +subsequent version of this License published by Apple. No one other than Apple +has the right to modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered Code may +contain errors that could cause failures or loss of data, and may be incomplete +or contain inaccuracies. You expressly acknowledge and agree that use of the +Covered Code, or any portion thereof, is at Your sole and entire risk. THE +COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF +ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" +FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF +SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF +QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH +CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE +COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR +REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR +WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED +REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge +that the Covered Code is not intended for use in the operation of nuclear +facilities, aircraft navigation, communication systems, or air traffic control +machines in which case the failure of the Covered Code could lead to death, +personal injury, or severe physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR +YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER +UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS +LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL +PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF +LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT +APPLY TO YOU. In no event shall Apple's total liability to You for all damages +(other than as may be required by applicable law) under this License exceed the +amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime +Streaming Server" or any other trademarks, service marks, logos or trade names +belonging to Apple (collectively "Apple Marks") or to any trademark, service +mark, logo or trade name belonging to any Contributor. You agree not to use +any Apple Marks in or as part of the name of products derived from the Original +Code or to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times with +Apple's third party trademark usage guidelines which are posted at +http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, each +Contributor retains all rights, title and interest in and to any Modifications +made by such Contributor. Apple retains all rights, title and interest in and +to the Original Code and any Modifications made by or on behalf of Apple +("Apple Modifications"), and such Apple Modifications will not be automatically +subject to this License. Apple may, at its sole discretion, choose to license +such Apple Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with any +term(s) of this License and fail to cure such breach within 30 days of becoming +aware of such breach; +(b) immediately in the event of the circumstances described in Section +13.5(b); or +(c) automatically without notice from Apple if You, at any time during the +term of this License, commence an action for patent infringement against Apple; +provided that Apple did not first commence an action for patent infringement +against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately stop +any further use, reproduction, modification, sublicensing and distribution of +the Covered Code. All sublicenses to the Covered Code which have been properly +granted prior to termination shall survive any termination of this License. +Provisions which, by their nature, should remain in effect beyond the +termination of this License shall survive, including but not limited to +Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other +for compensation, indemnity or damages of any sort solely as a result of +terminating this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in the +Covered Code include only those rights customarily provided to the public as +defined in this License. This customary commercial license in technical data +and software is provided in accordance with FAR 12.211 (Technical Data) and +12.212 (Computer Software) and, for Department of Defense purchases, DFAR +252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in +Commercial Computer Software or Computer Software Documentation). Accordingly, +all U.S. Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of legal +association between or among You, Apple or any Contributor, and You will not +represent to the contrary, whether expressly, by implication, appearance or +otherwise. + +13.3 Independent Development. Nothing in this License will impair Apple's +right to acquire, license, develop, have others develop for it, market and/or +distribute technology or products that perform the same or similar functions +as, or otherwise compete with, Modifications, Larger Works, technology or +products that You may develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce +any provision of this License will not be deemed a waiver of future enforcement +of that or any other provision. Any law or regulation which provides that the +language of a contract shall be construed against the drafter will not apply to +this License. + +13.5 Severability. (a) If for any reason a court of competent jurisdiction +finds any provision of this License, or portion thereof, to be unenforceable, +that provision of the License will be enforced to the maximum extent +permissible so as to effect the economic benefits and intent of the parties, +and the remainder of this License will continue in full force and effect. (b) +Notwithstanding the foregoing, if applicable law prohibits or restricts You +from fully and/or specifically complying with Sections 2 and/or 3 or prevents +the enforceability of either of those Sections, this License will immediately +terminate and You must immediately discontinue any use of the Covered Code and +destroy all copies of it that are in your possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution between +You and Apple relating to this License shall take place in the Northern +District of California, and You and Apple hereby consent to the personal +jurisdiction of, and venue in, the state and federal courts within that +District with respect to this License. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the entire +agreement between the parties with respect to the subject matter hereof. This +License shall be governed by the laws of the United States and the State of +California, except that body of California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following clause +applies: The parties hereby confirm that they have requested that this License +and all related documents be drafted in English. Les parties ont exigé que le +présent contrat et tous les documents connexes soient rédigés en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. + +This file contains Original Code and/or Modifications of Original Code as +defined in and that are subject to the Apple Public Source License Version 2.0 +(the 'License'). You may not use this file except in compliance with the +License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS +OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT +LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the +specific language governing rights and limitations under the License." + diff --git a/bootstrap_cmds/mig.xcodeproj/project.pbxproj b/bootstrap_cmds/mig.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8173f62 --- /dev/null +++ b/bootstrap_cmds/mig.xcodeproj/project.pbxproj @@ -0,0 +1,310 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + FC2E1879149BF95600349D18 /* mig.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCAD5337149BF58700CE0B4B /* mig.1 */; }; + FC2E187A149BF95600349D18 /* migcom.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCAD533C149BF58700CE0B4B /* migcom.1 */; }; + FCAD539C149BF58700CE0B4B /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD532B149BF58700CE0B4B /* error.c */; }; + FCAD539D149BF58700CE0B4B /* global.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD532D149BF58700CE0B4B /* global.c */; }; + FCAD539F149BF58700CE0B4B /* header.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5330149BF58700CE0B4B /* header.c */; }; + FCAD53A0149BF58700CE0B4B /* lexxer.l in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5334149BF58700CE0B4B /* lexxer.l */; }; + FCAD53A2149BF58700CE0B4B /* mig.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5338149BF58700CE0B4B /* mig.c */; }; + FCAD53A3149BF58700CE0B4B /* parser.y in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5340149BF58700CE0B4B /* parser.y */; }; + FCAD53A4149BF58700CE0B4B /* routine.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5343149BF58700CE0B4B /* routine.c */; }; + FCAD53A5149BF58700CE0B4B /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5345149BF58700CE0B4B /* server.c */; }; + FCAD53A6149BF58700CE0B4B /* statement.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5346149BF58700CE0B4B /* statement.c */; }; + FCAD53A7149BF58700CE0B4B /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD5349149BF58700CE0B4B /* string.c */; }; + FCAD53A8149BF58700CE0B4B /* type.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD534A149BF58700CE0B4B /* type.c */; }; + FCAD53A9149BF58700CE0B4B /* user.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD534C149BF58700CE0B4B /* user.c */; }; + FCAD53AA149BF58700CE0B4B /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = FCAD534D149BF58700CE0B4B /* utils.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FC2DBC52149BF01800EACA9D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1/"; + dstSubfolderSpec = 0; + files = ( + FC2E1879149BF95600349D18 /* mig.1 in CopyFiles */, + FC2E187A149BF95600349D18 /* migcom.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + FC2DBC54149BF01800EACA9D /* migcom */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = migcom; sourceTree = BUILT_PRODUCTS_DIR; }; + FC2E188C149C017900349D18 /* install-mig.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-mig.sh"; sourceTree = ""; }; + FCAD532A149BF58700CE0B4B /* alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alloc.h; sourceTree = ""; }; + FCAD532B149BF58700CE0B4B /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = ""; }; + FCAD532C149BF58700CE0B4B /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; + FCAD532D149BF58700CE0B4B /* global.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = global.c; sourceTree = ""; }; + FCAD532E149BF58700CE0B4B /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = global.h; sourceTree = ""; }; + FCAD532F149BF58700CE0B4B /* handler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = handler.c; sourceTree = ""; }; + FCAD5330149BF58700CE0B4B /* header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = header.c; sourceTree = ""; }; + FCAD5333149BF58700CE0B4B /* lexxer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lexxer.h; sourceTree = ""; }; + FCAD5334149BF58700CE0B4B /* lexxer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = lexxer.l; sourceTree = ""; }; + FCAD5337149BF58700CE0B4B /* mig.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mig.1; sourceTree = ""; }; + FCAD5338149BF58700CE0B4B /* mig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mig.c; sourceTree = ""; }; + FCAD5339149BF58700CE0B4B /* mig.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = mig.sh; sourceTree = ""; }; + FCAD533A149BF58700CE0B4B /* mig_errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mig_errors.h; sourceTree = ""; }; + FCAD533B149BF58700CE0B4B /* mig_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mig_machine.h; sourceTree = ""; }; + FCAD533C149BF58700CE0B4B /* migcom.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = migcom.1; sourceTree = ""; }; + FCAD5340149BF58700CE0B4B /* parser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = parser.y; sourceTree = ""; }; + FCAD5343149BF58700CE0B4B /* routine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = routine.c; sourceTree = ""; }; + FCAD5344149BF58700CE0B4B /* routine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = routine.h; sourceTree = ""; }; + FCAD5345149BF58700CE0B4B /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + FCAD5346149BF58700CE0B4B /* statement.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = statement.c; sourceTree = ""; }; + FCAD5347149BF58700CE0B4B /* statement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = statement.h; sourceTree = ""; }; + FCAD5348149BF58700CE0B4B /* strdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strdefs.h; sourceTree = ""; }; + FCAD5349149BF58700CE0B4B /* string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = string.c; sourceTree = ""; }; + FCAD534A149BF58700CE0B4B /* type.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = type.c; sourceTree = ""; }; + FCAD534B149BF58700CE0B4B /* type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = type.h; sourceTree = ""; }; + FCAD534C149BF58700CE0B4B /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + FCAD534D149BF58700CE0B4B /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; }; + FCAD534E149BF58700CE0B4B /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + FCAD534F149BF58700CE0B4B /* write.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = write.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FC2DBC51149BF01800EACA9D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FC2DBC49149BF01800EACA9D = { + isa = PBXGroup; + children = ( + FCAD5329149BF58700CE0B4B /* migcom */, + FC2E188B149C017900349D18 /* xcodescripts */, + FC2DBC55149BF01800EACA9D /* Products */, + ); + sourceTree = ""; + }; + FC2DBC55149BF01800EACA9D /* Products */ = { + isa = PBXGroup; + children = ( + FC2DBC54149BF01800EACA9D /* migcom */, + ); + name = Products; + sourceTree = ""; + }; + FC2E188B149C017900349D18 /* xcodescripts */ = { + isa = PBXGroup; + children = ( + FC2E188C149C017900349D18 /* install-mig.sh */, + ); + path = xcodescripts; + sourceTree = ""; + }; + FCAD5329149BF58700CE0B4B /* migcom */ = { + isa = PBXGroup; + children = ( + FCAD532A149BF58700CE0B4B /* alloc.h */, + FCAD532B149BF58700CE0B4B /* error.c */, + FCAD532C149BF58700CE0B4B /* error.h */, + FCAD532D149BF58700CE0B4B /* global.c */, + FCAD532E149BF58700CE0B4B /* global.h */, + FCAD532F149BF58700CE0B4B /* handler.c */, + FCAD5330149BF58700CE0B4B /* header.c */, + FCAD5333149BF58700CE0B4B /* lexxer.h */, + FCAD5334149BF58700CE0B4B /* lexxer.l */, + FCAD5337149BF58700CE0B4B /* mig.1 */, + FCAD5338149BF58700CE0B4B /* mig.c */, + FCAD5339149BF58700CE0B4B /* mig.sh */, + FCAD533A149BF58700CE0B4B /* mig_errors.h */, + FCAD533B149BF58700CE0B4B /* mig_machine.h */, + FCAD533C149BF58700CE0B4B /* migcom.1 */, + FCAD5340149BF58700CE0B4B /* parser.y */, + FCAD5343149BF58700CE0B4B /* routine.c */, + FCAD5344149BF58700CE0B4B /* routine.h */, + FCAD5345149BF58700CE0B4B /* server.c */, + FCAD5346149BF58700CE0B4B /* statement.c */, + FCAD5347149BF58700CE0B4B /* statement.h */, + FCAD5348149BF58700CE0B4B /* strdefs.h */, + FCAD5349149BF58700CE0B4B /* string.c */, + FCAD534A149BF58700CE0B4B /* type.c */, + FCAD534B149BF58700CE0B4B /* type.h */, + FCAD534C149BF58700CE0B4B /* user.c */, + FCAD534D149BF58700CE0B4B /* utils.c */, + FCAD534E149BF58700CE0B4B /* utils.h */, + FCAD534F149BF58700CE0B4B /* write.h */, + ); + name = migcom; + path = migcom.tproj; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FC2DBC53149BF01800EACA9D /* migcom */ = { + isa = PBXNativeTarget; + buildConfigurationList = FC2DBC5E149BF01800EACA9D /* Build configuration list for PBXNativeTarget "migcom" */; + buildPhases = ( + FC2DBC50149BF01800EACA9D /* Sources */, + FC2DBC51149BF01800EACA9D /* Frameworks */, + FC2DBC52149BF01800EACA9D /* CopyFiles */, + FC2E1884149BFF0900349D18 /* Run Script */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = migcom; + productName = mig; + productReference = FC2DBC54149BF01800EACA9D /* migcom */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FC2DBC4B149BF01800EACA9D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = "Apple Inc."; + }; + buildConfigurationList = FC2DBC4E149BF01800EACA9D /* Build configuration list for PBXProject "mig" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FC2DBC49149BF01800EACA9D; + productRefGroup = FC2DBC55149BF01800EACA9D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FC2DBC53149BF01800EACA9D /* migcom */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + FC2E1884149BFF0900349D18 /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-mig.sh"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FC2DBC50149BF01800EACA9D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FCAD53A3149BF58700CE0B4B /* parser.y in Sources */, + FCAD53A0149BF58700CE0B4B /* lexxer.l in Sources */, + FCAD539C149BF58700CE0B4B /* error.c in Sources */, + FCAD539D149BF58700CE0B4B /* global.c in Sources */, + FCAD539F149BF58700CE0B4B /* header.c in Sources */, + FCAD53A2149BF58700CE0B4B /* mig.c in Sources */, + FCAD53A4149BF58700CE0B4B /* routine.c in Sources */, + FCAD53A5149BF58700CE0B4B /* server.c in Sources */, + FCAD53A6149BF58700CE0B4B /* statement.c in Sources */, + FCAD53A7149BF58700CE0B4B /* string.c in Sources */, + FCAD53A8149BF58700CE0B4B /* type.c in Sources */, + FCAD53A9149BF58700CE0B4B /* user.c in Sources */, + FCAD53AA149BF58700CE0B4B /* utils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + FC2DBC5D149BF01800EACA9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = macosx.internal; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = __; + WARNING_CFLAGS = "-Wall"; + }; + name = Release; + }; + FC2DBC60149BF01800EACA9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + GCC_PREPROCESSOR_DEFINITIONS = "MIG_VERSION=\\\"$(RC_ProjectNameAndSourceVersion)\\\""; + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/libexec"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FC2DBC4E149BF01800EACA9D /* Build configuration list for PBXProject "mig" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FC2DBC5D149BF01800EACA9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FC2DBC5E149BF01800EACA9D /* Build configuration list for PBXNativeTarget "migcom" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FC2DBC60149BF01800EACA9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FC2DBC4B149BF01800EACA9D /* Project object */; +} diff --git a/bootstrap_cmds/migcom.tproj/alloc.h b/bootstrap_cmds/migcom.tproj/alloc.h new file mode 100644 index 0000000..87b9b5f --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/alloc.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _ALLOC_H +#define _ALLOC_H + +#include + +#endif /* _ALLOC_H */ diff --git a/bootstrap_cmds/migcom.tproj/error.c b/bootstrap_cmds/migcom.tproj/error.c new file mode 100644 index 0000000..37bcae3 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/error.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include +#include + +#include "global.h" +#include "error.h" + +extern int lineno; +extern char *yyinname; + +static char *program; +__private_extern__ +int mig_errors = 0; + +/*ARGSUSED*/ +/*VARARGS1*/ +void +fatal(char *format, ...) +{ + va_list pvar; + va_start(pvar, format); + fprintf(stderr, "%s: fatal: \"%s\", line %d: ", program, yyinname, lineno-1); + (void) vfprintf(stderr, format, pvar); + fprintf(stderr, "\n"); + va_end(pvar); + exit(1); +} + +__private_extern__ +/*ARGSUSED*/ +/*VARARGS1*/ +void +warn(char *format, ...) +{ + va_list pvar; + va_start(pvar, format); + if (!BeQuiet && (mig_errors == 0)) { + fprintf(stderr, "\"%s\", line %d: warning: ", yyinname, lineno-1); + (void) vfprintf(stderr, format, pvar); + fprintf(stderr, "\n"); + } + va_end(pvar); +} + +/*ARGSUSED*/ +/*VARARGS1*/ +void +error(char *format, ...) +{ + va_list pvar; + va_start(pvar, format); + fprintf(stderr, "\"%s\", line %d: ", yyinname, lineno-1); + (void) vfprintf(stderr, format, pvar); + fprintf(stderr, "\n"); + va_end(pvar); + mig_errors++; +} + +void +set_program_name(char *name) +{ + program = name; +} diff --git a/bootstrap_cmds/migcom.tproj/error.h b/bootstrap_cmds/migcom.tproj/error.h new file mode 100644 index 0000000..9ffd599 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/error.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _ERROR_H +#define _ERROR_H + +#include + +extern void fatal(char *format, ...); +extern void warn(char *format, ...); +extern void error(char *format, ...); + +extern int mig_errors; +extern void set_program_name(char *name); + +#endif /* _ERROR_H */ diff --git a/bootstrap_cmds/migcom.tproj/global.c b/bootstrap_cmds/migcom.tproj/global.c new file mode 100644 index 0000000..15c26f5 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/global.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "strdefs.h" +#include "global.h" +#include "error.h" +#include "mig_machine.h" + +boolean_t PrintVersion = FALSE; +boolean_t BeQuiet = FALSE; +boolean_t BeVerbose = FALSE; +boolean_t UseMsgRPC = TRUE; +boolean_t GenSymTab = FALSE; +boolean_t UseEventLogger = FALSE; +boolean_t BeLint = FALSE; +boolean_t BeAnsiC = TRUE; +boolean_t CheckNDR = FALSE; +boolean_t PackMsg = PACK_MESSAGES; +boolean_t UseSplitHeaders = FALSE; +boolean_t ShortCircuit = FALSE; +boolean_t UseRPCTrap = FALSE; +boolean_t TestRPCTrap= FALSE; +boolean_t IsVoucherCodeAllowed = TRUE; + +boolean_t IsKernelUser = FALSE; +boolean_t IsKernelServer = FALSE; +boolean_t UseSpecialReplyPort = FALSE; +boolean_t HasUseSpecialReplyPort = FALSE; +boolean_t HasConsumeOnSendError = FALSE; +u_int ConsumeOnSendError = 0; + +string_t RCSId = strNULL; + +string_t SubsystemName = strNULL; +u_int SubsystemBase = 0; + +string_t MsgOption = strNULL; +string_t WaitTime = strNULL; +string_t SendTime = strNULL; +string_t ErrorProc = "MsgError"; +string_t ServerPrefix = ""; +string_t UserPrefix = ""; +string_t ServerDemux = strNULL; +string_t ServerImpl = strNULL; +string_t ServerSubsys = strNULL; +int MaxMessSizeOnStack = -1; /* by default, always on stack */ +int UserTypeLimit = -1; /* by default, assume unlimited size. */ + +string_t yyinname; + +char NewCDecl[] = "(defined(__STDC__) || defined(c_plusplus))"; +char LintLib[] = "defined(LINTLIBRARY)"; + +void +init_global() +{ + yyinname = strmake(""); +} + +string_t UserFilePrefix = strNULL; +string_t UserHeaderFileName = strNULL; +string_t ServerHeaderFileName = strNULL; +string_t InternalHeaderFileName = strNULL; +string_t DefinesHeaderFileName = strNULL; +string_t UserFileName = strNULL; +string_t ServerFileName = strNULL; +string_t GenerationDate = strNULL; + +void +more_global() +{ + if (SubsystemName == strNULL) + fatal("no SubSystem declaration"); + + if (UserHeaderFileName == strNULL) + UserHeaderFileName = strconcat(SubsystemName, ".h"); + else if (streql(UserHeaderFileName, "/dev/null")) + UserHeaderFileName = strNULL; + + if (UserFileName == strNULL) + UserFileName = strconcat(SubsystemName, "User.c"); + else if (streql(UserFileName, "/dev/null")) + UserFileName = strNULL; + + if (ServerFileName == strNULL) + ServerFileName = strconcat(SubsystemName, "Server.c"); + else if (streql(ServerFileName, "/dev/null")) + ServerFileName = strNULL; + + if (ServerDemux == strNULL) + ServerDemux = strconcat(SubsystemName, "_server"); + + if (ServerImpl == strNULL) + ServerImpl = strconcat(SubsystemName, "_impl"); + + if (ServerSubsys == strNULL) { + if (ServerPrefix != strNULL) + ServerSubsys = strconcat(ServerPrefix, SubsystemName); + else + ServerSubsys = SubsystemName; + ServerSubsys = strconcat(ServerSubsys, "_subsystem"); + } + if (HasUseSpecialReplyPort && !BeAnsiC) { + fatal("Cannot use UseSpecialReplyPort in non ANSI mode\n"); + } +} diff --git a/bootstrap_cmds/migcom.tproj/global.h b/bootstrap_cmds/migcom.tproj/global.h new file mode 100644 index 0000000..39a133b --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/global.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _GLOBAL_H +#define _GLOBAL_H + +#include "type.h" + +extern boolean_t PrintVersion; /* print bootstrap_cmds project version and exit */ +extern boolean_t BeQuiet; /* no warning messages */ +extern boolean_t BeVerbose; /* summarize types, routines */ +extern boolean_t BeDebug; /* enters in the debug mode */ +extern boolean_t UseMsgRPC; +extern boolean_t GenSymTab; +extern boolean_t UseEventLogger; +extern boolean_t BeLint; +extern boolean_t BeAnsiC; +extern boolean_t CheckNDR; +extern boolean_t PackMsg; +extern boolean_t UseSplitHeaders; +extern boolean_t ShortCircuit; +extern boolean_t UseRPCTrap; +extern boolean_t TestRPCTrap; +extern boolean_t IsVoucherCodeAllowed; + +extern boolean_t IsKernelUser; +extern boolean_t IsKernelServer; +extern boolean_t UseSpecialReplyPort; +extern boolean_t HasUseSpecialReplyPort; /* whether UseSpecialReplyPort has ever been set to TRUE */ +extern boolean_t HasConsumeOnSendError; /* whether ConsumeOnSendError has ever been set */ +extern u_int ConsumeOnSendError; + +extern string_t RCSId; + +extern string_t SubsystemName; +extern u_int SubsystemBase; + +extern string_t MsgOption; +extern string_t WaitTime; +extern string_t SendTime; +extern string_t ErrorProc; +extern string_t ServerPrefix; +extern string_t UserPrefix; +extern string_t ServerDemux; +extern string_t ServerImpl; +extern string_t ServerSubsys; +extern int MaxMessSizeOnStack; +extern int UserTypeLimit; + +extern int yylineno; +extern string_t yyinname; + +extern void init_global(void); + +extern string_t UserFilePrefix; +extern string_t UserHeaderFileName; +extern string_t ServerHeaderFileName; +extern string_t InternalHeaderFileName; +extern string_t DefinesHeaderFileName; +extern string_t UserFileName; +extern string_t ServerFileName; + +extern void more_global(void); + +extern char NewCDecl[]; +extern char LintLib[]; + +#endif /* _GLOBAL_H */ diff --git a/bootstrap_cmds/migcom.tproj/handler.c b/bootstrap_cmds/migcom.tproj/handler.c new file mode 100644 index 0000000..b5156aa --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/handler.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/******************************************************** + * Abstract: + * routines to write pieces of the Handler module. + * exports WriteHandler which directs the writing of + * the Handler module + * + * + * $Header: /Users/Shared/bootstrap_cmds/bootstrap_cmds/migcom.tproj/handler.c,v 1.2 2005/02/06 07:28:59 lindak Exp $ + * + * HISTORY + * 03-Jul-97 Daniel Wade (danielw) at Apple + * Generated code is now ANSI C compliant + * + * 10-Sep-91 Gregg Kellogg (gk) at NeXT + * Created. + *******************************************************/ + +#include +#include "write.h" +#include "utils.h" +#include "global.h" + +static void +WriteIncludes(FILE *file) +{ + fprintf(file, "#define EXPORT_BOOLEAN\n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + if (IsCamelot) { + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + } + fprintf(file, "#include \"%s\"\n", ServerHeaderFileName); + fprintf(file, "\n"); +} + +static void +WriteGlobalDecls(FILE *file) +{ + fprintf(file, "#define novalue void\n"); + fprintf(file, "\n"); + + if (RCSId != strNULL) + WriteRCSDecl(file, strconcat(SubsystemName, "_handler"), RCSId); + + /* Used for locations in the request message, *not* reply message. + Reply message locations aren't dependent on IsKernel. */ + + if (IsKernel) + { + fprintf(file, "#define msg_request_port\tmsg_remote_port\n"); + fprintf(file, "#define msg_reply_port\t\tmsg_local_port\n"); + } + else + { + fprintf(file, "#define msg_request_port\tmsg_local_port\n"); + fprintf(file, "#define msg_reply_port\t\tmsg_remote_port\n"); + } +} + +static void +WriteProlog(FILE *file) +{ + fprintf(file, "/* Module %s */\n", SubsystemName); + fprintf(file, "\n"); + + WriteIncludes(file); + WriteBogusDefines(file); + WriteGlobalDecls(file); +} + + +static void +WriteSymTabEntries(FILE *file statement_t *stats) +{ + statement_t *stat; + u_int current = 0; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + int num = stat->stRoutine->rtNumber; + char *name = stat->stRoutine->rtName; + while (++current <= num) + fprintf(file,"\t\t\t{ \"\", 0, 0 },\n"); + fprintf(file, "\t{ \"%s\", %d, _X%s },\n", + name, + SubsystemBase + current - 1, + name); + } + while (++current <= rtNumber) + fprintf(file,"\t{ \"\", 0, 0 },\n"); +} + +static void +WriteArrayEntries(FILE *file, statement_t *stats) +{ + u_int current = 0; + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) + { + routine_t *rt = stat->stRoutine; + + while (current++ < rt->rtNumber) + fprintf(file, "\t\t\t0,\n"); + fprintf(file, "\t\t\t_X%s,\n", rt->rtName); + } + while (current++ < rtNumber) + fprintf(file, "\t\t\t0,\n"); +} + +static void +WriteEpilog(FILE *file, statement_t *stats) +{ + statement_t *stat; + u_int MaxReply = 0; + + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind != skRoutine) + continue; + if (stat->stRoutine->rtMaxReplySize > MaxReply) + MaxReply = stat->stRoutine->rtMaxReplySize; + } + + fprintf(file, "\n"); + + fprintf(file, "kern_return_t %s (\n", ServerProcName); + fprintf(file, "\tmsg_header_t *InHeadP,\n\t%s_t *%s)\n", SubsystemName, SubsystemName); + + fprintf(file, "{\n"); + fprintf(file, "\tchar OutBuf[%d];\n", MaxReply); + fprintf(file, "\tmsg_header_t *InP = InHeadP;\n"); + + if (IsCamelot) + fprintf(file, "\tcamelot_death_pill_t *OutP = (camelot_death_pill_t *) OutBuf;\n"); + else + fprintf(file, "\tdeath_pill_t *OutP = (death_pill_t *) OutBuf;\n"); + + fprintf(file, "\n"); + + WriteStaticDecl(file, itRetCodeType, itRetCodeType->itDeallocate, itRetCodeType->itLongForm, "RetCodeType"); + fprintf(file, "\n"); + + if (IsCamelot) + { + WriteStaticDecl(file, itDummyType, itDummyType->itDeallocate, itDummyType->itLongForm, "DummyType"); + fprintf(file, "\n"); + WriteStaticDecl(file, itTidType, itTidType->itDeallocate, itTidType->itLongForm, "TidType"); + fprintf(file, "\n"); + } + + fprintf(file, "\tOutP->Head.msg_simple = TRUE;\n"); + fprintf(file, "\tOutP->Head.msg_size = (mach_msg_size_t)sizeof(*OutP);\n"); + fprintf(file, "\tOutP->Head.msg_type = InP->msg_type;\n"); + fprintf(file, "\tOutP->Head.msg_local_port = PORT_NULL;\n"); + fprintf(file, "\tOutP->Head.msg_remote_port = InP->msg_reply_port;\n"); + fprintf(file, "\tOutP->Head.msg_id = InP->msg_id + 100;\n"); + fprintf(file, "\n"); + WritePackMsgType(file, itRetCodeType, itRetCodeType->itDeallocate, itRetCodeType->itLongForm, "OutP->RetCodeType", "RetCodeType"); + fprintf(file, "\tOutP->RetCode = MIG_BAD_ID;\n"); + fprintf(file, "\n"); + + if (IsCamelot) + { + WritePackMsgType(file, itDummyType, itDummyType->itDeallocate, itDummyType->itLongForm, "OutP->DummyType", "DummyType"); + fprintf(file, "\t/* dummy doesn't need a value */\n"); + fprintf(file, "\n"); + WritePackMsgType(file, itTidType, itTidType->itDeallocate, itTidType->itLongForm, "OutP->TidType", "TidType"); + fprintf(file, "\tOutP->Tid = ((camelot_death_pill_t *)InP)->Tid;\n"); + fprintf(file, "\n"); + } + + fprintf(file, "\tif ((InP->msg_id > %d) || (InP->msg_id < %d))\n", SubsystemBase + rtNumber - 1, SubsystemBase); + fprintf(file, "\t\treturn OutP->RetCode;\n"); + fprintf(file, "\telse {\n"); + fprintf(file, "\t\ttypedef novalue (*SERVER_STUB_PROC) (\n"); + fprintf(file, "\t\t\tmsg_header_t *,\n" + "\t\t\tmsg_header_t *,\n" + "\t\t\t%s_t *);\n", SubsystemName); + fprintf(file, "\t\tstatic const SERVER_STUB_PROC routines[] = {\n"); + + WriteArrayEntries(file, stats); + + fprintf(file, "\t\t};\n"); + fprintf(file, "\n"); + + /* Call appropriate routine */ + fprintf(file, "\t\tif (routines[InP->msg_id - %d])\n", SubsystemBase); + fprintf(file, "\t\t\t(routines[InP->msg_id - %d]) (\n" + "\t\t\t\tInP, &OutP->Head, %s);\n", + SubsystemBase, SubsystemName); + fprintf(file, "\t\t else\n"); + fprintf(file, "\t\t\treturn MIG_BAD_ID;\n"); + + fprintf(file, "\t}\n"); + + fprintf(file, "\tif (OutP->RetCode == MIG_NO_REPLY)\n"); + fprintf(file, "\t\treturn KERN_SUCCESS;\n"); + fprintf(file, "\treturn msg_send(&OutP->Head,\n"); + fprintf(file, "\t\t%s->timeout >= 0 ? SEND_TIMEOUT : MSG_OPTION_NONE,\n", SubsystemName); + fprintf(file, "\t\t%s->timeout);\n", SubsystemName); + fprintf(file, "}\n"); + + /* symtab */ + + if (GenSymTab) { + fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName); + WriteSymTabEntries(file,stats); + fprintf(file,"};\n"); + fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase); + fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber); + } +} + +/* + * Returns the return type of the server-side work function. + * Suitable for "extern %s serverfunc()". + */ +static char * +HandlerSideType(routine_t *rt) +{ + if (rt->rtServerReturn == argNULL) + return "void"; + else + return rt->rtServerReturn->argType->itTransType; +} + +static void +WriteLocalVarDecl(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + if (it->itInLine && it->itVarArray) + { + ipc_type_t *btype = it->itElement; + + fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itNumber/btype->itNumber); + } + else + fprintf(file, "\t%s %s", it->itTransType, arg->argVarName); +} + +static void +_WriteHandlerVarDecl(FILE *file, argument_t *arg) +{ + fprintf(file, "%s %s%s", arg->argType->itTransType, argByReferenceServer(arg) ? "*" : "", arg->argVarName); +} + +/* + * Writes the local variable declarations which are always + * present: InP, OutP, the server-side work function. + */ +static void +WriteVarDecls(FILE *file, routine_t *rt) +{ + int i; + + fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n"); + for (i = 1; i <= rt->rtMaxRequestPos; i++) + fprintf(file, "\tRequest *In%dP;\n", i); + fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n"); + fprintf(file, "\n"); + + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tboolean_t msg_simple;\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); + + fprintf(file, "\tunsigned int msg_size;\n"); + + /* if either request or reply is variable, we need msg_size_delta */ + if ((rt->rtNumRequestVar > 0) || (rt->rtNumReplyVar > 0)) + fprintf(file, "\tunsigned int msg_size_delta;\n"); + + fprintf(file, "\n"); +} + +static void +WriteMsgError(FILE *file, argument_t *arg, char *error) +{ + if (arg == argNULL) + fprintf(file, "\t\t{ OutP->RetCode = %s; return; }\n", error); + else { + fprintf(file, "\t\t{ OutP->RetCode = %s; goto punt%d; }\n", error, arg->argPuntNum); + fprintf(file, "#define\tlabel_punt%d\n", arg->argPuntNum); + } +} + +static void +WriteReplyInit(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + fprintf(file, "\tmsg_size = %d;\t\n", rt->rtReplySize); + if (rt->rtNumReplyVar > 0) + fprintf(file, "\t/* Maximum reply size %d */\n", rt->rtMaxReplySize); +} + +static void +WriteReplyHead(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + if (rt->rtMaxReplyPos > 0) + fprintf(file, "\tOutP = (Reply *) OutHeadP;\n"); + + fprintf(file, "\tOutP->Head.msg_simple = %s;\n", strbool(rt->rtSimpleSendReply)); + fprintf(file, "\tOutP->Head.msg_size = msg_size;\n"); +} + +static void +WriteCheckHead(FILE *file, routine_t *rt) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tmsg_size = In0P->Head.msg_size;\n"); + fprintf(file, "\tmsg_simple = In0P->Head.msg_simple;\n"); + + if (rt->rtNumRequestVar > 0) { + fprintf(file, "\tif ((msg_size < %d)", rt->rtRequestSize); + fprintf(file, " || (msg_size > %d)", rt->rtMaxRequestSize); + } + else + fprintf(file, "\tif ((msg_size != %d)", rt->rtRequestSize); + if (rt->rtSimpleCheckRequest) + fprintf(file, " || (msg_simple != %s)", strbool(rt->rtSimpleReceiveRequest)); + fprintf(file, ")\n"); + WriteMsgError(file, argNULL, "MIG_BAD_ARGUMENTS"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); +} + +static void +WriteTypeCheck(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + routine_t *rt = arg->argRoutine; + + fprintf(file, "#if\t__MigTypeCheck\n"); + if (akCheck(arg->argKind, akbQuickCheck)) + { + fprintf(file, "#if\tUseStaticMsgType\n"); + fprintf(file, "\tif (* (int *) &In%dP->%s != * (int *) &%sCheck)\n", arg->argRequestPos, arg->argTTName, arg->argVarName); + fprintf(file, "#else\t/* UseStaticMsgType */\n"); + } + fprintf(file, "\tif ((In%dP->%s%s.msg_type_inline != %s) ||\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? ".msg_type_header" : "", strbool(it->itInLine)); + fprintf(file, "\t (In%dP->%s%s.msg_type_longform != %s) ||\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? ".msg_type_header" : "", strbool(arg->argLongForm)); + if (it->itOutName == MSG_TYPE_POLYMORPHIC) + { + if (!rt->rtSimpleCheckRequest) + fprintf(file, "\t (MSG_TYPE_PORT_ANY(In%dP->%s.msg_type_%sname) && msg_simple) ||\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? "long_" : ""); + } + else + fprintf(file, "\t (In%dP->%s.msg_type_%sname != %s) ||\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? "long_" : "", it->itOutNameStr); + if (!it->itVarArray) + fprintf(file, "\t (In%dP->%s.msg_type_%snumber != %d) ||\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? "long_" : "", it->itNumber); + fprintf(file, "\t (In%dP->%s.msg_type_%ssize != %d))\n", arg->argRequestPos, arg->argTTName, arg->argLongForm ? "long_" : "", it->itSize); + if (akCheck(arg->argKind, akbQuickCheck)) + fprintf(file, "#endif\t/* UseStaticMsgType */\n"); + WriteMsgError(file, arg, "MIG_BAD_ARGUMENTS"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); +} + +static void +WriteCheckMsgSize(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + ipc_type_t *btype = arg->argType->itElement; + argument_t *count = arg->argCount; + boolean_t NoMoreArgs, LastVarArg; + + /* If there aren't any more In args after this, then + msg_size_delta value will only get used by TypeCheck code, + so put the assignment under the TypeCheck conditional. */ + + NoMoreArgs = arg->argRequestPos == rt->rtMaxRequestPos; + + /* If there aren't any more variable-sized arguments after this, + then we must check for exact msg-size and we don't need + to update msg_size. */ + + LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar; + + if (NoMoreArgs) + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* calculate the actual size in bytes of the data field. note + that this quantity must be a multiple of four. hence, if + the base type size isn't a multiple of four, we have to + round up. note also that btype->itNumber must + divide btype->itTypeSize (see itCalculateSizeInfo). */ + + if (btype->itTypeSize % 4 != 0) + fprintf(file, "\tmsg_size_delta = (%d * In%dP->%s + 3) & ~3;\n", btype->itTypeSize/btype->itNumber, arg->argRequestPos, count->argMsgField); + else + fprintf(file, "\tmsg_size_delta = %d * In%dP->%s;\n", btype->itTypeSize/btype->itNumber, arg->argRequestPos, count->argMsgField); + + if (!NoMoreArgs) + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* Don't decrement msg_size until we've checked it won't underflow. */ + + if (LastVarArg) + fprintf(file, "\tif (msg_size != %d + msg_size_delta)\n", rt->rtRequestSize); + else + fprintf(file, "\tif (msg_size < %d + msg_size_delta)\n", rt->rtRequestSize); + WriteMsgError(file, arg, "MIG_BAD_ARGUMENTS"); + + if (!LastVarArg) + fprintf(file, "\tmsg_size -= msg_size_delta;\n"); + + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); +} + +static void +WriteExtractArgValue(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + if (arg->argMultiplier > 1) + WriteCopyType(file, it, FALSE, "%s /* %d %s %d */", "/* %s */ In%dP->%s / %d", arg->argVarName, arg->argRequestPos, arg->argMsgField, arg->argMultiplier); + else if (it->itInTrans != strNULL) + WriteCopyType(file, it, FALSE, "%s /* %s %d %s */", "/* %s */ %s(In%dP->%s)", arg->argVarName, it->itInTrans, arg->argRequestPos, arg->argMsgField); + else + WriteCopyType(file, it, FALSE, "%s /* %d %s */", "/* %s */ In%dP->%s", arg->argVarName, arg->argRequestPos, arg->argMsgField); + fprintf(file, "\n"); +} + +static void +WriteInitializeCount(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argParent->argType; + ipc_type_t *btype = ptype->itElement; + + /* + * Initialize 'count' argument for variable-length inline OUT parameter + * with maximum allowed number of elements. + */ + + fprintf(file, "\t%s = %d;\n", arg->argVarName, ptype->itNumber/btype->itNumber); + fprintf(file, "\n"); +} + +static void +WriteExtractArg(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbRequest)) + WriteTypeCheck(file, arg); + + if (akCheckAll(arg->argKind, akbVariable|akbRequest)) + WriteCheckMsgSize(file, arg); + + if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) + WriteExtractArgValue(file, arg); + + if ((akIdent(arg->argKind) == akeCount) && akCheck(arg->argKind, akbReturnSnd)) { + ipc_type_t *ptype = arg->argParent->argType; + + if (ptype->itInLine && ptype->itVarArray) + WriteInitializeCount(file, arg); + } + + /* This assumes that the count argument directly follows the + associated variable-sized argument and any other implicit + arguments it may have. */ + + if ((akIdent(arg->argKind) == akeCount) && akCheck(arg->argKind, akbSendRcv) && (arg->argRequestPos < arg->argRoutine->rtMaxRequestPos)) { + ipc_type_t *ptype = arg->argParent->argType; + + if (ptype->itInLine && ptype->itVarArray) { + fprintf(file, "\tIn%dP = (Request *) ((char *) In%dP + msg_size_delta - %d);\n", arg->argRequestPos+1, arg->argRequestPos, ptype->itTypeSize + ptype->itPadSize); + fprintf(file, "\n"); + } + } +} + +static void +WriteHandlerCallArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + boolean_t NeedClose = FALSE; + + if (argByReferenceServer(arg)) + fprintf(file, "&"); + + if ((it->itInTrans != strNULL) && akCheck(arg->argKind, akbSendRcv) && !akCheck(arg->argKind, akbVarNeeded)) { + fprintf(file, "%s(", it->itInTrans); + NeedClose = TRUE; + } + + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "%s", arg->argVarName); + else if (akCheck(arg->argKind, akbSendRcv)) + fprintf(file, "In%dP->%s", arg->argRequestPos, arg->argMsgField); + else + fprintf(file, "OutP->%s", arg->argMsgField); + + if (NeedClose) + fprintf(file, ")"); + + if (!argByReferenceServer(arg) && (arg->argMultiplier > 1)) + fprintf(file, " / %d", arg->argMultiplier); +} + +static void +WriteDestroyArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#ifdef\tlabel_punt%d\n", arg->argPuntNum+1); + fprintf(file, "#undef\tlabel_punt%d\n", arg->argPuntNum+1); + fprintf(file, "punt%d:\n", arg->argPuntNum+1); + fprintf(file, "#endif\t/* label_punt%d */\n", arg->argPuntNum+1); + + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName); + else + fprintf(file, "\t%s(In%dP->%s);\n", it->itDestructor, arg->argRequestPos, arg->argMsgField); +} + +static void +WriteHandlerCall(FILE *file, routine_t *rt) +{ + boolean_t NeedClose = FALSE; + + fprintf(file, "\tif (%s->%s == 0)\n", SubsystemName, rt->rtName); + WriteMsgError(file, argNULL, "MIG_BAD_ID"); + + fprintf(file, "\t"); + if (rt->rtServerReturn != argNULL) { + argument_t *arg = rt->rtServerReturn; + ipc_type_t *it = arg->argType; + + if (rt->rtOneWay) + fprintf(file, "(void) "); + else + fprintf(file, "OutP->%s = ", arg->argMsgField); + if (it->itOutTrans != strNULL) { + fprintf(file, "%s(", it->itOutTrans); + NeedClose = TRUE; + } + } + fprintf(file, "(*%s->%s)(%s->arg", SubsystemName, rt->rtName, SubsystemName); + WriteListSkipFirst(file, rt->rtArgs, WriteHandlerCallArg, akbServerArg, + ", ", ""); + if (NeedClose) + fprintf(file, ")"); + fprintf(file, ");\n"); +} + +static void +WriteGetReturnValue(FILE *file, routine_t *rt) +{ + fprintf(file, "\t" "OutP->%s = %s;\n", rt->rtRetCode->argMsgField, rt->rtOneWay ? "MIG_NO_REPLY" : "KERN_SUCCESS"); +} + +static void +WriteCheckReturnValue(FILE *file, routine_t *rt) +{ + fprintf(file, "\tif (OutP->%s != KERN_SUCCESS)\n", rt->rtRetCode->argMsgField); + fprintf(file, "\t\treturn;\n"); +} + +static void +WritePackArgType(FILE *file, argument_t *arg) +{ + fprintf(file, "\n"); + + WritePackMsgType(file, arg->argType, arg->argDeallocate, arg->argLongForm, "OutP->%s", "%s", arg->argTTName); +} + +static void +WritePackArgValue(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "\n"); + + if (it->itInLine && it->itVarArray) { + argument_t *count = arg->argCount; + ipc_type_t *btype = it->itElement; + + /* Note btype->itNumber == count->argMultiplier */ + + fprintf(file, "\tbcopy((char *) %s, (char *) OutP->%s, ", arg->argVarName, arg->argMsgField); + fprintf(file, "%d * %s);\n", btype->itTypeSize, count->argVarName); + } + else if (arg->argMultiplier > 1) + WriteCopyType(file, it, TRUE, "OutP->%s /* %d %s */", "/* %s */ %d * %s", arg->argMsgField, arg->argMultiplier, arg->argVarName); + else if (it->itOutTrans != strNULL) + WriteCopyType(file, it, TRUE, "OutP->%s /* %s %s */", "/* %s */ %s(%s)", arg->argMsgField, it->itOutTrans, arg->argVarName); + else + WriteCopyType(file, it, TRUE, "OutP->%s /* %s */", "/* %s */ %s", arg->argMsgField, arg->argVarName); +} + +static void +WriteCopyArgValue(FILE *file, argument_t *arg) +{ + fprintf(file, "\n"); + WriteCopyType(file, arg->argType, TRUE, "/* %d */ OutP->%s", "In%dP->%s", arg->argRequestPos, arg->argMsgField); +} + +static void +WriteAdjustMsgSize(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argParent->argType; + ipc_type_t *btype = ptype->itElement; + + fprintf(file, "\n"); + + /* calculate the actual size in bytes of the data field. + note that this quantity must be a multiple of four. + hence, if the base type size isn't a multiple of four, + we have to round up. */ + + if (btype->itTypeSize % 4 != 0) + fprintf(file, "\tmsg_size_delta = (%d * %s + 3) & ~3;\n", btype->itTypeSize, arg->argVarName); + else + fprintf(file, "\tmsg_size_delta = %d * %s;\n", btype->itTypeSize, arg->argVarName); + + fprintf(file, "\tmsg_size += msg_size_delta;\n"); + + /* Don't bother moving OutP unless there are more Out arguments. */ + if (arg->argReplyPos < arg->argRoutine->rtMaxReplyPos) { + fprintf(file, "\tOutP = (Reply *) ((char *) OutP + "); + fprintf(file, "msg_size_delta - %d);\n", ptype->itTypeSize + ptype->itPadSize); + } +} + +static void +WritePackArg(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbReplyInit)) + WritePackArgType(file, arg); + + if (akCheckAll(arg->argKind, akbReturnSnd|akbVarNeeded)) + WritePackArgValue(file, arg); + + if (akCheck(arg->argKind, akbReplyCopy)) + WriteCopyArgValue(file, arg); + + if ((akIdent(arg->argKind) == akeCount) && akCheck(arg->argKind, akbReturnSnd)) { + ipc_type_t *ptype = arg->argParent->argType; + + if (ptype->itInLine && ptype->itVarArray) + WriteAdjustMsgSize(file, arg); + } +} + +static void +WriteFieldDecl(FILE *file, argument_t *arg) +{ + WriteFieldDeclPrim(file, arg, FetchServerType); +} + +static void +WriteRoutine(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + + fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); + fprintf(file, "mig_internal novalue _X%s (\n", rt->rtName); + fprintf(file, "\tmsg_header_t *InHeadP,\n" + "\tmsg_header_t *OutHeadP,\n" + "\t%s_t *%s)\n", SubsystemName, SubsystemName); + + fprintf(file, "{\n"); + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request"); + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply"); + + WriteVarDecls(file, rt); + + WriteList(file, rt->rtArgs, WriteCheckDecl, akbQuickCheck|akbRequest, "\n", "\n"); + WriteList(file, rt->rtArgs, WriteTypeDecl, akbReplyInit, "\n", "\n"); + + WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded, ";\n", ";\n\n"); + + WriteCheckHead(file, rt); + + WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", ""); + + WriteHandlerCall(file, rt); + WriteGetReturnValue(file, rt); + + /* In reverse order so we can jump into the middle. */ + + WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", ""); + fprintf(file, "#ifdef\tlabel_punt0\n"); + fprintf(file, "#undef\tlabel_punt0\n"); + fprintf(file, "punt0:\n"); + fprintf(file, "#endif\t/* label_punt0 */\n"); + + if (rt->rtOneWay) + fprintf(file, "\t;\n"); + else { + WriteCheckReturnValue(file, rt); + WriteReplyInit(file, rt); + WriteList(file, rt->rtArgs, WritePackArg, akbNone, "", ""); + WriteReplyHead(file, rt); + } + + fprintf(file, "}\n"); +} + +void +WriteHandler(FILE *file, statement_t *stats) +{ + statement_t *stat; + + WriteProlog(file); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: + WriteRoutine(file, stat->stRoutine); + break; + + case skImport: + case skSImport: + WriteImport(file, stat->stFileName); + break; + + case skUImport: + break; + + default: + fatal("WriteHandler(): bad statement_kind_t (%d)", (int) stat->stKind); + } + WriteEpilog(file, stats); +} + diff --git a/bootstrap_cmds/migcom.tproj/header.c b/bootstrap_cmds/migcom.tproj/header.c new file mode 100644 index 0000000..505cdd3 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/header.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "write.h" +#include "utils.h" +#include "global.h" +#include "strdefs.h" +#include "error.h" +#include + +void +WriteIncludes(FILE *file, boolean_t isuser, boolean_t isdef) +{ + if (isdef) { + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + if (!isuser) + fprintf(file, "#include \n"); + } + else { + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); + + if (IsVoucherCodeAllowed && !IsKernelUser && !IsKernelServer) { + fprintf(file, "\t\n/* BEGIN VOUCHER CODE */\n\n"); + fprintf(file, "#ifndef KERNEL\n"); + fprintf(file, "#if defined(__has_include)\n"); + fprintf(file, "#if __has_include()\n"); + fprintf(file, "#ifndef USING_VOUCHERS\n"); + fprintf(file, "#define USING_VOUCHERS\n"); + fprintf(file, "#endif\n"); + + + fprintf(file, "#ifndef __VOUCHER_FORWARD_TYPE_DECLS__\n"); + fprintf(file, "#define __VOUCHER_FORWARD_TYPE_DECLS__\n"); + + fprintf(file, "#ifdef __cplusplus\n"); + fprintf(file, "extern \"C\" {\n"); + fprintf(file, "#endif\n"); + + fprintf(file, "\textern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));\n"); + + fprintf(file, "#ifdef __cplusplus\n"); + fprintf(file, "}\n"); + fprintf(file, "#endif\n"); + + fprintf(file, "#endif // __VOUCHER_FORWARD_TYPE_DECLS__\n"); + fprintf(file, "#endif // __has_include()\n"); + fprintf(file, "#endif // __has_include\n"); + fprintf(file, "#endif // !KERNEL\n"); + + fprintf(file, "\t\n/* END VOUCHER CODE */\n\n"); + } + + fprintf(file, "\t\n/* BEGIN MIG_STRNCPY_ZEROFILL CODE */\n\n"); + fprintf(file, "#if defined(__has_include)\n"); + fprintf(file, "#if __has_include()\n"); + fprintf(file, "#ifndef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "#define USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "#endif\n"); + + fprintf(file, "#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n"); + fprintf(file, "#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n"); + + fprintf(file, "#ifdef __cplusplus\n"); + fprintf(file, "extern \"C\" {\n"); + fprintf(file, "#endif\n"); + + fprintf(file, "\textern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import));\n"); + + fprintf(file, "#ifdef __cplusplus\n"); + fprintf(file, "}\n"); + fprintf(file, "#endif\n"); + + fprintf(file, "#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */\n"); + fprintf(file, "#endif /* __has_include() */\n"); + fprintf(file, "#endif /* __has_include */\n"); + fprintf(file, "\t\n/* END MIG_STRNCPY_ZEROFILL CODE */\n\n"); + + if (ShortCircuit) + fprintf(file, "#include \n"); + if (isuser && IsKernelUser) { + fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNEL_SPECIFIC_CODE_)\n"); + fprintf(file, "#include \n"); + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + } + fprintf(file, "\n"); +} + +static void +WriteETAPDefines(FILE *file) +{ + statement_t *stat; + int fnum; + char *fname; + int first = TRUE; + + fprintf(file, "\n#ifndef subsystem_to_name_map_%s\n", SubsystemName); + fprintf(file, "#define subsystem_to_name_map_%s \\\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + fnum = SubsystemBase + stat->stRoutine->rtNumber; + fname = stat->stRoutine->rtName; + if (! first) + fprintf(file, ",\\\n"); + fprintf(file, " { \"%s\", %d }", fname, fnum); + first = FALSE; + } + fprintf(file, "\n#endif\n"); +} + +static void +WriteProlog(FILE *file, char *protect, boolean_t more, boolean_t isuser) +{ + if (protect != strNULL) { + fprintf(file, "#ifndef\t_%s\n", protect); + fprintf(file, "#define\t_%s\n", protect); + fprintf(file, "\n"); + } + + fprintf(file, "/* Module %s */\n", SubsystemName); + fprintf(file, "\n"); + + if (more) { + WriteIncludes(file, isuser, UseSplitHeaders); + } + fprintf(file, "#ifdef AUTOTEST\n"); + fprintf(file, "#ifndef FUNCTION_PTR_T\n"); + fprintf(file, "#define FUNCTION_PTR_T\n"); + fprintf(file, "typedef void (*function_ptr_t)"); + fprintf(file, "(mach_port_t, char *, mach_msg_type_number_t);\n"); + fprintf(file, "typedef struct {\n"); + fprintf(file, " char *name;\n"); + fprintf(file, " function_ptr_t function;\n"); + fprintf(file, "} function_table_entry;\n"); + fprintf(file, "typedef function_table_entry *function_table_t;\n"); + fprintf(file, "#endif /* FUNCTION_PTR_T */\n"); + fprintf(file, "#endif /* AUTOTEST */\n"); + fprintf(file, "\n#ifndef\t%s_MSG_COUNT\n", SubsystemName); + fprintf(file, "#define\t%s_MSG_COUNT\t%d\n", SubsystemName, rtNumber); + fprintf(file, "#endif\t/* %s_MSG_COUNT */\n\n", SubsystemName); +} + +static void +WriteEpilog(FILE *file, char *protect, boolean_t isuser) +{ + char *defname = isuser ? "__AfterMigUserHeader" : "__AfterMigServerHeader"; + + WriteETAPDefines(file); + fprintf(file, "\n#ifdef %s\n%s\n#endif /* %s */\n", defname, defname, defname); + if (protect != strNULL) { + fprintf(file, "\n"); + fprintf(file, "#endif\t /* _%s */\n", protect); + } +} + +static void +WriteUserRoutine(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); + WriteMigExternal(file); + fprintf(file, "%s %s\n", ReturnTypeStr(rt), rt->rtUserName); + if (BeLint) { + fprintf(file, "#if\t%s\n", LintLib); + fprintf(file, " ("); + WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", " , ""); + fprintf(file, ")\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n"); + fprintf(file, "{ "); + fprintf(file, "return "); + fprintf(file, "%s(", rt->rtUserName); + WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", ""); + fprintf(file, "); }\n"); + fprintf(file, "#else\n"); + } + if (BeAnsiC) { + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n"); + fprintf(file, ");\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n"); + fprintf(file, ");\n"); + fprintf(file, "#else\n"); + + fprintf(file, " ();\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + if (BeLint) { + fprintf(file, "#endif\t/* %s */\n", LintLib); + } +} + +void +WriteUserRequestUnion(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* union of all requests */\n\n"); + fprintf(file, "#ifndef __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName); + fprintf(file, "#define __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName); + fprintf(file, "union __RequestUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + + rt = stat->stRoutine; + fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtUserName); + } + } + fprintf(file, "};\n"); + fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName); +} + +void +WriteUserReplyUnion(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* union of all replies */\n\n"); + fprintf(file, "#ifndef __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName); + fprintf(file, "#define __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName); + fprintf(file, "union __ReplyUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + + rt = stat->stRoutine; + fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtUserName); + } + } + fprintf(file, "};\n"); + fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName); +} + +void +WriteUserHeader(FILE *file, statement_t *stats) +{ + statement_t *stat; + char *protect = strconcat(SubsystemName, "_user_"); + + WriteProlog(file, protect, TRUE, TRUE); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skImport: + case skUImport: + case skDImport: + WriteImport(file, stat->stFileName); + break; + + case skRoutine: + case skSImport: + case skIImport: + break; + + default: + fatal("WriteHeader(): bad statement_kind_t (%d)", (int) stat->stKind); + } + fprintf(file, "\n"); + fprintf(file, "#ifdef __BeforeMigUserHeader\n"); + fprintf(file, "__BeforeMigUserHeader\n"); + fprintf(file, "#endif /* __BeforeMigUserHeader */\n"); + fprintf(file, "\n"); + fprintf(file, "#include \n"); + fprintf(file, "__BEGIN_DECLS\n"); + fprintf(file, "\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) + WriteUserRoutine(file, stat->stRoutine); + } + fprintf(file, "\n"); + fprintf(file, "__END_DECLS\n"); + + fprintf(file, "\n"); + fprintf(file, "/********************** Caution **************************/\n"); + fprintf(file, "/* The following data types should be used to calculate */\n"); + fprintf(file, "/* maximum message sizes only. The actual message may be */\n"); + fprintf(file, "/* smaller, and the position of the arguments within the */\n"); + fprintf(file, "/* message layout may vary from what is presented here. */\n"); + fprintf(file, "/* For example, if any of the arguments are variable- */\n"); + fprintf(file, "/* sized, and less than the maximum is sent, the data */\n"); + fprintf(file, "/* will be packed tight in the actual message to reduce */\n"); + fprintf(file, "/* the presence of holes. */\n"); + fprintf(file, "/********************** Caution **************************/\n"); + fprintf(file, "\n"); + + WriteRequestTypes(file, stats); + WriteUserRequestUnion(file, stats); + + WriteReplyTypes(file, stats); + WriteUserReplyUnion(file, stats); + + WriteEpilog(file, protect, TRUE); +} + +static void +WriteDefinesRoutine(FILE *file, routine_t *rt) +{ + char *up = (char *)malloc(strlen(rt->rtName)+1); + + up = toupperstr(strcpy(up, rt->rtName)); + fprintf(file, "#define\tMACH_ID_%s\t\t%d\t/* %s() */\n", up, rt->rtNumber + SubsystemBase, rt->rtName); + if (rt->rtKind == rkRoutine) + fprintf(file, "#define\tMACH_ID_%s_REPLY\t\t%d\t/* %s() */\n", up, rt->rtNumber + SubsystemBase + 100, rt->rtName); + fprintf(file, "\n"); +} + +void +WriteServerRoutine(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); + WriteMigExternal(file); + + // MIG_SERVER_ROUTINE can be defined by system headers to resolve to an attribute that + // tells the compiler that this is a MIG server routine. Useful for static analysis. + fprintf(file, "MIG_SERVER_ROUTINE\n%s %s\n", ReturnTypeStr(rt), rt->rtServerName); + + if (BeLint) { + fprintf(file, "#if\t%s\n", LintLib); + fprintf(file, " ("); + WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", " , ""); + fprintf(file, ")\n"); + WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ";\n", ";\n"); + fprintf(file, "{ "); + fprintf(file, "return "); + fprintf(file, "%s(", rt->rtServerName); + WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", ", ""); + fprintf(file, "); }\n"); + fprintf(file, "#else /* %s */\n",LintLib); + } + if (BeAnsiC) { + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ",\n", "\n"); + fprintf(file, ");\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ",\n", "\n"); + fprintf(file, ");\n"); + fprintf(file, "#else\n"); + + fprintf(file, " ();\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + if (BeLint) { + fprintf(file, "#endif\t/* %s */\n", LintLib); + } +} + +static void +WriteDispatcher(FILE *file) +{ + statement_t *stat; + int descr_count = 0; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + routine_t *rt = stat->stRoutine; + descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0); + } + fprintf(file, "\n"); + + WriteMigExternal(file); + fprintf(file, "boolean_t %s(\n", ServerDemux); + fprintf(file, "\t\tmach_msg_header_t *InHeadP,\n"); + fprintf(file, "\t\tmach_msg_header_t *OutHeadP);\n\n"); + + WriteMigExternal(file); + fprintf(file, "mig_routine_t %s_routine(\n", ServerDemux); + fprintf(file, "\t\tmach_msg_header_t *InHeadP);\n\n"); + + fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n"); + fprintf(file, "extern const struct %s {\n", ServerSubsys); + if (UseRPCTrap) { + fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n"); + } + else { + fprintf(file, "\tmig_server_routine_t\tserver;\t/* Server routine */\n"); + } + fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n"); + fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n"); + fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n"); + if (UseRPCTrap) { + fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n"); + fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n"); + } + else { + fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n"); + fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n"); + } + fprintf(file, "\t\troutine[%d];\n", rtNumber); + if (UseRPCTrap) { + fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n"); + fprintf(file, "\t\targ_descriptor[%d];\n", descr_count); + } + fprintf(file, "} %s;\n", ServerSubsys); + fprintf(file, "\n"); +} + +void +WriteBogusServerRoutineAnnotationDefine(FILE *file) { + // MIG_SERVER_ROUTINE can be defined by system headers to resolve to + // an attribute that tells the compiler that this is a MIG server routine. + // Useful for static analysis. + fprintf(file, "#ifndef MIG_SERVER_ROUTINE\n"); + fprintf(file, "#define MIG_SERVER_ROUTINE\n"); + fprintf(file, "#endif\n"); + fprintf(file, "\n"); +} + +void +WriteServerHeader(FILE *file, statement_t *stats) +{ + statement_t *stat; + char *protect = strconcat(SubsystemName, "_server_"); + + WriteProlog(file, protect, TRUE, FALSE); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skImport: + case skSImport: + case skDImport: + WriteImport(file, stat->stFileName); + break; + + case skRoutine: + case skUImport: + case skIImport: + break; + + default: + fatal("WriteServerHeader(): bad statement_kind_t (%d)", (int) stat->stKind); + } + fprintf(file, "\n#ifdef __BeforeMigServerHeader\n"); + fprintf(file, "__BeforeMigServerHeader\n"); + fprintf(file, "#endif /* __BeforeMigServerHeader */\n\n"); + + WriteBogusServerRoutineAnnotationDefine(file); + + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) + WriteServerRoutine(file, stat->stRoutine); + } + WriteDispatcher(file); + + WriteRequestTypes(file, stats); + WriteServerRequestUnion(file, stats); + + WriteReplyTypes(file, stats); + WriteServerReplyUnion(file, stats); + + WriteEpilog(file, protect, FALSE); +} + +static void +WriteInternalRedefine(FILE *file, routine_t *rt) +{ + fprintf(file, "#define %s %s_external\n", rt->rtUserName, rt->rtUserName); +} + +void +WriteInternalHeader(FILE *file, statement_t *stats) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: + WriteInternalRedefine(file, stat->stRoutine); + break; + + case skImport: + case skUImport: + case skSImport: + case skDImport: + case skIImport: + break; + + default: + fatal("WriteInternalHeader(): bad statement_kind_t (%d)", (int) stat->stKind); + } +} + +void +WriteDefinesHeader(FILE *file, statement_t *stats) +{ + statement_t *stat; + char *protect = strconcat(SubsystemName, "_defines"); + + WriteProlog(file, protect, FALSE, FALSE); + fprintf(file, "\n/*\tDefines related to the Subsystem %s\t*/\n\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: + WriteDefinesRoutine(file, stat->stRoutine); + break; + + case skImport: + case skSImport: + case skUImport: + break; + + default: + fatal("WriteDefinesHeader(): bad statement_kind_t (%d)", (int) stat->stKind); + } + WriteEpilog(file, protect, FALSE); +} diff --git a/bootstrap_cmds/migcom.tproj/lexxer.h b/bootstrap_cmds/migcom.tproj/lexxer.h new file mode 100644 index 0000000..6f1cfa5 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/lexxer.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +extern void LookFileName(void); +extern void LookString(void); +extern void LookQString(void); +extern void LookNormal(void); diff --git a/bootstrap_cmds/migcom.tproj/lexxer.l b/bootstrap_cmds/migcom.tproj/lexxer.l new file mode 100644 index 0000000..82b32e5 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/lexxer.l @@ -0,0 +1,314 @@ +%k 10000 +%n 5000 +%a 20000 +%e 10000 +%p 25000 + +Ident ([A-Za-z_][A-Za-z_0-9]*) +Number ([0-9]+) +String ([-/._$A-Za-z0-9]+) +QString (\"[^"\n]*\") +AString (\<[^>\n]*\>) +FileName ({QString}|{AString}) + +/* new flex syntax to accomplish the same thing as #define YY_NO_UNPUT */ +%option nounput + +%{ +/* + * Copyright (c) 1999-2018 Apple, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999, 2008 Apple Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include "strdefs.h" +#include "type.h" +#include +#include +#include +#include "statement.h" +#include "global.h" +#include "y.tab.h" // was parser.h +#include "lexxer.h" +#include "mig_machine.h" + +#define PortSize (sizeof (mach_port_t) * NBBY) +#ifdef __STDC__ +#define stringize(x) #x +#else /* __STDC__ */ +#define stringize(x) "x" +#endif /* __STDC__ */ + +#ifdef LDEBUG +#define RETURN(sym) \ +{ \ + printf("yylex: returning '%s' (%d)\n", stringize(sym), (sym)); \ + return (sym); \ +} +#else /* LDEBUG */ +#define RETURN(sym) return (sym) +#endif /* LDEBUG */ + +#define TPRETURN(intype, outtype, tsize) \ +{ \ + yylval.symtype.innumber = (intype); \ + yylval.symtype.instr = stringize(intype); \ + yylval.symtype.outnumber = (outtype); \ + yylval.symtype.outstr = stringize(outtype); \ + yylval.symtype.size = (tsize); \ + RETURN(sySymbolicType); \ +} + +#define TRETURN(type, tsize) TPRETURN(type,type,tsize) + +#define SAVE(s) do {oldYYBegin = s; BEGIN s; } while (0) + +#define RESTORE BEGIN oldYYBegin + +#define FRETURN(val) \ +{ \ + yylval.flag = (val); \ + RETURN(syIPCFlag); \ +} + +#define YY_NO_UNPUT /* suppress yyunput generation */ + +static int oldYYBegin = 0; + +int lineno = 0; /* Replaces lex yylineno */ + +static void doSharp(char *); /* process body of # directives */ +extern void yyerror(char *); +%} + +%Start Normal String FileName QString SkipToEOL + +%% + +[Rr][Oo][Uu][Tt][Ii][Nn][Ee] RETURN(syRoutine); +[Ss][Ii][Mm][Pp][Ll][Ee][Rr][Oo][Uu][Tt][Ii][Nn][Ee] RETURN(sySimpleRoutine); +[Ss][Uu][Bb][Ss][Yy][Ss][Tt][Ee][Mm] RETURN(sySubsystem); +[Mm][Ss][Gg][Oo][Pp][Tt][Ii][Oo][Nn] RETURN(syMsgOption); +[Uu][Ss][Ee][Ss][Pp][Ee][Cc][Ii][Aa][Ll][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syUseSpecialReplyPort); +[Cc][Oo][Nn][Ss][Uu][Mm][Ee][Oo][Nn][Ss][Ee][Nn][Dd][Ee][Rr][Rr][Oo][Rr] RETURN(syConsumeOnSendError); +[Mm][Ss][Gg][Ss][Ee][Qq][Nn][Oo] RETURN(syMsgSeqno); +[Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syWaitTime); +[Ss][Ee][Nn][Dd][Tt][Ii][Mm][Ee] RETURN(sySendTime); +[Nn][Oo][Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syNoWaitTime); +[Nn][Oo][Ss][Ee][Nn][Dd][Tt][Ii][Mm][Ee] RETURN(syNoSendTime); +[Ii][Nn] RETURN(syIn); +[Oo][Uu][Tt] RETURN(syOut); +[Uu][Ss][Ee][Rr][Ii][Mm][Pp][Ll] RETURN(syUserImpl); +[Ss][Ee][Rr][Vv][Ee][Rr][Ii][Mm][Pp][Ll] RETURN(syServerImpl); +[Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(sySecToken); +[Ss][Ee][Rr][Vv][Ee][Rr][Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(syServerSecToken); +[Uu][Ss][Ee][Rr][Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(syUserSecToken); +[Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syAuditToken); +[Ss][Ee][Rr][Vv][Ee][Rr][Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syServerAuditToken); +[Uu][Ss][Ee][Rr][Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syUserAuditToken); +[Ss][Ee][Rr][Vv][Ee][Rr][Cc][Oo][Nn][Tt][Ee][Xx][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syServerContextToken); +[Ii][Nn][Oo][Uu][Tt] RETURN(syInOut); +[Rr][Ee][Qq][Uu][Ee][Ss][Tt][Pp][Oo][Rr][Tt] RETURN(syRequestPort); +[Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syReplyPort); +[Uu][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syUReplyPort); +[Ss][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(sySReplyPort); +[Aa][Rr][Rr][Aa][Yy] RETURN(syArray); +[Oo][Ff] RETURN(syOf); +[Ee][Rr][Rr][Oo][Rr] RETURN(syErrorProc); +[Ss][Ee][Rr][Vv][Ee][Rr][Pp][Rr][Ee][Ff][Ii][Xx] RETURN(syServerPrefix); +[Uu][Ss][Ee][Rr][Pp][Rr][Ee][Ff][Ii][Xx] RETURN(syUserPrefix); +[Ss][Ee][Rr][Vv][Ee][Rr][Dd][Ee][Mm][Uu][Xx] RETURN(syServerDemux); +[Rr][Cc][Ss][Ii][Dd] RETURN(syRCSId); +[Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syImport); +[Uu][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syUImport); +[Ss][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(sySImport); +[Dd][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syDImport); +[Ii][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syIImport); +[Tt][Yy][Pp][Ee] RETURN(syType); +[Kk][Ee][Rr][Nn][Ee][Ll][Ss][Ee][Rr][Vv][Ee][Rr] RETURN(syKernelServer); +[Kk][Ee][Rr][Nn][Ee][Ll][Uu][Ss][Ee][Rr] RETURN(syKernelUser); +[Ss][Kk][Ii][Pp] RETURN(sySkip); +[Ss][Tt][Rr][Uu][Cc][Tt] RETURN(syStruct); +[Ii][Nn][Tt][Rr][Aa][Nn] RETURN(syInTran); +[Oo][Uu][Tt][Tt][Rr][Aa][Nn] RETURN(syOutTran); +[Dd][Ee][Ss][Tt][Rr][Uu][Cc][Tt][Oo][Rr] RETURN(syDestructor); +[Cc][Tt][Yy][Pp][Ee] RETURN(syCType); +[Cc][Uu][Ss][Ee][Rr][Tt][Yy][Pp][Ee] RETURN(syCUserType); +[Cc][Ss][Ee][Rr][Vv][Ee][Rr][Tt][Yy][Pp][Ee] RETURN(syCServerType); +[Cc]_[Ss][Tt][Rr][Ii][Nn][Gg] RETURN(syCString); + +[Ss][Aa][Mm][Ee][Cc][Oo][Uu][Nn][Tt] FRETURN(flSameCount); +[Rr][Ee][Tt][Cc][Oo][Dd][Ee] FRETURN(flRetCode); +[Pp][Hh][Yy][Ss][Ii][Cc][Aa][Ll][Cc][Oo][Pp][Yy] FRETURN(flPhysicalCopy); +[Oo][Vv][Ee][Rr][Ww][Rr][Ii][Tt][Ee] FRETURN(flOverwrite); +[Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flDealloc); +[Nn][Oo][Tt][Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flNotDealloc); +[Cc][Oo][Uu][Nn][Tt][Ii][Nn][Oo][Uu][Tt] FRETURN(flCountInOut); +[Pp][Oo][Ll][Yy][Mm][Oo][Rr][Pp][Hh][Ii][Cc] TPRETURN(MACH_MSG_TYPE_POLYMORPHIC, MACH_MSG_TYPE_POLYMORPHIC, PortSize); +[Aa][Uu][Tt][Oo] FRETURN(flAuto); +[Cc][Oo][Nn][Ss][Tt] FRETURN(flConst); +"PointerTo" RETURN(syPointerTo); +"PointerToIfNot" RETURN(syPointerToIfNot); +"ValueOf" RETURN(syValueOf); +"UserTypeLimit" RETURN(syUserTypeLimit); +"OnStackLimit" RETURN(syOnStackLimit); + + +"MACH_MSG_TYPE_UNSTRUCTURED" TRETURN(MACH_MSG_TYPE_UNSTRUCTURED,0); +"MACH_MSG_TYPE_BIT" TRETURN(MACH_MSG_TYPE_BIT,1); +"MACH_MSG_TYPE_BOOLEAN" TRETURN(MACH_MSG_TYPE_BOOLEAN,32); +"MACH_MSG_TYPE_INTEGER_8" TRETURN(MACH_MSG_TYPE_INTEGER_8,8); +"MACH_MSG_TYPE_INTEGER_16" TRETURN(MACH_MSG_TYPE_INTEGER_16,16); +"MACH_MSG_TYPE_INTEGER_32" TRETURN(MACH_MSG_TYPE_INTEGER_32,32); +"MACH_MSG_TYPE_INTEGER_64" TRETURN(MACH_MSG_TYPE_INTEGER_64,64); +"MACH_MSG_TYPE_REAL_32" TRETURN(MACH_MSG_TYPE_REAL_32,32); +"MACH_MSG_TYPE_REAL_64" TRETURN(MACH_MSG_TYPE_REAL_64,64); +"MACH_MSG_TYPE_CHAR" TRETURN(MACH_MSG_TYPE_CHAR,8); +"MACH_MSG_TYPE_BYTE" TRETURN(MACH_MSG_TYPE_BYTE,8); + +"MACH_MSG_TYPE_MOVE_RECEIVE" TPRETURN(MACH_MSG_TYPE_MOVE_RECEIVE,MACH_MSG_TYPE_PORT_RECEIVE,PortSize); +"MACH_MSG_TYPE_COPY_SEND" TPRETURN(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize); +"MACH_MSG_TYPE_MAKE_SEND" TPRETURN(MACH_MSG_TYPE_MAKE_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize); +"MACH_MSG_TYPE_MOVE_SEND" TPRETURN(MACH_MSG_TYPE_MOVE_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize); +"MACH_MSG_TYPE_MAKE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MAKE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize); +"MACH_MSG_TYPE_MOVE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MOVE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize); + +"MACH_MSG_TYPE_PORT_NAME" TRETURN(MACH_MSG_TYPE_PORT_NAME,PortSize); +"MACH_MSG_TYPE_PORT_RECEIVE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_RECEIVE,PortSize); +"MACH_MSG_TYPE_PORT_SEND" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND,PortSize); +"MACH_MSG_TYPE_PORT_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize); +"MACH_MSG_TYPE_POLYMORPHIC" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC, MACH_MSG_TYPE_POLYMORPHIC, PortSize); + +":" RETURN(syColon); +";" RETURN(sySemi); +"," RETURN(syComma); +"+" RETURN(syPlus); +"-" RETURN(syMinus); +"*" RETURN(syStar); +"/" RETURN(syDiv); +"(" RETURN(syLParen); +")" RETURN(syRParen); +"=" RETURN(syEqual); +"^" RETURN(syCaret); +"~" RETURN(syTilde); +"<" RETURN(syLAngle); +">" RETURN(syRAngle); +"[" RETURN(syLBrack); +"]" RETURN(syRBrack); +"|" RETURN(syBar); + +{Ident} { yylval.identifier = strmake(yytext); + RETURN(syIdentifier); } +{Number} { yylval.number = atoi(yytext); RETURN(syNumber); } + +{String} { yylval.string = strmake(yytext); + SAVE(Normal); RETURN(syString); } +{FileName} { yylval.string = strmake(yytext); + SAVE(Normal); RETURN(syFileName); } +{QString} { yylval.string = strmake(yytext); + SAVE(Normal); RETURN(syQString); } + +^\#[ \t]*{Number}[ \t]*\"[^"]*\" { doSharp(yytext+1); + BEGIN SkipToEOL; } +^\#\ *{Number} { doSharp(yytext+1); + BEGIN SkipToEOL; } +^\#pragma { BEGIN SkipToEOL; } +^\# { yyerror("illegal # directive"); + BEGIN SkipToEOL; } + +\n { RESTORE; lineno++; } +. ; + +[ \t] ; +\n lineno++; +. { SAVE(Normal); RETURN(syError); } + +%% + +extern void +LookNormal() +{ + SAVE(Normal); +} + +extern void +LookString() +{ + SAVE(String); +} + +extern void +LookQString() +{ + SAVE(QString); +} + +extern void +LookFileName() +{ + SAVE(FileName); +} + +static void +doSharp(char *body) +{ + char *startName, *endName; + + lineno = atoi(body); + startName = strchr(body, '"'); + if (startName != NULL) { + endName = strrchr(body, '"'); + *endName = '\0'; + strfree(yyinname); + yyinname = strmake(startName+1); + } +} + +int +yywrap() +{ + return 1; +} diff --git a/bootstrap_cmds/migcom.tproj/mig.1 b/bootstrap_cmds/migcom.tproj/mig.1 new file mode 100644 index 0000000..6ab8cda --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/mig.1 @@ -0,0 +1,88 @@ +.TH MIG 1 "Nov 20, 2009" "Apple Computer, Inc." +.SH NAME +mig \- Mach Interface Generator +.SH SYNOPSIS +.B mig +[ +.I "option \&..." +] +.I "file" + +.SH DESCRIPTION +The +.I mig +command invokes the Mach Interface Generator to generate Remote Procedure Call (RPC) +code for client-server style Mach IPC from specification files. +.SH OPTIONS +.TP +.B \-q/-Q +Omit / +.I emit +warning messages. +.TP +.B \-v/-V +Verbose mode ( on / +.I off +) will summarize types and routines as they are processed. +.TP +.B \-l/-L +Controls ( +.I off +/ on ) whether or not generated code logs RPC events to system logs. +.TP +.B \-k/-K +Controls ( +.I on +/ off ) whether generated code complies with ANSI C standards. +.TP +.B \-s/-S +Controls ( on / +.I off +) whether generated server-side code includes a generated symbol table. +.TP +.BI \-i " prefix" +Specify User file prefix. +.TP +.BI \-user " path" +Specify name of user-side RPC generated source file. +.TP +.BI \-server " path" +Specify name of server-side RPC generated source file. +.TP +.BI \-header " path" +Specify name of user-side generated header file. +.TP +.BI \-sheader " path" +Specify name of server-side generated header file. +.TP +.BI \-iheader " path" +Specify internal header file name. +.TP +.BI \-dheader " path" +Specify defines generated header file. +.TP +.BI \-maxonstack " value" +Specify maximum size of message on stack. +.TP +.B \-split +Use split headers. +.TP +.BI \-arch " arch" +Specify machine architecture for target code. +.TP +.B \-MD +Option is passed to the C compiler for dependency generation. +.TP +.B \-cpp +This option is ignored. +.TP +.BI \-cc " path" +Specify pathname to specific C compiler to use as the preprocessor. +.TP +.BI \-migcom " path" +Specify pathname to specific migcom compiler to use for source code generation. +.TP +.BI \-isysroot " path" +Specify SDK root directory. +.TP +Additional options provided are passed along to the C compiler unchanged. diff --git a/bootstrap_cmds/migcom.tproj/mig.c b/bootstrap_cmds/migcom.tproj/mig.c new file mode 100644 index 0000000..9bdd304 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/mig.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Switches are; + * -[v,Q] verbose or not quiet: prints out type + * and routine information as mig runs. + * -[V,q] not verbose or quiet : don't print + * information during compilation + * (this is the default) + * -[r,R] do or don't use rpc calls instead of + * send/receive pairs. Default is -r. + * -[s,S] generate symbol table or not: generate a + * table of rpc-name, number, routine triplets + * as an external data structure -- main use is + * for protection system's specification of rights + * and for protection dispatch code. Default is -s. + * -[l,L] -L generate code that insert code for logging + * the most important events that happen at the + * stub level (message conception, target routine + * calls). Default is -l. + * -[k,K] -K enforces MIG to generate K&R C language, with the + * addition of ANSI C syntax under #ifdef __STDC__. + * Default is -k. + * -[n,N] -n enforces NDR checking and conversion logic generation. + * Default is -N (no checking). + * -i + * Put each user routine in its own file. The + * file is named .c. + * -user + * Name the user-side file + * -server + * Name the server-side file + * -header + * Name the user-side header file + * -iheader + * Name the user-side internal header file + * -sheader + * Name the server-side header file + * -dheader + * Name the defines (msgh_ids) header file + * + * DESIGN: + * Mig uses a lexxer module created by lex from lexxer.l and + * a parser module created by yacc from parser.y to parse an + * interface definitions module for a mach server. + * The parser module calls routines in statement.c + * and routines.c to build a list of statement structures. + * The most interesting statements are the routine definitions + * which contain information about the name, type, characteristics + * of the routine, an argument list containing information for + * each argument type, and a list of special arguments. The + * argument type structures are build by routines in type.c + * Once parsing is completed, the three code generation modules: + * header.c user.c and server.c are called sequentially. These + * do some code generation directly and also call the routines + * in utils.c for common (parameterized) code generation. + * + */ + +#include +#include +#include +#include "error.h" +#include "lexxer.h" +#include "global.h" +#include "write.h" + +extern int yyparse(void); +static FILE *myfopen(const char *name, const char *mode); + +static void +parseArgs(int argc,char *argv[]) +{ + if (argc == 2 && streql(argv[1], "-version")) { + PrintVersion = TRUE; + return; + } + + while (--argc > 0) + if ((++argv)[0][0] == '-') { + switch (argv[0][1]) { + + case 'q': + BeQuiet = TRUE; + break; + + case 'Q': + BeQuiet = FALSE; + break; + + case 'v': + BeVerbose = TRUE; + break; + + case 'V': + BeVerbose = FALSE; + break; + + case 'r': + UseMsgRPC = TRUE; + break; + + case 'R': + UseMsgRPC = FALSE; + break; + + case 'l': + UseEventLogger = FALSE; + break; + + case 'L': + UseEventLogger = TRUE; + break; + + case 'k': + BeAnsiC = TRUE; + break; + + case 'K': + BeAnsiC = FALSE; + break; + + case 'n': + if (streql(argv[0], "-novouchers")) { + IsVoucherCodeAllowed = FALSE; + } else { + CheckNDR = TRUE; + } + break; + + case 'N': + CheckNDR = FALSE; + break; + + case 's': + if (streql(argv[0], "-server")) { + --argc; ++argv; + if (argc == 0) + fatal("missing name for -server option"); + ServerFileName = strmake(argv[0]); + } + else if (streql(argv[0], "-sheader")) { + --argc; ++argv; + if (argc == 0) + fatal ("missing name for -sheader option"); + ServerHeaderFileName = strmake(argv[0]); + } + else if (streql(argv[0], "-split")) + UseSplitHeaders = TRUE; + else + GenSymTab = TRUE; + break; + + case 'S': + GenSymTab = FALSE; + break; + + case 't': + warn("Mach RPC traps not fully supported"); + TestRPCTrap = TRUE; + UseRPCTrap = TRUE; + break; + + case 'T': + UseRPCTrap = FALSE; + break; + + case 'i': + if (streql(argv[0], "-iheader")) { + --argc; ++argv; + if (argc == 0) + fatal("missing name for -iheader option"); + InternalHeaderFileName = strmake(argv[0]); + } + else { + --argc; ++argv; + if (argc == 0) + fatal("missing prefix for -i option"); + UserFilePrefix = strmake(argv[0]); + } + break; + + case 'u': + if (streql(argv[0], "-user")) { + --argc; ++argv; + if (argc == 0) + fatal("missing name for -user option"); + UserFileName = strmake(argv[0]); + } + else + fatal("unknown flag: '%s'", argv[0]); + break; + + case 'h': + if (streql(argv[0], "-header")) { + --argc; ++argv; + if (argc == 0) + fatal("missing name for -header option"); + UserHeaderFileName = strmake(argv[0]); + } + else + fatal("unknown flag: '%s'", argv[0]); + break; + + case 'd': + if (streql(argv[0], "-dheader")) { + --argc; ++argv; + if (argc == 0) + fatal("missing name for -dheader option"); + DefinesHeaderFileName = strmake(argv[0]); + } + else + fatal("unknown flag: '%s'", argv[0]); + break; + + case 'm': + if (streql(argv[0], "-maxonstack")) { + --argc; ++argv; + if (argc == 0) + fatal("missing size for -maxonstack option"); + MaxMessSizeOnStack = atoi(argv[0]); + } + else + fatal("unknown flag: '%s'", argv[0]); + break; + + case 'X': + ShortCircuit = FALSE; + break; + + case 'x': + ShortCircuit = TRUE; + /* fall thru - no longer supported */ + + default: + fatal("unknown/unsupported flag: '%s'", argv[0]); + /*NOTREACHED*/ + } + } + else + fatal("bad argument: '%s'", *argv); +} + +FILE *uheader, *server, *user; + +int +main(int argc, char *argv[]) +{ + FILE *iheader = 0; + FILE *sheader = 0; + FILE *dheader = 0; + time_t loc; + extern string_t GenerationDate; + + set_program_name("mig"); + parseArgs(argc, argv); + if (PrintVersion) { + printf("%s\n", MIG_VERSION); + fflush(stdout); + exit(0); + } + init_global(); + init_type(); + loc = time((time_t *)0); + GenerationDate = ctime(&loc); + + LookNormal(); + (void) yyparse(); + + if (mig_errors > 0) + fatal("%d errors found. Abort.\n", mig_errors); + + more_global(); + + uheader = myfopen(UserHeaderFileName, "w"); + if (!UserFilePrefix) + user = myfopen(UserFileName, "w"); + server = myfopen(ServerFileName, "w"); + if (ServerHeaderFileName) + sheader = myfopen(ServerHeaderFileName, "w"); + if (IsKernelServer) { + iheader = myfopen(InternalHeaderFileName, "w"); + } + if (DefinesHeaderFileName) + dheader = myfopen(DefinesHeaderFileName, "w"); + if (BeVerbose) { + printf("Writing %s ... ", UserHeaderFileName); + fflush(stdout); + } + WriteUserHeader(uheader, stats); + fclose(uheader); + if (ServerHeaderFileName) { + if (BeVerbose) { + printf ("done.\nWriting %s ...", ServerHeaderFileName); + fflush (stdout); + } + WriteServerHeader(sheader, stats); + fclose(sheader); + } + if (IsKernelServer) { + if (BeVerbose) { + printf("done.\nWriting %s ... ", InternalHeaderFileName); + fflush(stdout); + } + WriteInternalHeader(iheader, stats); + fclose(iheader); + } + if (DefinesHeaderFileName) { + if (BeVerbose) { + printf ("done.\nWriting %s ...", DefinesHeaderFileName); + fflush (stdout); + } + WriteDefinesHeader(dheader, stats); + fclose(dheader); + } + if (UserFilePrefix) { + if (BeVerbose) { + printf("done.\nWriting individual user files ... "); + fflush(stdout); + } + WriteUserIndividual(stats); + } + else { + if (BeVerbose) { + printf("done.\nWriting %s ... ", UserFileName); + fflush(stdout); + } + WriteUser(user, stats); + fclose(user); + } + if (BeVerbose) { + printf("done.\nWriting %s ... ", ServerFileName); + fflush(stdout); + } + WriteServer(server, stats); + fclose(server); + if (BeVerbose) + printf("done.\n"); + + exit(0); +} + +static FILE * +myfopen(const char *name, const char *mode) +{ + const char *realname; + FILE *file; + + if (name == strNULL) + realname = "/dev/null"; + else + realname = name; + + file = fopen(realname, mode); + if (file == NULL) + fatal("fopen(%s): %s", realname, strerror(errno)); + + return file; +} diff --git a/bootstrap_cmds/migcom.tproj/mig.sh b/bootstrap_cmds/migcom.tproj/mig.sh new file mode 100644 index 0000000..85cf5a2 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/mig.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# +# Copyright (c) 1999-2008 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# "Portions Copyright (c) 1999, 2008 Apple Inc. All Rights +# Reserved. This file contains Original Code and/or Modifications of +# Original Code as defined in and that are subject to the Apple Public +# Source License Version 1.0 (the 'License'). You may not use this file +# except in compliance with the License. Please obtain a copy of the +# License at http://www.apple.com/publicsource and read it before using +# this file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the +# License for the specific language governing rights and limitations +# under the License." +# +# @APPLE_LICENSE_HEADER_END@ +# +# Mach Operating System +# Copyright (c) 1991,1990 Carnegie Mellon University +# All Rights Reserved. +# +# Permission to use, copy, modify and distribute this software and its +# documentation is hereby granted, provided that both the copyright +# notice and this permission notice appear in all copies of the +# software, derivative works or modified versions, and any portions +# thereof, and that both notices appear in supporting documentation. +# +# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +# +# Carnegie Mellon requests users of this software to return to +# +# Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU +# School of Computer Science +# Carnegie Mellon University +# Pittsburgh PA 15213-3890 +# +# any improvements or extensions that they make and grant Carnegie Mellon +# the rights to redistribute these changes. +# + +realpath() +{ + local FILE="$1" + local PARENT=$(dirname "$FILE") + local BASE=$(basename "$FILE") + pushd "$PARENT" >/dev/null 2>&1 || return 0 + local DIR=$(pwd -P) + popd >/dev/null + if [ "$DIR" == "/" ]; then + echo "/$BASE" + else + echo "$DIR/$BASE" + fi + return 1 +} + +scriptPath=$(realpath "$0") +scriptRoot=$(dirname "$scriptPath") +migcomPath=$(realpath "${scriptRoot}/../libexec/migcom") + +if [ -n "${SDKROOT}" ]; then + sdkRoot="${SDKROOT}"; +fi + +if [ -z "${MIGCC}" ]; then + xcrunPath="/usr/bin/xcrun" + if [ -x "${xcrunPath}" ]; then + MIGCC=`"${xcrunPath}" -sdk "$sdkRoot" -find cc` + else + MIGCC=$(realpath "${scriptRoot}/cc") + fi +fi + +C=${MIGCC} +M=${MIGCOM-${migcomPath}} + +if [ $# -eq 1 ] && [ "$1" = "-version" ] ; then + "$M" "$@" + exit $? +fi + +cppflags="-D__MACH30__" + +files= +arch=`/usr/bin/arch` + +WORKTMP=`/usr/bin/mktemp -d "${TMPDIR:-/tmp}/mig.XXXXXX"` +if [ $? -ne 0 ]; then + echo "Failure creating temporary work directory: ${WORKTMP}" + echo "Exiting..." + exit 1 +fi + +# parse out the arguments until we hit plain file name(s) + +until [ $# -eq 0 ] +do + case "$1" in + -[dtqkKQvVtTrRsSlLxXnN] ) migflags=( "${migflags[@]}" "$1" ); shift;; + -i ) sawI=1; migflags=( "${migflags[@]}" "$1" "$2" ); shift; shift;; + -user ) user="$2"; if [ ! "${sawI-}" ]; then migflags=( "${migflags[@]}" "$1" "$2" ); fi; shift; shift;; + -server ) server="$2"; migflags=( "${migflags[@]}" "$1" "$2" ); shift; shift;; + -header ) header="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;; + -sheader ) sheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;; + -iheader ) iheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;; + -dheader ) dheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;; + -arch ) arch="$2"; shift; shift;; + -target ) target=( "$1" "$2"); shift; shift;; + -maxonstack ) migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;; + -split ) migflags=( "${migflags[@]}" "$1" ); shift;; + -novouchers ) migflags=( "${migflags[@]}" "$1" ); shift;; + -MD ) sawMD=1; cppflags=( "${cppflags[@]}" "$1"); shift;; + -cpp) shift; shift;; + -cc) C="$2"; shift; shift;; + -migcom) M="$2"; shift; shift;; + -isysroot) sdkRoot=$(realpath "$2"); shift; shift;; + -* ) cppflags=( "${cppflags[@]}" "$1"); shift;; + * ) break;; + esac +done + +# process the rest as files +until [ $# -eq 0 ] +do + case "$1" in + -[dtqkKQvVtTrRsSlLxXnN] ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;; + -i ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -user ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -server ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -header ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -sheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -iheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -dheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -arch ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift ; shift; continue;; + -target ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift ; shift; continue;; + -maxonstack ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -split ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;; + -novouchers ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;; + -MD ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;; + -cpp) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -cc) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -migcom) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -isysroot) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;; + -* ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;; + * ) file="$1"; shift;; + esac + base="$(basename "${file}" .defs)" + temp="${WORKTMP}/${base}.$$" + sourcedir="$(dirname "${file}")" + if [ -n "${sdkRoot}" ] + then + iSysRootParm=( "-isysroot" "${sdkRoot}" ) + fi + if [ ! -r "${file}" ] + then + echo "error: cannot read file ${file}" + rm -rf ${WORKTMP} + exit 1 + fi + rm -f "${temp}.c" "${temp}.d" + (echo '#line 1 '\"${file}\" ; cat "${file}" ) > "${temp}.c" + "$C" -E -arch ${arch} "${target[@]}" "${cppflags[@]}" -I "${sourcedir}" "${iSysRootParm[@]}" "${temp}.c" | "$M" "${migflags[@]}" + if [ $? -ne 0 ] + then + rm -rf "${temp}.c" "${temp}.d" "${WORKTMP}" + exit 1 + fi + if [ "${sawMD}" -a -f "${temp}.d" ] + then + deps= + s= + rheader="${header-${base}.h}" + if [ "${rheader}" != /dev/null ]; then + deps="${deps}${s}${rheader}"; s=" " + fi + ruser="${user-${base}User.c}" + if [ "${ruser}" != /dev/null ]; then + deps="${deps}${s}${ruser}"; s=" " + fi + rserver="${server-${base}Server.c}" + if [ "${rserver}" != /dev/null ]; then + deps="${deps}${s}${rserver}"; s=" " + fi + rsheader="${sheader-/dev/null}" + if [ "${rsheader}" != /dev/null ]; then + deps="${deps}${s}${rsheader}"; s=" " + fi + riheader="${iheader-/dev/null}" + if [ "${riheader}" != /dev/null ]; then + deps="${deps}${s}${riheader}"; s=" " + fi + rdheader="${dheader-/dev/null}" + if [ "${rdheader}" != /dev/null ]; then + deps="${deps}${s}${rdheader}"; s=" " + fi + for target in "${deps}" + do + sed -e 's;^'"${temp}"'.o[ ]*:;'"${target}"':;' \ + -e 's;: '"${temp}"'.c;: '"$file"';' \ + < "${temp}.d" > "${target}.d" + done + rm -f "${temp}.d" + fi + rm -f "${temp}.c" +done + +/bin/rmdir "${WORKTMP}" +exit 0 + diff --git a/bootstrap_cmds/migcom.tproj/mig_errors.h b/bootstrap_cmds/migcom.tproj/mig_errors.h new file mode 100644 index 0000000..f951667 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/mig_errors.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1987 Carnegie-Mellon University + * All rights reserved. The CMU software License Agreement specifies + * the terms and conditions for use and redistribution. + */ +/* + * Mach Interface Generator errors + * + * $Header: /Users/Shared/bootstrap_cmds/bootstrap_cmds/migcom.tproj/mig_errors.h,v 1.1.1.2 2000/01/11 00:36:18 wsanchez Exp $ + * + * HISTORY + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 28-Apr-88 Bennet Yee (bsy) at Carnegie-Mellon University + * Put mig_symtab back. + * + * 2-Dec-87 David Golub (dbg) at Carnegie-Mellon University + * Added MIG_ARRAY_TOO_LARGE. + * + * 25-May-87 Richard Draves (rpd) at Carnegie-Mellon University + * Added definition of death_pill_t. + * + * 31-Jul-86 Michael Young (mwyoung) at Carnegie-Mellon University + * Created. + */ +#ifndef _MIG_ERRORS_H +#define _MIG_ERRORS_H + +#include +#include + +#define MIG_TYPE_ERROR -300 /* Type check failure */ +#define MIG_REPLY_MISMATCH -301 /* Wrong return message ID */ +#define MIG_REMOTE_ERROR -302 /* Server detected error */ +#define MIG_BAD_ID -303 /* Bad message ID */ +#define MIG_BAD_ARGUMENTS -304 /* Server found wrong arguments */ +#define MIG_NO_REPLY -305 /* Server shouldn't reply */ +#define MIG_EXCEPTION -306 /* Server raised exception */ +#define MIG_ARRAY_TOO_LARGE -307 /* User specified array not large enough + to hold returned array */ + +typedef struct { + msg_header_t Head; + msg_type_t RetCodeType; + kern_return_t RetCode; +} death_pill_t; + +typedef struct mig_symtab { + char *ms_routine_name; + int ms_routine_number; +#ifdef hc + void +#else + int +#endif + (*ms_routine)(); +} mig_symtab_t; + +#endif _MIG_ERRORS_H diff --git a/bootstrap_cmds/migcom.tproj/mig_machine.h b/bootstrap_cmds/migcom.tproj/mig_machine.h new file mode 100644 index 0000000..aab5801 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/mig_machine.h @@ -0,0 +1,16 @@ +#if !defined(_MIG_MACHINE_H) +#define _MIG_MACHINE_H + +#define machine_alignment(SZ,ESZ) \ +(((SZ) = ((SZ) + 3) & ~3), (SZ) += (ESZ)) + +#define machine_padding(BYTES) \ +((BYTES & 3) ? (4 - (BYTES & 3)) : 0) + +#ifndef NBBY +#define NBBY 8 +#endif + +#define PACK_MESSAGES TRUE + +#endif diff --git a/bootstrap_cmds/migcom.tproj/migcom.1 b/bootstrap_cmds/migcom.tproj/migcom.1 new file mode 100644 index 0000000..3ade83b --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/migcom.1 @@ -0,0 +1,73 @@ +.TH MIGCOM 1 "Nov 20, 2009" "Apple Computer, Inc." +.SH NAME +migcom \- Mach Interface Generator COMpiler +.SH SYNOPSIS +.B migcom +[ +.I "option \&..." +] +.I " syNumber +%token sySymbolicType +%token syIdentifier +%token syString syQString +%token syFileName +%token syIPCFlag + +%left syPlus syMinus +%left syStar syDiv + + +%type ImportIndicant +%type VarArrayHead ArrayHead StructHead IntExp +%type NamedTypeSpec TransTypeSpec NativeTypeSpec TypeSpec +%type CStringSpec +%type BasicTypeSpec PrevTypeSpec ArgumentType +%type TypePhrase +%type PrimIPCType IPCType +%type RoutineDecl Routine SimpleRoutine +%type Direction TrImplKeyword +%type Argument Trailer Arguments ArgumentList +%type IPCFlags + +%{ + +#include +#include "lexxer.h" +#include "strdefs.h" +#include "type.h" +#include "routine.h" +#include "statement.h" +#include "global.h" +#include "error.h" + +static char *import_name(statement_kind_t sk); +extern int yylex(void); + +/* forward declaration */ +void yyerror(char *s); + +%} + +%union +{ + u_int number; + identifier_t identifier; + string_t string; + statement_kind_t statement_kind; + ipc_type_t *type; + struct + { + u_int innumber; /* msgt_name value, when sending */ + string_t instr; + u_int outnumber; /* msgt_name value, when receiving */ + string_t outstr; + u_int size; /* 0 means there is no default size */ + } symtype; + routine_t *routine; + arg_kind_t direction; + argument_t *argument; + ipc_flags_t flag; +} + +%% + +Statements : /* empty */ + | Statements Statement + ; + +Statement : Subsystem sySemi + | WaitTime sySemi + | SendTime sySemi + | MsgOption sySemi + | UseSpecialReplyPort sySemi + | ConsumeOnSendError sySemi + | UserTypeLimit sySemi + | OnStackLimit sySemi + | Error sySemi + | ServerPrefix sySemi + | UserPrefix sySemi + | ServerDemux sySemi + | TypeDecl sySemi + | RoutineDecl sySemi +{ + statement_t *st = stAlloc(); + + st->stKind = skRoutine; + st->stRoutine = $1; + rtCheckRoutine($1); + if (BeVerbose) + rtPrintRoutine($1); +} + | sySkip sySemi + { rtSkip(); } + | Import sySemi + | RCSDecl sySemi + | sySemi + | error sySemi + { yyerrok; } + ; + +Subsystem : SubsystemStart SubsystemMods + SubsystemName SubsystemBase +{ + if (BeVerbose) { + printf("Subsystem %s: base = %u%s%s\n\n", + SubsystemName, SubsystemBase, + IsKernelUser ? ", KernelUser" : "", + IsKernelServer ? ", KernelServer" : ""); + } +} + ; + +SubsystemStart : sySubsystem +{ + if (SubsystemName != strNULL) { + warn("previous Subsystem decl (of %s) will be ignored", SubsystemName); + IsKernelUser = FALSE; + IsKernelServer = FALSE; + strfree(SubsystemName); + } +} + ; + +SubsystemMods : /* empty */ + | SubsystemMods SubsystemMod + ; + +SubsystemMod : syKernelUser +{ + if (IsKernelUser) + warn("duplicate KernelUser keyword"); + if (!UseMsgRPC) { + warn("with KernelUser the -R option is meaningless"); + UseMsgRPC = TRUE; + } + IsKernelUser = TRUE; +} + | syKernelServer +{ + if (IsKernelServer) + warn("duplicate KernelServer keyword"); + IsKernelServer = TRUE; +} + ; + +SubsystemName : syIdentifier { SubsystemName = $1; } + ; + +SubsystemBase : syNumber { SubsystemBase = $1; } + ; + +MsgOption : LookString syMsgOption syString +{ + if (streql($3, "MACH_MSG_OPTION_NONE")) { + MsgOption = strNULL; + if (BeVerbose) + printf("MsgOption: canceled\n\n"); + } + else { + MsgOption = $3; + if (BeVerbose) + printf("MsgOption %s\n\n",$3); + } +} + ; + +UseSpecialReplyPort : syUseSpecialReplyPort syNumber +{ + UseSpecialReplyPort = ($2 != 0); + HasUseSpecialReplyPort |= UseSpecialReplyPort; +} + ; + +ConsumeOnSendError : LookString syConsumeOnSendError syString +{ + if (strcasecmp($3, "None") == 0) { + ConsumeOnSendError = ConsumeOnSendErrorNone; + } else if (strcasecmp($3, "Timeout") == 0) { + ConsumeOnSendError = ConsumeOnSendErrorTimeout; + HasConsumeOnSendError = TRUE; + } else if (strcasecmp($3, "Any") == 0) { + ConsumeOnSendError = ConsumeOnSendErrorAny; + HasConsumeOnSendError = TRUE; + } else { + error("syntax error"); + } +} + ; + +UserTypeLimit : syUserTypeLimit syNumber + {UserTypeLimit = $2; } + ; +OnStackLimit : syOnStackLimit syNumber + {MaxMessSizeOnStack = $2; } + ; + +WaitTime : LookString syWaitTime syString +{ + WaitTime = $3; + if (BeVerbose) + printf("WaitTime %s\n\n", WaitTime); +} + | syNoWaitTime +{ + WaitTime = strNULL; + if (BeVerbose) + printf("NoWaitTime\n\n"); +} + ; + +SendTime : LookString sySendTime syString +{ + SendTime = $3; + if (BeVerbose) + printf("SendTime %s\n\n", SendTime); +} + | syNoSendTime +{ + SendTime = strNULL; + if (BeVerbose) + printf("NoSendTime\n\n"); +} + ; + +Error : syErrorProc syIdentifier +{ + ErrorProc = $2; + if (BeVerbose) + printf("ErrorProc %s\n\n", ErrorProc); +} + ; + +ServerPrefix : syServerPrefix syIdentifier +{ + ServerPrefix = $2; + if (BeVerbose) + printf("ServerPrefix %s\n\n", ServerPrefix); +} + ; + +UserPrefix : syUserPrefix syIdentifier +{ + UserPrefix = $2; + if (BeVerbose) + printf("UserPrefix %s\n\n", UserPrefix); +} + ; + +ServerDemux : syServerDemux syIdentifier +{ + ServerDemux = $2; + if (BeVerbose) + printf("ServerDemux %s\n\n", ServerDemux); +} + ; + +Import : LookFileName ImportIndicant syFileName +{ + statement_t *st = stAlloc(); + st->stKind = $2; + st->stFileName = $3; + + if (BeVerbose) + printf("%s %s\n\n", import_name($2), $3); +} + ; + +ImportIndicant : syImport { $$ = skImport; } + | syUImport { $$ = skUImport; } + | sySImport { $$ = skSImport; } + | syIImport { $$ = skIImport; } + | syDImport { $$ = skDImport; } + ; + +RCSDecl : LookQString syRCSId syQString +{ + if (RCSId != strNULL) + warn("previous RCS decl will be ignored"); + if (BeVerbose) + printf("RCSId %s\n\n", $3); + RCSId = $3; +} + ; + +TypeDecl : syType NamedTypeSpec +{ + identifier_t name = $2->itName; + + if (itLookUp(name) != itNULL) + warn("overriding previous definition of %s", name); + itInsert(name, $2); +} + ; + +NamedTypeSpec : syIdentifier syEqual TransTypeSpec + { itTypeDecl($1, $$ = $3); } + ; + +TransTypeSpec : TypeSpec + { $$ = itResetType($1); } + | TransTypeSpec syInTran syColon syIdentifier + syIdentifier syLParen syIdentifier syRParen +{ + $$ = $1; + + if (($$->itTransType != strNULL) && !streql($$->itTransType, $4)) + warn("conflicting translation types (%s, %s)", $$->itTransType, $4); + $$->itTransType = $4; + + if (($$->itInTrans != strNULL) && !streql($$->itInTrans, $5)) + warn("conflicting in-translation functions (%s, %s)", $$->itInTrans, $5); + $$->itInTrans = $5; + + if (($$->itServerType != strNULL) && !streql($$->itServerType, $7)) + warn("conflicting server types (%s, %s)", $$->itServerType, $7); + $$->itServerType = $7; +} + | TransTypeSpec syOutTran syColon syIdentifier + syIdentifier syLParen syIdentifier syRParen +{ + $$ = $1; + + if (($$->itServerType != strNULL) && !streql($$->itServerType, $4)) + warn("conflicting server types (%s, %s)", $$->itServerType, $4); + $$->itServerType = $4; + + if (($$->itOutTrans != strNULL) && !streql($$->itOutTrans, $5)) + warn("conflicting out-translation functions (%s, %s)", $$->itOutTrans, $5); + $$->itOutTrans = $5; + + if (($$->itTransType != strNULL) && !streql($$->itTransType, $7)) + warn("conflicting translation types (%s, %s)", $$->itTransType, $7); + $$->itTransType = $7; +} + | TransTypeSpec syDestructor syColon syIdentifier + syLParen syIdentifier syRParen +{ + $$ = $1; + + if (($$->itDestructor != strNULL) && !streql($$->itDestructor, $4)) + warn("conflicting destructor functions (%s, %s)", $$->itDestructor, $4); + $$->itDestructor = $4; + + if (($$->itTransType != strNULL) && !streql($$->itTransType, $6)) + warn("conflicting translation types (%s, %s)", $$->itTransType, $6); + $$->itTransType = $6; +} + | TransTypeSpec syCType syColon syIdentifier +{ + $$ = $1; + + if (($$->itUserType != strNULL) && !streql($$->itUserType, $4)) + warn("conflicting user types (%s, %s)", $$->itUserType, $4); + $$->itUserType = $4; + + if (($$->itServerType != strNULL) && !streql($$->itServerType, $4)) + warn("conflicting server types (%s, %s)", $$->itServerType, $4); + $$->itServerType = $4; +} + | TransTypeSpec syCUserType syColon syIdentifier +{ + $$ = $1; + + if (($$->itUserType != strNULL) && !streql($$->itUserType, $4)) + warn("conflicting user types (%s, %s)", $$->itUserType, $4); + $$->itUserType = $4; +} + | TransTypeSpec syCServerType + syColon syIdentifier +{ + $$ = $1; + + if (($$->itServerType != strNULL) && !streql($$->itServerType, $4)) + warn("conflicting server types (%s, %s)", + $$->itServerType, $4); + $$->itServerType = $4; +} + ; + +TypeSpec : BasicTypeSpec + { $$ = $1; } + | PrevTypeSpec + { $$ = $1; } + | VarArrayHead TypeSpec + { $$ = itVarArrayDecl($1, $2); } + | ArrayHead TypeSpec + { $$ = itArrayDecl($1, $2); } + | syCaret TypeSpec + { $$ = itPtrDecl($2); } + | StructHead TypeSpec + { $$ = itStructDecl($1, $2); } + | CStringSpec + { $$ = $1; } + | NativeTypeSpec + { $$ = $1; } + ; + +NativeTypeSpec : syPointerTo syLParen TypePhrase syRParen + { $$ = itNativeType($3, TRUE, 0); } + | syPointerToIfNot syLParen TypePhrase syComma + TypePhrase syRParen + { $$ = itNativeType($3, TRUE, $5); } + | syValueOf syLParen TypePhrase syRParen + { $$ = itNativeType($3, FALSE, 0); } + ; + +BasicTypeSpec : IPCType +{ + $$ = itShortDecl($1.innumber, $1.instr, + $1.outnumber, $1.outstr, + $1.size); +} + | syLParen IPCType syComma IntExp + IPCFlags syRParen +{ + error("Long form type declarations aren't allowed any longer\n"); +} + ; + +PrimIPCType : syNumber +{ + $$.innumber = $$.outnumber = $1; + $$.instr = $$.outstr = strNULL; + $$.size = 0; +} + | sySymbolicType + { $$ = $1; } + ; + +IPCType : PrimIPCType + { $$ = $1; } + | PrimIPCType syBar PrimIPCType +{ + if ($1.size != $3.size) { + if ($1.size == 0) + $$.size = $3.size; + else if ($3.size == 0) + $$.size = $1.size; + else { + error("sizes in IPCTypes (%d, %d) aren't equal", + $1.size, $3.size); + $$.size = 0; + } + } + else + $$.size = $1.size; + $$.innumber = $1.innumber; + $$.instr = $1.instr; + $$.outnumber = $3.outnumber; + $$.outstr = $3.outstr; +} + ; + +PrevTypeSpec : syIdentifier + { $$ = itPrevDecl($1); } + ; + +VarArrayHead : syArray syLBrack syRBrack syOf + { $$ = 0; } + | syArray syLBrack syStar syRBrack syOf + { $$ = 0; } + | syArray syLBrack syStar syColon IntExp + syRBrack syOf + { $$ = $5; } + ; + +ArrayHead : syArray syLBrack IntExp syRBrack syOf + { $$ = $3; } + ; + +StructHead : syStruct syLBrack IntExp syRBrack syOf + { $$ = $3; } + ; + +CStringSpec : syCString syLBrack IntExp syRBrack + { $$ = itCStringDecl($3, FALSE); } + | syCString syLBrack syStar syColon + IntExp syRBrack + { $$ = itCStringDecl($5, TRUE); } + ; + +TypePhrase : syIdentifier + { $$ = $1; } + | TypePhrase syIdentifier + { $$ = strphrase($1, $2); strfree($2); } + ; + +IntExp : IntExp syPlus IntExp + { $$ = $1 + $3; } + | IntExp syMinus IntExp + { $$ = $1 - $3; } + | IntExp syStar IntExp + { $$ = $1 * $3; } + | IntExp syDiv IntExp + { $$ = $1 / $3; } + | syNumber + { $$ = $1; } + | syLParen IntExp syRParen + { $$ = $2; } + ; + + +RoutineDecl : Routine { $$ = $1; } + | SimpleRoutine { $$ = $1; } + ; + +Routine : syRoutine syIdentifier Arguments + { $$ = rtMakeRoutine($2, $3); } + ; + +SimpleRoutine : sySimpleRoutine syIdentifier Arguments + { $$ = rtMakeSimpleRoutine($2, $3); } + ; + +Arguments : syLParen syRParen + { $$ = argNULL; } + | syLParen ArgumentList syRParen + { $$ = $2; } + + ; + +ArgumentList : Argument + { $$ = $1; } + | Trailer + { $$ = $1; } + | Argument sySemi ArgumentList +{ + $$ = $1; + $$->argNext = $3; +} + | Trailer sySemi ArgumentList +{ + $$ = $1; + $$->argNext = $3; +} + ; + +Argument : Direction syIdentifier ArgumentType IPCFlags +{ + $$ = argAlloc(); + $$->argKind = $1; + $$->argName = $2; + $$->argType = $3; + $$->argFlags = $4; + if ($3 && $3->itNative) { + if ($1 != akIn && $1 != akOut && $1 != akInOut) + error("Illegal direction specified"); + + if (!($3->itNativePointer) && $1 != akIn) + error("ValueOf only valid for in"); + + if (($3->itBadValue) != NULL && $1 != akIn) + error("PointerToIfNot only valid for in"); + } +} + ; + +Trailer : TrImplKeyword syIdentifier ArgumentType +{ + $$ = argAlloc(); + $$->argKind = $1; + $$->argName = $2; + $$->argType = $3; +} + ; + + +Direction : /* empty */ { $$ = akNone; } + | syIn { $$ = akIn; } + | syOut { $$ = akOut; } + | syInOut { $$ = akInOut; } + | syRequestPort { $$ = akRequestPort; } + | syReplyPort { $$ = akReplyPort; } + | sySReplyPort { $$ = akSReplyPort; } + | syUReplyPort { $$ = akUReplyPort; } + | syWaitTime { $$ = akWaitTime; } + | sySendTime { $$ = akSendTime; } + | syMsgOption { $$ = akMsgOption; } + | sySecToken { $$ = akSecToken; } + | syServerSecToken { $$ = akServerSecToken; } + | syUserSecToken { $$ = akUserSecToken; } + | syAuditToken { $$ = akAuditToken; } + | syServerAuditToken { $$ = akServerAuditToken; } + | syUserAuditToken { $$ = akUserAuditToken; } + | syServerContextToken { $$ = akServerContextToken; } + | syMsgSeqno { $$ = akMsgSeqno; } + ; + + + +TrImplKeyword : syServerImpl { $$ = akServerImpl; } + | syUserImpl { $$ = akUserImpl; } + ; + + +ArgumentType : syColon syIdentifier +{ + $$ = itLookUp($2); + if ($$ == itNULL) + error("type '%s' not defined", $2); +} + | syColon NamedTypeSpec + { $$ = $2; } + | syColon NativeTypeSpec + { $$ = $2; } + ; + +IPCFlags : /* empty */ + { $$ = flNone; } + | IPCFlags syComma syIPCFlag +{ + if ($1 & $3) + warn("redundant IPC flag ignored"); + else + $$ = $1 | $3; +} + | IPCFlags syComma syIPCFlag syLBrack syRBrack +{ + if ($3 != flDealloc) + warn("only Dealloc is variable"); + else + $$ = $1 | flMaybeDealloc; +} + +LookString : /* empty */ + { LookString(); } + ; + +LookFileName : /* empty */ + { LookFileName(); } + ; + +LookQString : /* empty */ + { LookQString(); } + ; + +%% + +void +yyerror(char *s) +{ + error(s); +} + +static char * +import_name(statement_kind_t sk) +{ + switch (sk) { + + case skImport: + return "Import"; + + case skSImport: + return "SImport"; + + case skUImport: + return "UImport"; + + case skIImport: + return "IImport"; + + case skDImport: + return "DImport"; + + default: + fatal("import_name(%d): not import statement", (int) sk); + /*NOTREACHED*/ + return strNULL; + } +} diff --git a/bootstrap_cmds/migcom.tproj/routine.c b/bootstrap_cmds/migcom.tproj/routine.c new file mode 100644 index 0000000..f4c0778 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/routine.c @@ -0,0 +1,1844 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include "type.h" + +#include +#include +#include "mig_machine.h" +#include "error.h" +#include "alloc.h" +#include "global.h" +#include "routine.h" +#include "write.h" + +u_int rtNumber = 0; + +static void rtSizeDelta(FILE *file, u_int mask, routine_t *rt); + +routine_t * +rtAlloc(void) +{ + routine_t *new; + + new = (routine_t *) calloc(1, sizeof *new); + if (new == rtNULL) + fatal("rtAlloc(): %s", strerror(errno)); + new->rtNumber = rtNumber++; + new->rtName = strNULL; + new->rtErrorName = strNULL; + new->rtUserName = strNULL; + new->rtServerName = strNULL; + + return new; +} + +void +rtSkip(void) +{ + rtNumber++; +} + +argument_t * +argAlloc(void) +{ + extern void KPD_error(FILE *file, argument_t *arg); + + static argument_t prototype = + { + .argName = strNULL, + .argNext = argNULL, + .argKind = akNone, + .argType = itNULL, + .argKPD_Type = argKPD_NULL, + .argKPD_Template = (void(*)(FILE *, argument_t *, boolean_t))KPD_error, + .argKPD_Init = KPD_error, + .argKPD_Pack = KPD_error, + .argKPD_Extract = KPD_error, + .argKPD_TypeCheck = KPD_error, + .argVarName = strNULL, + .argMsgField = strNULL, + .argTTName = strNULL, + .argPadName = strNULL, + .argSuffix = strNULL, + .argFlags = flNone, + .argDeallocate = d_NO, + .argCountInOut = FALSE, + .argRoutine = rtNULL, + .argCount = argNULL, + .argSubCount = argNULL, + .argCInOut = argNULL, + .argPoly = argNULL, + .argDealloc = argNULL, + .argSameCount = argNULL, + .argParent = argNULL, + .argMultiplier = 1, + .argRequestPos = 0, + .argReplyPos = 0, + .argByReferenceUser = FALSE, + .argByReferenceServer = FALSE, + .argTempOnStack = FALSE + }; + argument_t *new; + + new = (argument_t *) malloc(sizeof *new); + if (new == argNULL) + fatal("argAlloc(): %s", strerror(errno)); + *new = prototype; + return new; +} + +routine_t * +rtMakeRoutine(identifier_t name, argument_t *args) +{ + routine_t *rt = rtAlloc(); + + rt->rtName = name; + rt->rtKind = rkRoutine; + rt->rtArgs = args; + + return rt; +} + +routine_t * +rtMakeSimpleRoutine(identifier_t name, argument_t *args) +{ + routine_t *rt = rtAlloc(); + + rt->rtName = name; + rt->rtKind = rkSimpleRoutine; + rt->rtArgs = args; + + return rt; +} + +char * +rtRoutineKindToStr(routine_kind_t rk) +{ + switch (rk) { + + case rkRoutine: + return "Routine"; + + case rkSimpleRoutine: + return "SimpleRoutine"; + + default: + fatal("rtRoutineKindToStr(%d): not a routine_kind_t", rk); + /*NOTREACHED*/ + return strNULL; + } +} + +static void +rtPrintArg(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + if (!akCheck(arg->argKind, akbUserArg|akbServerArg) || + (akIdent(arg->argKind) == akeCount) || + (akIdent(arg->argKind) == akeDealloc) || + (akIdent(arg->argKind) == akeNdrCode) || + (akIdent(arg->argKind) == akePoly)) + return; + + printf("\n\t"); + + switch (akIdent(arg->argKind)) { + + case akeRequestPort: + printf("RequestPort"); + break; + + case akeReplyPort: + printf("ReplyPort"); + break; + + case akeWaitTime: + printf("WaitTime"); + break; + + case akeSendTime: + printf("SendTime"); + break; + + case akeMsgOption: + printf("MsgOption"); + break; + + case akeMsgSeqno: + printf("MsgSeqno\t"); + break; + + case akeSecToken: + printf("SecToken\t"); + break; + + case akeAuditToken: + printf("AuditToken\t"); + break; + + case akeContextToken: + printf("ContextToken\t"); + break; + + case akeImplicit: + printf("Implicit\t"); + break; + + default: + if (akCheck(arg->argKind, akbRequest)) { + if (akCheck(arg->argKind, akbSend)) + printf("In"); + else + printf("(In)"); + } + if (akCheck(arg->argKind, akbReply)) { + if (akCheck(arg->argKind, akbReturn)) + printf("Out"); + else + printf("(Out)"); + } + printf("\t"); + } + + printf("\t%s: %s", arg->argName, it->itName); + + if (arg->argDeallocate == d_YES) + printf(", Dealloc"); + else if (arg->argDeallocate == d_MAYBE) + printf(", Dealloc[]"); + + if (arg->argCountInOut) + printf(", CountInOut"); + + if (arg->argFlags & flSameCount) + printf(", SameCount"); + + if (arg->argFlags & flPhysicalCopy) + printf(", PhysicalCopy"); + + if (arg->argFlags & flRetCode) + printf(", PhysicalCopy"); + + if (arg->argFlags & flOverwrite) + printf(", Overwrite"); + + if (arg->argFlags & flAuto) + printf(", Auto"); + + if (arg->argFlags & flConst) + printf(", Const"); +} + +void +rtPrintRoutine(routine_t *rt) +{ + argument_t *arg; + + printf("%s (%d) %s(", rtRoutineKindToStr(rt->rtKind), rt->rtNumber, rt->rtName); + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + rtPrintArg(arg); + + printf(")\n"); + printf("\n"); +} + +/* + * Determines appropriate value of msg-simple for the message. + * One version for both In & Out. + */ + +static void +rtCheckSimple(argument_t *args, u_int mask, boolean_t *simple) +{ + argument_t *arg; + boolean_t MustBeComplex = FALSE; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, mask)) { + ipc_type_t *it = arg->argType; + + if (IS_KERN_PROC_DATA(it)) + MustBeComplex = TRUE; + } + + *simple = !MustBeComplex; +} + +static void +rtCheckFit(routine_t *rt, u_int mask, boolean_t *fitp, boolean_t *uselimp, u_int *knownp) +{ + boolean_t uselim = FALSE; + argument_t *arg; + u_int size = sizeof(mach_msg_header_t); + + if (!rt->rtSimpleRequest) + machine_alignment(size,sizeof(mach_msg_body_t)); + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, mask)) { + ipc_type_t *it = arg->argType; + + machine_alignment(size, it->itMinTypeSize); + if (it->itNative) + uselim = TRUE; + else if (IS_VARIABLE_SIZED_UNTYPED(it)) { + machine_alignment(size, it->itTypeSize); + size += it->itPadSize; + } + } + *knownp = size; + if (MaxMessSizeOnStack == -1) { + *fitp = TRUE; + *uselimp = FALSE; + } + else if (size > MaxMessSizeOnStack) { + *fitp = FALSE; + *uselimp = FALSE; + } + else if (!uselim) { + *fitp = TRUE; + *uselimp = FALSE; + } + else if (UserTypeLimit == -1) { + *fitp = FALSE; + *uselimp = FALSE; + } + else if (size + UserTypeLimit > MaxMessSizeOnStack) { + *fitp = FALSE; + *uselimp = TRUE; + } + else { + *fitp = TRUE; + *uselimp = TRUE; + } +} + +static void +rtFindHowMany(routine_t *rt) +{ + argument_t *arg; + int multiplier = 1; + boolean_t test; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if (IS_MULTIPLE_KPD(it)) { + if (!it->itVarArray) + multiplier = it->itKPD_Number; + test = !it->itVarArray && !it->itElement->itVarArray; + it = it->itElement; + } + else + test = !it->itVarArray; + + if (akCheck(arg->argKind, akbSendKPD)) { + + if (it->itInLine) + rt->rtCountPortsIn += it->itNumber * multiplier; + else if (it->itPortType) { + if (test) + rt->rtCountOolPortsIn += it->itNumber * multiplier; + } + else { + if (test) + rt->rtCountOolIn += (it->itNumber * it->itSize + 7)/8 * multiplier; + } + } + if (akCheckAll(arg->argKind, akbReturnKPD)) { + if (it->itInLine) + rt->rtCountPortsOut += it->itNumber * multiplier; + else if (it->itPortType) { + if (test) + rt->rtCountOolPortsOut += it->itNumber * multiplier; + } + else { + if (test) + rt->rtCountOolOut += ((it->itNumber * it->itSize + 7)/8) * multiplier; + } + } + } +} + +boolean_t +rtCheckMask(argument_t *args, u_int mask) +{ + argument_t *arg; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) + return TRUE; + return FALSE; +} + +boolean_t +rtCheckMaskFunction(argument_t *args, u_int mask, boolean_t (*func)(argument_t *arg)) +{ + argument_t *arg; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) + if ((*func)(arg)) + return TRUE; + return FALSE; +} + + +int +rtCountKPDs(argument_t *args, u_int mask) +{ + argument_t *arg; + int count = 0; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) + count += arg->argType->itKPD_Number; + return count; +} + +int +rtCountFlags(argument_t *args, u_int flag) +{ + argument_t *arg; + int count = 0; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (arg->argFlags & flag) + count++; + return count; +} + +int +rtCountArgDescriptors(argument_t *args, int *argcount) +{ + argument_t *arg; + int count = 0; + + if (argcount) + *argcount = 0; + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, akbServerArg)) { + if (RPCFixedArray(arg) || + RPCPort(arg) || + RPCVariableArray(arg) || + RPCPortArray(arg)) { + count++; + if (argcount) + (*argcount)++; + } + else { + if (argcount) { + if (arg->argType->itStruct && arg->argType->itNumber && + (arg->argType->itSize >= 32)) + *argcount += arg->argType->itNumber * (arg->argType->itSize / 32); + else + (*argcount)++; + } + } + } + return count; +} + +int +rtCountMask(argument_t *args, u_int mask) +{ + argument_t *arg; + int count = 0; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) + count++; + return count; +} + +/* arg->argType may be NULL in this function */ + +static void +rtDefaultArgKind(routine_t *rt, argument_t *arg) +{ + if ((arg->argKind == akNone) && (rt->rtRequestPort == argNULL)) + arg->argKind = akRequestPort; + + if (arg->argKind == akNone) + arg->argKind = akIn; +} + +/* + * Initializes arg->argDeallocate, + * arg->argCountInOut from arg->argFlags + * and perform consistency check over the + * flags. + */ + +static ipc_flags_t +rtProcessDeallocFlag(ipc_type_t *it, ipc_flags_t flags, arg_kind_t kind, dealloc_t *what, string_t name) +{ + + /* only one of flDealloc, flNotDealloc, flMaybeDealloc */ + + if (flags & flMaybeDealloc) { + if (flags & (flDealloc|flNotDealloc)) { + warn("%s: Dealloc and NotDealloc ignored with Dealloc[]", name); + flags &= ~(flDealloc|flNotDealloc); + } + } + + if ((flags&(flDealloc|flNotDealloc)) == (flDealloc|flNotDealloc)) { + warn("%s: Dealloc and NotDealloc cancel out", name); + flags &= ~(flDealloc|flNotDealloc); + } + + if (((IsKernelServer && akCheck(kind, akbReturn)) || + (IsKernelUser && akCheck(kind, akbSend))) && + (flags & flDealloc)) { + /* + * For a KernelServer interface and an Out argument, + * or a KernelUser interface and an In argument, + * we avoid a possible spurious warning about the deallocate bit. + * For compatibility with Mach 2.5, the deallocate bit + * may need to be enabled on some inline arguments. + */ + + *what= d_YES; + } + else if (flags & (flMaybeDealloc|flDealloc)) { + /* only give semantic warnings if the user specified something */ + if (it->itInLine && !it->itPortType) { + warn("%s: Dealloc is ignored: it is meaningless for that type of argument", name); + flags &= ~(flMaybeDealloc|flDealloc); + } + else + *what = (flags & flMaybeDealloc) ? d_MAYBE : d_YES; + } + return flags; +} + +static void +rtProcessSameCountFlag(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + ipc_flags_t flags = arg->argFlags; + string_t name = arg->argVarName; + static argument_t *old_arg; + + if (flags & flSameCount) { + if (!it->itVarArray) { + warn("%s: SameCount is ignored - the argument is not variable", name); + flags &= ~flSameCount; + } + if (old_arg) { + if (old_arg->argParent) + old_arg = old_arg->argParent; + if (old_arg->argSameCount) + old_arg = old_arg->argSameCount; + + if (!old_arg->argType->itVarArray) { + warn("%s: SameCount is ignored - adjacent argument is not variable", name); + flags &= ~flSameCount; + } + +#define SAMECOUNT_MASK akeBITS|akbSend|akbReturn|akbRequest|akbReply|akbUserArg|akbServerArg + if (akCheck(old_arg->argKind, SAMECOUNT_MASK) != + akCheck(arg->argKind, SAMECOUNT_MASK) || + old_arg->argCountInOut != arg->argCountInOut) { + warn("%s: SameCount is ignored - inconsistencies with the adjacent argument\n", name); + flags &= ~flSameCount; + } + arg->argSameCount = old_arg; + } + arg->argFlags = flags; + } + old_arg = arg; +} + +static ipc_flags_t +rtProcessCountInOutFlag(ipc_type_t *it, ipc_flags_t flags, arg_kind_t kind, boolean_t *what, string_t name) +{ + if (flags & flCountInOut) { + if (!akCheck(kind, akbReply)) { + warn("%s: CountInOut is ignored: argument must be Out\n", name); + flags &= ~flCountInOut; + } + else if (!it->itVarArray || !it->itInLine) { + warn("%s: CountInOut is ignored: argument isn't variable or in-line\n", name); + flags &= ~flCountInOut; + } + else + *what = TRUE; + } + return flags; +} + +static ipc_flags_t +rtProcessPhysicalCopyFlag(ipc_type_t *it, ipc_flags_t flags, arg_kind_t kind, string_t name) +{ + if (flags & flPhysicalCopy) { + if (it->itInLine) { + warn("%s: PhysicalCopy is ignored, argument copied inline anyway", name); + flags &= ~flPhysicalCopy; + } + if (it->itPortType) { + warn("%s: PhysicalCopy is ignored, it does not apply to ports and array of ports", name); + flags &= ~flPhysicalCopy; + } + } + return flags; +} + +static void +rtProcessRetCodeFlag(argument_t *thisarg) +{ + ipc_type_t *it = thisarg->argType; + ipc_flags_t flags = thisarg->argFlags; + string_t name = thisarg->argVarName; + routine_t *thisrout = thisarg->argRoutine; + + if (flags & flRetCode) { + if (!it->itInLine || !it->itStruct || + it->itSize != 32 || it->itNumber != 1) { + warn("%s: RetCode is ignored - the type doesn't match a MIG RetCode", name); + flags &= ~flRetCode; + } + else if (thisrout->rtKind != rkSimpleRoutine) { + fatal("%s: RetCode is allowed only for SimpleRoutines", name); + } + else if (thisrout->rtRetCArg != argNULL) { + warn("%s: RetCode is ignored - only one argument can be flagged as RetCode", name); + flags &= ~flRetCode; + } + else { + thisrout->rtRetCArg = thisarg; + } + thisarg->argFlags = flags; + } +} + +static ipc_flags_t +rtProcessOverwriteFlag(ipc_type_t *it, ipc_flags_t flags, arg_kind_t kind, string_t name) +{ + if (flags & flOverwrite) + if (it->itInLine || it->itMigInLine || + /* among In, Out, InOut, we want only the Out! */ + !akCheck(kind, akbReturn) || akCheck(kind, akbSend)) { + warn("%s: Overwrite is ignored - it must be Out AND Ool!", name); + flags &= ~flOverwrite; + } + return flags; +} + +static void +rtDetectKPDArg(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *string; + + if (IS_KERN_PROC_DATA(it)) { + if (akCheck(arg->argKind, akbSendBody)) { + arg->argKind = akRemFeature(arg->argKind, akbSendBody); + arg->argKind = akAddFeature(arg->argKind, akbSendKPD); + } + if (akCheck(arg->argKind, akbReturnBody)) { + arg->argKind = akRemFeature(arg->argKind, akbReturnBody); + arg->argKind = akAddFeature(arg->argKind, akbReturnKPD); + } + if (it->itInLine) { + string = "mach_msg_port_descriptor_t"; + arg->argKPD_Type = MACH_MSG_PORT_DESCRIPTOR; + } + else if (it->itPortType) { + string = "mach_msg_ool_ports_descriptor_t"; + arg->argKPD_Type = MACH_MSG_OOL_PORTS_DESCRIPTOR; + } + else { + string = "mach_msg_ool_descriptor_t"; + arg->argKPD_Type = MACH_MSG_OOL_DESCRIPTOR; + } + it->itKPDType = string; + } +} + +static void +rtAugmentArgKind(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + /* akbVariable means variable-sized inline */ + + if (IS_VARIABLE_SIZED_UNTYPED(it)) { + if (akCheckAll(arg->argKind, akbRequest|akbReply)) + error("%s: Inline variable-sized arguments can't be InOut", arg->argName); + arg->argKind = akAddFeature(arg->argKind, akbVariable); + } + if (IS_OPTIONAL_NATIVE(it)) + arg->argKind = akAddFeature(arg->argKind, akbVariable); + + /* + * Need to use a local variable in the following cases: + * 1) There is a translate-out function & the argument is being + * returned. We need to translate it before it hits the message. + * 2) There is a translate-in function & the argument is + * sent and returned. We need a local variable for its address. + * 3) There is a destructor function, which will be used + * (SendRcv and not ReturnSnd), and there is a translate-in + * function whose value must be saved for the destructor. + * 4) This is Complex KPD (array of KPD), and as such it has to + * be copied to a local array in input and output + * 5) Both poly and dealloc generate warnings compile time, because + * we attempt to take address of bit-field structure member + */ + + if ( + ((it->itOutTrans != strNULL) && akCheck(arg->argKind, akbReturnSnd)) || + ((it->itInTrans != strNULL) && akCheckAll(arg->argKind, akbSendRcv|akbReturnSnd)) || + ((it->itDestructor != strNULL) && akCheck(arg->argKind, akbSendRcv) && !akCheck(arg->argKind, akbReturnSnd) && (it->itInTrans != strNULL)) || + (IS_MULTIPLE_KPD(it)) || + ((akIdent(arg->argKind) == akePoly) && akCheck(arg->argKind, akbReturnSnd)) || + ((akIdent(arg->argKind) == akeDealloc) && akCheck(arg->argKind, akbReturnSnd)) + ) { + arg->argKind = akRemFeature(arg->argKind, akbReplyCopy); + arg->argKind = akAddFeature(arg->argKind, akbVarNeeded); + } +} + +/* + * The Suffix allows to handle KPDs as normal data. + * it is used in InArgMsgField. + */ +static void +rtSuffixExtArg(argument_t *args) +{ + argument_t *arg; + char *subindex; + char string[MAX_STR_LEN]; + + for (arg = args; arg != argNULL; arg = arg->argNext) { + if (akCheck(arg->argKind, akbSendKPD | akbReturnKPD)) { + if (IS_MULTIPLE_KPD(arg->argType)) + subindex = "[0]"; + else + subindex = ""; + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + (void)sprintf(string, "%s.name", subindex); + break; + + case MACH_MSG_OOL_DESCRIPTOR: + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + (void)sprintf(string, "%s.address", subindex); + break; + + default: + error("Type of kernel processed data unknown\n"); + } + arg->argSuffix = strconcat(arg->argMsgField, string); + /* see above the list of VarNeeded cases */ + /* + * argCount has been removed from the VarNeeded list, + * because VarSize arrays have their Count in the untyped + * section of the message, and because it is not possible + * to move anything in-line/out-of-line + */ + } + else if (akIdent(arg->argKind) == akePoly && + akCheck(arg->argParent->argKind, akbSendKPD | akbReturnKPD)) { + argument_t *par_arg = arg->argParent; + + if (IS_MULTIPLE_KPD(par_arg->argType)) + subindex = "[0]"; + else + subindex = ""; + switch (par_arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + (void)sprintf(string, "%s.disposition", subindex); + arg->argSuffix = strconcat(par_arg->argMsgField, string); + break; + + default: + error("Type of kernel processed data inconsistent\n"); + } + } + else if (akIdent(arg->argKind) == akeDealloc && + akCheck(arg->argParent->argKind, akbSendKPD | akbReturnKPD)) { + argument_t *par_arg = arg->argParent; + + if (IS_MULTIPLE_KPD(par_arg->argType)) + subindex = "[0]"; + else + subindex = ""; + switch (par_arg->argKPD_Type) { + + case MACH_MSG_OOL_DESCRIPTOR: + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + (void)sprintf(string, "%s.deallocate", subindex); + arg->argSuffix = strconcat(par_arg->argMsgField, string); + break; + + default: + error("Type of kernel processed data inconsistent\n"); + } + } + } +} + +/* arg->argType may be NULL in this function */ + +static void +rtCheckRoutineArg(routine_t *rt, argument_t *arg) +{ + switch (akIdent(arg->argKind)) { + + case akeRequestPort: + if (rt->rtRequestPort != argNULL) + warn("multiple RequestPort args in %s; %s won't be used", rt->rtName, rt->rtRequestPort->argName); + rt->rtRequestPort = arg; + break; + + case akeReplyPort: + if (rt->rtReplyPort != argNULL) + warn("multiple ReplyPort args in %s; %s won't be used", rt->rtName, rt->rtReplyPort->argName); + rt->rtReplyPort = arg; + break; + + case akeWaitTime: + if (rt->rtWaitTime != argNULL) + warn("multiple WaitTime/SendTime type args in %s; %s won't be used", rt->rtName, rt->rtWaitTime->argName); + rt->rtWaitTime = arg; + break; + + case akeSendTime: + if (rt->rtWaitTime != argNULL) { + if (akIdent(rt->rtWaitTime->argKind) == akeWaitTime) { + warn("SendTime type argument after a WaitTime in %s; SendTime %s won't be used", rt->rtName, arg->argName); + break; + } else { + warn("multiple SendTime type args in %s; %s won't be used", rt->rtName, rt->rtWaitTime->argName); + } + } + rt->rtWaitTime = arg; + break; + + case akeMsgOption: + if (rt->rtMsgOption != argNULL) + warn("multiple MsgOption args in %s; %s won't be used", rt->rtName, rt->rtMsgOption->argName); + rt->rtMsgOption = arg; + break; + + default: + break; + } +} + +/* arg->argType may be NULL in this function */ + +static void +rtSetArgDefaults(routine_t *rt, argument_t *arg) +{ + arg->argRoutine = rt; + if (arg->argVarName == strNULL) + arg->argVarName = arg->argName; + if (arg->argMsgField == strNULL) + switch(akIdent(arg->argKind)) { + + case akeRequestPort: + arg->argMsgField = "Head.msgh_request_port"; + break; + + case akeReplyPort: + arg->argMsgField = "Head.msgh_reply_port"; + break; + + case akeNdrCode: + arg->argMsgField = "NDR"; + break; + + case akeSecToken: + arg->argMsgField = "msgh_sender"; + break; + + case akeAuditToken: + arg->argMsgField = "msgh_audit"; + break; + + case akeContextToken: + arg->argMsgField = "msgh_context"; + break; + + case akeMsgSeqno: + arg->argMsgField = "msgh_seqno"; + break; + + case akeImplicit: + /* the field is set directly by Yacc */ + break; + + default: + arg->argMsgField = arg->argName; + break; + } + + if (arg->argTTName == strNULL) + arg->argTTName = strconcat(arg->argName, "Template"); + if (arg->argPadName == strNULL) + arg->argPadName = strconcat(arg->argName, "Pad"); + + /* + * The poly args for the request and reply ports have special defaults, + * because their msg-type-name values aren't stored in normal fields. + */ + + if ((rt->rtRequestPort != argNULL) && + (rt->rtRequestPort->argPoly == arg) && + (arg->argType != itNULL)) { + arg->argMsgField = "Head.msgh_bits"; + arg->argType->itInTrans = "MACH_MSGH_BITS_REQUEST"; + } + + if ((rt->rtReplyPort != argNULL) && + (rt->rtReplyPort->argPoly == arg) && + (arg->argType != itNULL)) { + arg->argMsgField = "Head.msgh_bits"; + arg->argType->itInTrans = "MACH_MSGH_BITS_REPLY"; + } +} + +static void +rtAddCountArg(argument_t *arg) +{ + argument_t *count, *master; + ipc_type_t *it = arg->argType; + + count = argAlloc(); + + if (IS_MULTIPLE_KPD(it) && it->itElement->itVarArray) { + count->argName = strconcat(arg->argName, "Subs"); + count->argType = itMakeSubCountType(it->itKPD_Number, it->itVarArray, arg->argVarName); + count->argKind = akeSubCount; + arg->argSubCount = count; + } + else { + count->argName = strconcat(arg->argName, "Cnt"); + count->argType = itMakeCountType(); + count->argKind = akeCount; + arg->argCount = count; + if (arg->argParent != argNULL) { + /* this is the case where we are at the second level of recursion: + we want the Parent to access it through argCount */ + arg->argParent->argCount = count; + } + } + master = (arg->argParent != argNULL) ? arg->argParent : arg; + if (IS_MULTIPLE_KPD(master->argType)) + count->argMultiplier = 1; + else + count->argMultiplier = it->itElement->itNumber; + count->argParent = arg; + count->argNext = arg->argNext; + arg->argNext = count; + + if (arg->argType->itString) { + /* C String gets no Count argument on either side, but are still in the msg */ + count->argKind = akAddFeature(count->argKind, akCheck(arg->argKind, akbSend) ? akbSendRcv : akbReturnRcv); + count->argVarName = (char *)0; + } + else { + /* + * Count arguments have to be present on the message body (NDR encoded) + * akbVariable has to be turned down, has it foul the algorithm + * for detecting the in-line variable sized arrays + */ + count->argKind |= akAddFeature(akbUserArg|akbServerArg, (arg->argKind) & ~akeBITS); + count->argKind = akRemFeature(count->argKind, akbVariable|akbVarNeeded); + if (IS_VARIABLE_SIZED_UNTYPED(arg->argType)) + /* + * Count arguments for the above types are explicitly declared + * BEFORE the variable (with those bits, they would come afterwards) + */ + count->argKind = akRemFeature(count->argKind, akbRequest|akbReply); + } +} + +static void +rtAddCountInOutArg(argument_t *arg) +{ + argument_t *count; + + /* + * The user sees a single count variable. However, to get the + * count passed from user to server for variable-sized inline OUT + * arrays, we need two count arguments internally. This is + * because the count value lives in different message fields (and + * is scaled differently) in the request and reply messages. + * + * The two variables have the same name to simplify code generation. + * + * This variable has a null argParent field because it has akbRequest. + * For example, see rtCheckVariable. + */ + + count = argAlloc(); + count->argName = strconcat(arg->argName, "Cnt"); + count->argType = itMakeCountType(); + count->argParent = argNULL; + count->argNext = arg->argNext; + arg->argNext = count; + (count->argCInOut = arg->argCount)->argCInOut = count; + count->argKind = akCountInOut; +} + +static void +rtAddPolyArg(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + argument_t *poly; + arg_kind_t akbsend, akbreturn; + + poly = argAlloc(); + poly->argName = strconcat(arg->argName, "Poly"); + poly->argType = itMakePolyType(); + poly->argParent = arg; + poly->argNext = arg->argNext; + arg->argNext = poly; + arg->argPoly = poly; + + /* + * akbsend is bits added if the arg is In; + * akbreturn is bits added if the arg is Out. + * The mysterious business with KernelServer subsystems: + * when packing Out arguments, they use OutNames instead + * of InNames, and the OutName determines if they are poly-in + * as well as poly-out. + */ + + akbsend = akbSend; + akbreturn = akbReturn; + + if (it->itInName == MACH_MSG_TYPE_POLYMORPHIC) { + akbsend |= akbUserArg|akbSendSnd; + if (!IsKernelServer) + akbreturn |= akbServerArg|akbReturnSnd; + } + if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC) { + akbsend |= akbServerArg|akbSendRcv; + akbreturn |= akbUserArg|akbReturnRcv; + if (IsKernelServer) + akbreturn |= akbServerArg|akbReturnSnd; + } + + poly->argKind = akPoly; + if (akCheck(arg->argKind, akbSend)) + poly->argKind = akAddFeature(poly->argKind, akCheck(arg->argKind, akbsend)); + if (akCheck(arg->argKind, akbReturn)) + poly->argKind = akAddFeature(poly->argKind, akCheck(arg->argKind, akbreturn)); +} + +static void +rtAddDeallocArg(argument_t *arg) +{ + argument_t *dealloc; + + dealloc = argAlloc(); + dealloc->argName = strconcat(arg->argName, "Dealloc"); + dealloc->argType = itMakeDeallocType(); + dealloc->argParent = arg; + dealloc->argNext = arg->argNext; + arg->argNext = dealloc; + arg->argDealloc = dealloc; + + /* + * Dealloc flag can only be associated to KPDs. + */ + + dealloc->argKind = akeDealloc; + if (akCheck(arg->argKind, akbSend)) + dealloc->argKind = akAddFeature(dealloc->argKind, akCheck(arg->argKind, akbUserArg|akbSend|akbSendSnd)); + if (akCheck(arg->argKind, akbReturn)) { + dealloc->argKind = akAddFeature(dealloc->argKind, akCheck(arg->argKind, akbServerArg|akbReturn|akbReturnSnd)); + dealloc->argByReferenceServer = TRUE; + } +} + +static void +rtCheckRoutineArgs(routine_t *rt) +{ + argument_t *arg; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + rtDefaultArgKind(rt, arg); + rtCheckRoutineArg(rt, arg); + + /* need to set argTTName before adding implicit args */ + rtSetArgDefaults(rt, arg); + + /* the arg may not have a type (if there was some error in parsing it), + in which case we don't want to do these steps. */ + + if (it != itNULL) { + arg->argFlags = rtProcessDeallocFlag(it, arg->argFlags, arg->argKind, &arg->argDeallocate, arg->argVarName); + arg->argFlags = rtProcessCountInOutFlag(it, arg->argFlags, arg->argKind, &arg->argCountInOut, arg->argVarName); + rtProcessSameCountFlag(arg); + arg->argFlags = rtProcessPhysicalCopyFlag(it, arg->argFlags, arg->argKind, arg->argVarName); + rtProcessRetCodeFlag(arg); + arg->argFlags = rtProcessOverwriteFlag(it, arg->argFlags, arg->argKind, arg->argVarName); + rtAugmentArgKind(arg); + + /* args added here will get processed in later iterations */ + /* order of args is 'arg poly countinout count dealloc' */ + + if (arg->argDeallocate == d_MAYBE) + rtAddDeallocArg(arg); + if (it->itVarArray || (IS_MULTIPLE_KPD(it) && it->itElement->itVarArray)) + rtAddCountArg(arg); + if (arg->argCountInOut) + rtAddCountInOutArg(arg); + if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) || (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) + rtAddPolyArg(arg); + /* + * Detects whether the arg has to become part of the + * Kernel Processed Data section; if yes, define the proper + * itUserKPDType, itServerKPDType + */ + rtDetectKPDArg(arg); + } + } +} + +boolean_t +rtCheckTrailerType(argument_t *arg) +{ + if (akIdent(arg->argKind) == akeSecToken || + akIdent(arg->argKind) == akeAuditToken || + akIdent(arg->argKind) == akeContextToken ) + itCheckTokenType(arg->argVarName, arg->argType); + + if (akIdent(arg->argKind) == akeMsgSeqno) + itCheckIntType(arg->argVarName, arg->argType); + /* + * if the built-in are not used, we cannot match + * the type/size of the desciption provided by the user + * with the one defined in message.h. + */ + + return TRUE; +} + +static void +rtCheckArgTypes(routine_t *rt) +{ + if (rt->rtRequestPort == argNULL) + error("%s %s doesn't have a server port argument", rtRoutineKindToStr(rt->rtKind), rt->rtName); + + if ((rt->rtRequestPort != argNULL) && + (rt->rtRequestPort->argType != itNULL)) + itCheckRequestPortType(rt->rtRequestPort->argName, rt->rtRequestPort->argType); + + if ((rt->rtReplyPort != argNULL) && + (rt->rtReplyPort->argType != itNULL)) + itCheckReplyPortType(rt->rtReplyPort->argName, rt->rtReplyPort->argType); + + if ((rt->rtWaitTime != argNULL) && + (rt->rtWaitTime->argType != itNULL)) + itCheckIntType(rt->rtWaitTime->argName, rt->rtWaitTime->argType); + + if ((rt->rtMsgOption != argNULL) && + (rt->rtMsgOption->argType != itNULL)) + itCheckIntType(rt->rtMsgOption->argName, rt->rtMsgOption->argType); + + if ((IsKernelServer && rt->rtServerImpl) || + (IsKernelUser && rt->rtUserImpl)) + fatal("Implicit data is not supported in the KernelUser and KernelServer modes"); + /* rtCheckTrailerType will hit a fatal() if something goes wrong */ + if (rt->rtServerImpl) + rtCheckMaskFunction(rt->rtArgs, akbServerImplicit, rtCheckTrailerType); + if (rt->rtUserImpl) + rtCheckMaskFunction(rt->rtArgs, akbUserImplicit, rtCheckTrailerType); +} + +/* + * Check for arguments which are missing seemingly needed functions. + * We make this check here instead of in itCheckDecl, because here + * we can take into account what kind of argument the type is + * being used with. + * + * These are warnings, not hard errors, because mig will generate + * reasonable code in any case. The generated code will work fine + * if the ServerType and TransType are really the same, even though + * they have different names. + */ + +static void +rtCheckArgTrans(routine_t *rt) +{ + argument_t *arg; + + /* the arg may not have a type (if there was some error in parsing it) */ + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if ((it != itNULL) && !streql(it->itServerType, it->itTransType)) { + if (akCheck(arg->argKind, akbSendRcv) && (it->itInTrans == strNULL)) + warn("%s: argument has no in-translation function", arg->argName); + + if (akCheck(arg->argKind, akbReturnSnd) && (it->itOutTrans == strNULL)) + warn("%s: argument has no out-translation function", arg->argName); + } + } +} + +/* + * Adds an implicit return-code argument. It exists in the reply message, + * where it is the first piece of data (After the NDR format label).. + */ + +static void +rtAddRetCode(routine_t *rt) +{ + argument_t *arg = argAlloc(); + + arg->argName = "RetCode"; + arg->argType = itRetCodeType; + arg->argKind = akRetCode; + rt->rtRetCode = arg; + + arg->argNext = rt->rtArgs; + rt->rtArgs = arg; +} + +/* + * Process the Return Code. + * The MIG protocol says that RetCode != 0 are only sent through + * mig_reply_error_t structures. Therefore, there is no need + * for reserving a RetCode in a complex Reply message. + */ +static void +rtProcessRetCode(routine_t *rt) +{ + if (!rt->rtOneWay && !rt->rtSimpleReply) { + argument_t *arg = rt->rtRetCode; + + arg->argKind = akRemFeature(arg->argKind, akbReply); + /* we want the RetCode to be a local variable instead */ + arg->argKind = akAddFeature(arg->argKind, akbVarNeeded); + } + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + argument_t *arg = rt->rtRetCArg; + + arg->argKind = akeRetCode|akbUserArg|akbServerArg|akbSendRcv; + } +} + +/* + * Adds an implicit NDR argument. It exists in the reply message, + * where it is the first piece of data. + */ + +static void +rtAddNdrCode(routine_t *rt) +{ + argument_t *arg = argAlloc(); + + arg->argName = "NDR_record"; + arg->argType = itNdrCodeType; + arg->argKind = akeNdrCode; + rt->rtNdrCode = arg; + + /* add at beginning, so ndr-code is first in the reply message */ + arg->argNext = rt->rtArgs; + rt->rtArgs = arg; +} + +/* + * Process the NDR Code. + * We stick a NDR format label iff there is untyped data + */ +static void +rtProcessNdrCode(routine_t *rt) +{ + argument_t *ndr = rt->rtNdrCode; + argument_t *arg; + boolean_t found; + + /* akbSendSnd|akbSendBody initialize the NDR format label */ +#define ndr_send akbRequest|akbSend|akbSendSnd|akbSendBody + /* akbReplyInit initializes the NDR format label */ +#define ndr_rcv akbReply|akbReplyInit|akbReturn|akbReturnBody + + ndr->argKind = akAddFeature(ndr->argKind, ndr_send|ndr_rcv); + + for (found = FALSE, arg = ndr->argNext; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, akbSendRcv|akbSendBody) && + !akCheck(arg->argKind, akbServerImplicit) && !arg->argType->itPortType && + (!arg->argParent || akIdent(arg->argKind) == akeCount || + akIdent(arg->argKind) == akeCountInOut)) { + arg->argKind = akAddFeature(arg->argKind, akbSendNdr); + found = TRUE; + } + if (!found) + ndr->argKind = akRemFeature(ndr->argKind, ndr_send); + + found = FALSE; + if (!rt->rtOneWay) + for (arg = ndr->argNext; arg != argNULL; arg = arg->argNext) + if ((arg == rt->rtRetCode && akCheck(arg->argKind, akbReply)) || + (arg != rt->rtRetCode && + akCheck(arg->argKind, akbReturnRcv|akbReturnBody) && + !akCheck(arg->argKind, akbUserImplicit) && !arg->argType->itPortType && + (!arg->argParent || akIdent(arg->argKind) == akeCount || + akIdent(arg->argKind) == akeCountInOut))) { + arg->argKind = akAddFeature(arg->argKind, akbReturnNdr); + found = TRUE; + } + if (!found && !akCheck(rt->rtRetCode->argKind, akbReply)) + ndr->argKind = akRemFeature(ndr->argKind, ndr_rcv); +} + +/* + * Adds a dummy WaitTime argument to the function. + * This argument doesn't show up in any C argument lists; + * it implements the global WaitTime statement. + */ + +static void +rtAddWaitTime(routine_t *rt, identifier_t name, arg_kind_t kind) +{ + argument_t *arg = argAlloc(); + argument_t **loc; + + arg->argName = "dummy WaitTime arg"; + arg->argVarName = name; + arg->argType = itWaitTimeType; + arg->argKind = kind; + rt->rtWaitTime = arg; + + /* add wait-time after msg-option, if possible */ + + if (rt->rtMsgOption != argNULL) + loc = &rt->rtMsgOption->argNext; + else + loc = &rt->rtArgs; + + arg->argNext = *loc; + *loc = arg; + + rtSetArgDefaults(rt, arg); +} + +/* + * Adds a dummy MsgOption argument to the function. + * This argument doesn't show up in any C argument lists; + * it implements the global MsgOption statement. + */ + +static void +rtAddMsgOption(routine_t *rt, identifier_t name) +{ + argument_t *arg = argAlloc(); + argument_t **loc; + + arg->argName = "dummy MsgOption arg"; + arg->argVarName = name; + arg->argType = itMsgOptionType; + arg->argKind = akeMsgOption; + rt->rtMsgOption = arg; + + /* add msg-option after msg-seqno */ + + loc = &rt->rtArgs; + + arg->argNext = *loc; + *loc = arg; + + rtSetArgDefaults(rt, arg); +} + +/* + * Process the MsgOption Code. + * We must add the information to post a receive with the right + * Trailer options. + */ +static void +rtProcessMsgOption(routine_t *rt) +{ + argument_t *msgop = rt->rtMsgOption; + argument_t *arg; + boolean_t sectoken = FALSE; + boolean_t audittoken = FALSE; + boolean_t contexttoken = FALSE; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, akbReturn|akbUserImplicit)) { + if (akIdent(arg->argKind) == akeSecToken) + sectoken = TRUE; + else if (akIdent(arg->argKind) == akeAuditToken) + audittoken = TRUE; + else if (akIdent(arg->argKind) == akeContextToken) + contexttoken = TRUE; + } + + if (contexttoken == TRUE) + msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_CTX)"); + else if (audittoken == TRUE) + msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT)"); + else if (sectoken == TRUE) + msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER)"); + /* other implicit data received by the user will be handled here */ +} + +static void +rtProcessUseSpecialReplyPort(routine_t *rt) +{ + if (IsKernelUser || IsKernelServer) { + fatal("UseSpecialReplyPort option cannot be used with KernelUser / KernelServer\n"); + } + rt->rtMsgOption->argVarName = strconcat(rt->rtMsgOption->argVarName, "|__MigSpecialReplyPortMsgOption"); +} + +/* + * Adds a dummy reply port argument to the function. + */ + +static void +rtAddDummyReplyPort(routine_t *rt, ipc_type_t *type) +{ + argument_t *arg = argAlloc(); + argument_t **loc; + + arg->argName = "dummy ReplyPort arg"; + arg->argVarName = "dummy ReplyPort arg"; + arg->argType = type; + arg->argKind = akeReplyPort; + rt->rtReplyPort = arg; + + /* add the reply port after the request port */ + + if (rt->rtRequestPort != argNULL) + loc = &rt->rtRequestPort->argNext; + else + loc = &rt->rtArgs; + + arg->argNext = *loc; + *loc = arg; + + rtSetArgDefaults(rt, arg); +} + + +/* + * At least one overwrite keyword has been detected: + * we tag all the OOL entries (ports + data) with + * akbOverwrite which will tell us that we have to + * fill a KPD entry in the message-template + */ +static void +rtCheckOverwrite(routine_t *rt) +{ + argument_t *arg; + int howmany = rt->rtOverwrite; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if (akCheck(arg->argKind, akbReturnKPD) && !it->itInLine) { + /* among OUT args, we want OOL, OOL ports and MigInLine */ + arg->argKind = akAddFeature(arg->argKind, akbOverwrite); + if (arg->argFlags & flOverwrite) + howmany--; + if (!howmany) + return; + } + } +} + +/* + * Initializes argRequestPos, argReplyPos, rtMaxRequestPos, rtMaxReplyPos, + * rtNumRequestVar, rtNumReplyVar, and adds akbVarNeeded to those arguments + * that need it because of variable-sized inline considerations. + * + * argRequestPos and argReplyPos get -1 if the value shouldn't be used. + */ +static void +rtCheckVariable(routine_t *rt) +{ + argument_t *arg; + int NumRequestVar = 0; + int NumReplyVar = 0; + int MaxRequestPos = 0; + int MaxReplyPos = 0; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + argument_t *parent = arg->argParent; + + /* + * We skip KPDs. We have to make sure that the KPDs count + * present in the message body follow the RequestPos/ReplyPos logic + * The rest of the parameters are defaulted to have + * Arg{Request, Reply}Pos = 0 + */ + if (parent == argNULL || akCheck(parent->argKind, akbSendKPD|akbReturnKPD)) { + if (akCheckAll(arg->argKind, akbSend|akbSendBody)) { + arg->argRequestPos = NumRequestVar; + MaxRequestPos = NumRequestVar; + if (akCheck(arg->argKind, akbVariable)) + NumRequestVar++; + } + if (akCheckAll(arg->argKind, akbReturn|akbReturnBody)) { + arg->argReplyPos = NumReplyVar; + MaxReplyPos = NumReplyVar; + if (akCheck(arg->argKind, akbVariable)) + NumReplyVar++; + } + } + else { + arg->argRequestPos = parent->argRequestPos; + arg->argReplyPos = parent->argReplyPos; + } + /* + printf("Var %s Kind %x RequestPos %d\n", arg->argVarName, arg->argKind, arg->argRequestPos); + printf("* Var %s Kind %x ReplyPos %d\n", arg->argVarName, arg->argKind, arg->argReplyPos); + */ + + /* Out variables that follow a variable-sized field + need VarNeeded or ReplyCopy; they can't be stored + directly into the reply message. */ + + if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody) && + !akCheck(arg->argKind, akbReplyCopy|akbVarNeeded) && + (arg->argReplyPos > 0)) + arg->argKind = akAddFeature(arg->argKind, akbVarNeeded); + } + + rt->rtNumRequestVar = NumRequestVar; + rt->rtNumReplyVar = NumReplyVar; + rt->rtMaxRequestPos = MaxRequestPos; + rt->rtMaxReplyPos = MaxReplyPos; +} + +/* + * Adds akbDestroy where needed. + */ + +static void +rtCheckDestroy(routine_t *rt) +{ + argument_t *arg; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if(akCheck(arg->argKind, akbSendRcv) && + !akCheck(arg->argKind, akbReturnSnd) && + (it->itDestructor != strNULL || IS_MIG_INLINE_EMUL(it))) { + arg->argKind = akAddFeature(arg->argKind, akbDestroy); + } + if (argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) && + arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR && + (arg->argFlags & flAuto)) + arg->argKind = akAddFeature(arg->argKind, akbDestroy); + } +} + +/* + * Sets ByReferenceUser and ByReferenceServer. + */ + +static void +rtAddByReference(routine_t *rt) +{ + argument_t *arg; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if (akCheck(arg->argKind, akbReturnRcv) && it->itStruct) { + arg->argByReferenceUser = TRUE; + + /* + * A CountInOut arg itself is not akbReturnRcv, + * so we need to set argByReferenceUser specially. + */ + + if (arg->argCInOut != argNULL) + arg->argCInOut->argByReferenceUser = TRUE; + } + + if ((akCheck(arg->argKind, akbReturnSnd) || + (akCheck(arg->argKind, akbServerImplicit) && + akCheck(arg->argKind, akbReturnRcv) && + akCheck(arg->argKind, akbSendRcv))) + && it->itStruct) { + arg->argByReferenceServer = TRUE; + } + } +} + +/* + * This procedure can be executed only when all the akb* and ake* have + * been set properly (when rtAddCountArg is executed, akbVarNeeded + * might not be set yet - see rtCheckVariable) + */ +void +rtAddSameCount(routine_t *rt) +{ + argument_t *arg; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (arg->argFlags & flSameCount) { + ipc_type_t *it = arg->argType; + argument_t *tmp_count; + argument_t *my_count = arg->argCount; + argument_t *ref_count = arg->argSameCount->argCount; + + tmp_count = argAlloc(); + *tmp_count = *ref_count; + /* + * if our count is a akbVarNeeded, we need to copy this + * attribute to the master count! + */ + tmp_count->argKind = akeSameCount; + ref_count->argKind = akAddFeature(ref_count->argKind, akCheck(my_count->argKind, akbVarNeeded)); + tmp_count->argKind = akAddFeature(tmp_count->argKind, akCheck(my_count->argKind, akbVarNeeded)); + tmp_count->argNext = my_count->argNext; + tmp_count->argMultiplier = my_count->argMultiplier; + tmp_count->argType = my_count->argType; + tmp_count->argParent = arg; + /* we don't need more */ + arg->argCount = tmp_count; + arg->argNext = tmp_count; + /* for these args, Cnt is not akbRequest, and therefore size is embedded */ + if (IS_VARIABLE_SIZED_UNTYPED(it)) + it->itMinTypeSize = 0; + tmp_count->argType->itMinTypeSize = 0; + tmp_count->argType->itTypeSize = 0; + } +} + +void +rtCheckRoutine(routine_t *rt) +{ + /* Initialize random fields. */ + + rt->rtErrorName = ErrorProc; + rt->rtOneWay = (rt->rtKind == rkSimpleRoutine); + rt->rtServerName = strconcat(ServerPrefix, rt->rtName); + rt->rtUserName = strconcat(UserPrefix, rt->rtName); + rt->rtUseSpecialReplyPort = UseSpecialReplyPort && !rt->rtOneWay; + rt->rtConsumeOnSendError = ConsumeOnSendError; + + /* Add implicit arguments. */ + + rtAddRetCode(rt); + rtAddNdrCode(rt); + + /* Check out the arguments and their types. Add count, poly + implicit args. Any arguments added after rtCheckRoutineArgs + should have rtSetArgDefaults called on them. */ + + rtCheckRoutineArgs(rt); + + /* Add dummy WaitTime and MsgOption arguments, if the routine + doesn't have its own args and the user specified global values. */ + + if (rt->rtReplyPort == argNULL) { + if (rt->rtOneWay) + rtAddDummyReplyPort(rt, itZeroReplyPortType); + else + rtAddDummyReplyPort(rt, itRealReplyPortType); + } else if (akCheck(rt->rtReplyPort->argKind, akbUserArg)) { + /* If an explicit ReplyPort is used, we can't assume it will be the SRP */ + rt->rtUseSpecialReplyPort = FALSE; + } + if (rt->rtMsgOption == argNULL) { + if (MsgOption == strNULL) + rtAddMsgOption(rt, "MACH_MSG_OPTION_NONE"); + else + rtAddMsgOption(rt, MsgOption); + } + if (rt->rtWaitTime == argNULL) { + if (WaitTime != strNULL) + rtAddWaitTime(rt, WaitTime, akeWaitTime); + else if (SendTime != strNULL) + rtAddWaitTime(rt, SendTime, akeSendTime); + } + if (rt->rtWaitTime && rt->rtConsumeOnSendError == ConsumeOnSendErrorNone) { + warn("%s %s specifies a SendTime/WaitTime which may leak resources, " + "adopt \"ConsumeOnSendError Timeout\"", + rtRoutineKindToStr(rt->rtKind), rt->rtName); + } + + + /* Now that all the arguments are in place, do more checking. */ + + rtCheckArgTypes(rt); + rtCheckArgTrans(rt); + + if (rt->rtOneWay) { + if (rtCheckMask(rt->rtArgs, akbReturn) || rt->rtUserImpl) + error("%s %s has OUT argument", rtRoutineKindToStr(rt->rtKind), rt->rtName); + } + + /* If there were any errors, don't bother calculating more info + that is only used in code generation anyway. Therefore, + the following functions don't have to worry about null types. */ + + if (mig_errors > 0) + fatal("%d errors found. Abort.\n", mig_errors); + + rt->rtServerImpl = rtCountMask(rt->rtArgs, akbServerImplicit); + rt->rtUserImpl = rtCountMask(rt->rtArgs, akbUserImplicit); + /* + * ASSUMPTION: + * kernel cannot change a message from simple to complex, + * therefore SimpleSendReply and SimpleRcvReply become SimpleReply + */ + rtCheckSimple(rt->rtArgs, akbRequest, &rt->rtSimpleRequest); + rtCheckSimple(rt->rtArgs, akbReply, &rt->rtSimpleReply); + + rt->rtRequestKPDs = rtCountKPDs(rt->rtArgs, akbSendKPD); + rt->rtReplyKPDs = rtCountKPDs(rt->rtArgs, akbReturnKPD); + /* + * Determine how many overwrite parameters we have: + * # of Overwrite args -> rt->rtOverwrite + * flOverwrite -> the arg has to be overwritten + * akbOverwrite -> the arg has to be declared in the message-template + * (only as a placeholder if !flOverwrite). + */ + if ((rt->rtOverwrite = rtCountFlags(rt->rtArgs, flOverwrite))) { + rtCheckOverwrite(rt); + rt->rtOverwriteKPDs = rtCountKPDs(rt->rtArgs, akbReturnKPD|akbOverwrite); + if (IsKernelUser) + fatal("Overwrite option(s) do not match with the KernelUser personality\n"); + } + + rtCheckFit(rt, akbRequest, &rt->rtRequestFits, &rt->rtRequestUsedLimit, &rt->rtRequestSizeKnown); + rtCheckFit(rt, akbReply, &rt->rtReplyFits, &rt->rtReplyUsedLimit, &rt->rtReplySizeKnown); + + rtCheckVariable(rt); + rtCheckDestroy(rt); + rtAddByReference(rt); + rtSuffixExtArg(rt->rtArgs); + rtAddSameCount(rt); + rtProcessRetCode(rt); + rtProcessNdrCode(rt); + if (rt->rtUserImpl) + rtProcessMsgOption(rt); + if (rt->rtUseSpecialReplyPort) + rtProcessUseSpecialReplyPort(rt); + + rt->rtNoReplyArgs = !rtCheckMask(rt->rtArgs, akbReturnSnd); + + if (UseEventLogger) + /* some more info's are needed for Event logging/Stats */ + rtFindHowMany(rt); +} + +void +rtMinRequestSize(FILE *file, routine_t *rt, char *str) +{ + fprintf(file, "(mach_msg_size_t)(sizeof(%s)", str); + rtSizeDelta(file, akbRequest, rt); + fprintf(file, ")"); +} + +void +rtMinReplySize(FILE *file, routine_t *rt, char *str) +{ + fprintf(file, "(mach_msg_size_t)(sizeof(%s)", str); + rtSizeDelta(file, akbReply, rt); + fprintf(file, ")"); +} + +static void +rtSizeDelta(FILE *file, u_int mask, routine_t *rt) +{ + argument_t *arg; + u_int min_size = sizeof(mach_msg_header_t); + u_int max_size; + boolean_t output = FALSE; + + if (!rt->rtSimpleRequest) + machine_alignment(min_size, sizeof(mach_msg_body_t)); + max_size = min_size; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, mask)) { + ipc_type_t *it = arg->argType; + + machine_alignment(min_size, it->itMinTypeSize); + machine_alignment(max_size, it->itMinTypeSize); + + if (IS_VARIABLE_SIZED_UNTYPED(it)) { + machine_alignment(max_size, it->itTypeSize); + max_size += it->itPadSize; + } + if (IS_OPTIONAL_NATIVE(it)) { + if (output) + fprintf(file, " + "); + else { + output = TRUE; + fprintf(file, " - ("); + } + fprintf(file, "_WALIGNSZ_(%s)", it->itUserType); + } + } + if (min_size != max_size) { + if (output) + fprintf(file, " + "); + else + fprintf(file, " - "); + fprintf(file, "%d", max_size - min_size); + } + if (output) + fprintf(file, ")"); +} + diff --git a/bootstrap_cmds/migcom.tproj/routine.h b/bootstrap_cmds/migcom.tproj/routine.h new file mode 100644 index 0000000..1b63a03 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/routine.h @@ -0,0 +1,549 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include + +#ifndef _ROUTINE_H +#define _ROUTINE_H + +#include "type.h" +#include +#include +#include +#include + +/* base kind arg */ +#define akeNone (0) +#define akeNormal (1) /* a normal, user-defined argument */ +#define akeRequestPort (2) /* pointed at by rtRequestPort */ +#define akeWaitTime (3) /* pointed at by rtWaitTime */ +#define akeReplyPort (4) /* pointed at by rtReplyPort */ +#define akeMsgOption (5) /* pointed at by rtMsgOption */ +#define akeMsgSeqno (6) /* pointed at by rtMsgSeqno */ +#define akeRetCode (7) /* pointed at by rtRetCode */ +#define akeNdrCode (8) /* pointed at by rtNdrCode */ +#define akeCount (9) /* a count arg for argParent */ +#define akePoly (10) /* a poly arg for argParent */ +#define akeDealloc (11) /* a deallocate arg for argParent */ +#define akeCountInOut (12) /* a count-in-out arg */ +#define akeSameCount (13) /* a samecount case: in fact, a no count! */ +#define akeSubCount (14) /* a array of array case: subordinate arrays count */ +#define akeImplicit (15) /* an implicit argument, from the trailer */ +#define akeSecToken (16) /* an argument from the trailer: the security token */ +#define akeAuditToken (17) /* an argument from the trailer: the audit token */ +#define akeContextToken (18) /* an argument from the trailer: the context token */ +#define akeSendTime (19) /* pointed at by rtWaitTime */ + +#define akeBITS (0x0000003f) +#define akbRequest (0x00000040) /* has a msg_type in request */ +#define akbReply (0x00000080) /* has a msg_type in reply */ +#define akbUserArg (0x00000100) /* an arg on user-side */ +#define akbServerArg (0x00000200) /* an arg on server-side */ +#define akbSend (0x00000400) /* value carried in request */ +#define akbSendBody (0x00000800) /* value carried in request body */ +#define akbSendSnd (0x00001000) /* value stuffed into request */ +#define akbSendRcv (0x00002000) /* value grabbed from request */ +#define akbReturn (0x00004000) /* value carried in reply */ +#define akbReturnBody (0x00008000) /* value carried in reply body */ +#define akbReturnSnd (0x00010000) /* value stuffed into reply */ +#define akbReturnRcv (0x00020000) /* value grabbed from reply */ +#define akbReturnNdr (0x00040000) /* needs NDR conversion in reply */ +#define akbReplyInit (0x00080000) /* reply value doesn't come from target routine */ +#define akbReplyCopy (0x00200000) /* copy reply value from request */ +#define akbVarNeeded (0x00400000) /* may need local var in server */ +#define akbDestroy (0x00800000) /* call destructor function */ +#define akbVariable (0x01000000) /* variable size inline data */ +#define akbSendNdr (0x04000000) /* needs NDR conversion in request */ +#define akbSendKPD (0x08000000) /* the arg is sent in the Kernel Processed Data + section of the Request message */ +#define akbReturnKPD (0x10000000) /* the arg is sent in the Kernel Processed Data + section of the Reply message */ +#define akbUserImplicit (0x20000000) /* the arg is Impl */ +#define akbServerImplicit (0x40000000) /* the arg is Impl */ +#define akbOverwrite (0x80000000) +/* be careful, there aren't many bits left */ + +typedef u_int arg_kind_t; + +/* + * akbRequest means msg_type/data fields are allocated in the request + * msg. akbReply means msg_type/data fields are allocated in the + * reply msg. These bits * control msg structure declarations packing, + * and checking of mach_msg_type_t fields. + * + * akbUserArg means this argument is an argument to the user-side stub. + * akbServerArg means this argument is an argument to + * the server procedure called by the server-side stub. + * + * The akbSend* and akbReturn* bits control packing/extracting values + * in the request and reply messages. + * + * akbSend means the argument's value is carried in the request msg. + * akbSendBody implies akbSend; the value is carried in the msg body. + * akbSendKPD is the equivalent of akbSendBody for Kernel Processed Data. + * akbSendSnd implies akbSend; the value is stuffed into the request. + * akbSendRcv implies akbSend; the value is pulled out of the request. + * + * akbReturn, akbReturnBody, akbReturnSnd, akbReturnRcv are defined + * similarly but apply to the reply message. + * + * User-side code generation (header.c, user.c) and associated code + * should use akbSendSnd and akbReturnRcv, but not akbSendRcv and + * akbReturnSnd. Server-side code generation (server.c) is reversed. + * Code generation should use the more specific akb{Send,Return}{Snd,Rcv} + * bits when possible, instead of akb{Send,Return}. + * + * Note that akRetCode and akReturn lack any Return bits, although + * there is a value in the msg. These guys are packed/unpacked + * with special code, unlike other arguments. + * + * akbReplyInit implies akbReply. It means the server-side stub + * should initialize the field, because its value does not come + * from the execution of the target routine: the setting of the + * NDR record is the sole example (at the moment) of use of this flag. + * + * akbVariable means the argument has variable-sized inline data. + * It isn't currently used for code generation, but routine.c + * does use it internally. It is added in rtAugmentArgKind. + * + * akbReplyCopy and akbVarNeeded help control code generation in the + * server-side stub. The preferred method of handling data in the + * server-side stub avoids copying into/out-of local variables. In + * arguments get passed directly to the server proc from the request msg. + * Out arguments get stuffed directly into the reply msg by the server proc. + * For InOut arguments, the server proc gets the address of the data in + * the request msg, and the resulting data gets copied to the reply msg. + * Some arguments need a local variable in the server-side stub. The + * code extracts the data from the request msg into the variable, and + * stuff the reply msg from the variable. + * + * akbReplyCopy implies akbReply. It means the data should get copied + * from the request msg to the reply msg after the server proc is called. + * It is only used by akInOut. akTid doesn't need it because the tid + * data in the reply msg is initialized in the server demux function. + * + * akbVarNeeded means the argument needs a local variable in the + * server-side stub. It is added in rtAugmentArgKind and + * rtCheckVariable. An argument shouldn't have all three of + * akbReturnSnd, akbVarNeeded and akbReplyCopy, because this indicates + * the reply msg should be stuffed both ways. + * + * akbDestroy helps control code generation in the server-side stub. + * It means this argument has a destructor function which should be called. + * + * akbOverwrite is used to identify the arguments that have to put an entry in + * the scatter list (the message-template used by the User stub to specify + * where the out-of-line data sent by server has to land). + * + * akbUserImplicit (akbServerImplicit) is used to mark the arguments that + * correspond to implicit data (data generated by the kernel and inserted in + * the trailer). + * + * Header file generation (header.c) uses: + * akbUserArg + * + * User stub generation (user.c) uses: + * akbUserArg, akbRequest, akbReply, akbSendSnd, + * akbSendBody, akbSendKPD, akbReturnRcv, akbOverwrite, akbUserImplicit + * + * Server stub generation (server.c) uses: + * akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd, + * akbReplyCopy, akbVarNeeded, akbSendBody, akbServerImplicit + * + * + * During code generation, the routine, argument, and type data structures + * are read-only. The code generation functions' output is their only + * side-effect. + * + * + * Style note: + * Code can use logical operators (|, &, ~) on akb values. + * ak values should be manipulated with the ak functions. + */ + +/* various useful combinations */ + +#define akbNone (0) +#define akbAll (~akbNone) +#define akbAllBits (~akeBITS) + +#define akbSendBits (akbSend|akbSendBody|akbSendSnd|akbSendRcv) +#define akbReturnBits (akbReturn|akbReturnBody|akbReturnSnd|akbReturnRcv) +#define akbSendReturnBits (akbSendBits|akbReturnBits) + +#define akNone akeNone + +#define akIn akAddFeature(akeNormal, \ + akbUserArg|akbServerArg|akbRequest|akbSendBits) + +#define akOut akAddFeature(akeNormal, \ + akbUserArg|akbServerArg|akbReply|akbReturnBits) + +#define akServerImpl akAddFeature(akeImplicit, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv) +#define akUserImpl akAddFeature(akeImplicit, \ + akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv) + +#define akServerSecToken akAddFeature(akeSecToken, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv) +#define akUserSecToken akAddFeature(akeSecToken, \ + akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv) +#define akSecToken akAddFeature(akeSecToken, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \ + akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv) + +#define akServerAuditToken akAddFeature(akeAuditToken, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv) +#define akUserAuditToken akAddFeature(akeAuditToken, \ + akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv) +#define akAuditToken akAddFeature(akeAuditToken, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \ + akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv) + +#define akServerContextToken akAddFeature(akeContextToken, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv) + +#define akMsgSeqno akAddFeature(akeMsgSeqno, \ + akbServerArg|akbServerImplicit|akbSend|akbSendRcv) + +#define akInOut akAddFeature(akeNormal, \ + akbUserArg|akbServerArg|akbRequest|akbReply| \ + akbSendBits|akbReturnBits|akbReplyCopy) + +#define akRequestPort akAddFeature(akeRequestPort, \ + akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv) + +#define akWaitTime akAddFeature(akeWaitTime, akbUserArg) + +#define akSendTime akAddFeature(akeSendTime, akbUserArg) + +#define akMsgOption akAddFeature(akeMsgOption, akbUserArg) + +#define akReplyPort akAddFeature(akeReplyPort, \ + akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv) + +#define akUReplyPort akAddFeature(akeReplyPort, \ + akbUserArg|akbSend|akbSendSnd|akbSendRcv) + +#define akSReplyPort akAddFeature(akeReplyPort, \ + akbServerArg|akbSend|akbSendSnd|akbSendRcv) + +#define akRetCode akAddFeature(akeRetCode, akbReply|akbReturnBody) + +#define akCount akAddFeature(akeCount, \ + akbUserArg|akbServerArg) + +#define akPoly akePoly + +#define akDealloc akAddFeature(akeDealloc, akbUserArg) + +#define akCountInOut akAddFeature(akeCountInOut, akbRequest|akbSendBits) + +#define akCheck(ak, bits) ((ak) & (bits)) +#define akCheckAll(ak, bits) (akCheck(ak, bits) == (bits)) +#define akAddFeature(ak, bits) ((ak)|(bits)) +#define akRemFeature(ak, bits) ((ak)&~(bits)) +#define akIdent(ak) ((ak) & akeBITS) + +#define argIsIn(arg) (akIdent(arg->argKind) == akeNormal && \ + akCheck(arg->argKind, akbRequest)) +#define argIsOut(arg) (akIdent(arg->argKind) == akeNormal && \ + akCheck(arg->argKind, akbReply)) + +/* + * The arguments to a routine/function are linked in left-to-right order. + * argName is used for error messages and pretty-printing, + * not code generation. Code generation shouldn't make any assumptions + * about the order of arguments, esp. count and poly arguments. + * (Unfortunately, code generation for inline variable-sized arguments + * does make such assumptions.) + * + * argVarName is the name used in generated code for function arguments + * and local variable names. argMsgField is the name used in generated + * code for the field in msgs where the argument's value lives. + * argTTName is the name used in generated code for msg-type fields and + * static variables used to initialize those fields. argPadName is the + * name used in generated code for a padding field in msgs. + * + * argFlags can be used to override the deallocate bits + * in the argument's type. rtProcessArgFlags sets argDeallocate + * from it and the type. Code generation shouldn't use + * argFlags. + * + * argCount, argPoly, and argDealloc get to the implicit count, poly, + * and dealloc arguments associated with the argument; they should be + * used instead of argNext. In these implicit arguments, argParent is + * a pointer to the "real" arg. + * + * In count arguments, argMultiplier is a scaling factor applied to + * the count arg's value to get msg-type-number. It is equal to + * argParent->argType->itElement->itNumber + * + */ + +typedef struct argument +{ + /* if argKind == akReturn, then argName is name of the function */ + identifier_t argName; + struct argument *argNext; + + arg_kind_t argKind; + ipc_type_t *argType; + /* Kernel Processed Data */ + mach_msg_descriptor_type_t argKPD_Type; /* KPD type: port, ool, port+ool */ + void (* argKPD_Template)(FILE *file, struct argument *arg, boolean_t in); /* KPD discipline for static templates */ + void (* argKPD_Init)(FILE *file, struct argument *arg); /* KPD discipline for initializing */ + void (* argKPD_Pack)(FILE *file, struct argument *ar); /* KPD discipline for packing */ + void (* argKPD_Extract)(FILE *file, struct argument *arg); /* KPD discipline for extracting */ + void (* argKPD_TypeCheck)(FILE *file, struct argument *ar); /* KPD discipline for type checking */ + + string_t argVarName; /* local variable and argument names */ + string_t argMsgField; /* message field's name */ + string_t argTTName; /* name for msg_type fields, static vars */ + string_t argPadName; /* name for pad field in msg */ + string_t argSuffix; /* name extension for KPDs */ + + ipc_flags_t argFlags; + dealloc_t argDeallocate; /* overrides argType->itDeallocate */ + boolean_t argCountInOut; + + struct routine *argRoutine; /* routine we are part of */ + + struct argument *argCount; /* our count arg, if present */ + struct argument *argSubCount; /* our sub-count arg, if present (variable subordinate arrays) */ + struct argument *argCInOut; /* our CountInOut arg, if present */ + struct argument *argPoly; /* our poly arg, if present */ + struct argument *argDealloc; /* our dealloc arg, if present */ + struct argument *argSameCount; /* the arg to take the count from, if present */ + struct argument *argParent; /* in a count or poly arg, the base arg */ + u_int argMultiplier; /* for Count argument: parent is a multiple + of a basic IPC type. Argument must be + multiplied by Multiplier to get IPC + number-of-elements. */ + + /* how variable/inline args precede this one, in request and reply */ + u_int argRequestPos; + u_int argReplyPos; + /* whether argument is by reference, on user and server side */ + boolean_t argByReferenceUser; + boolean_t argByReferenceServer; + + boolean_t argTempOnStack; /* A temporary for the short-circuiting + * code when -maxonstack is used. + */ +} argument_t; + +/* + * The various routine kinds' peculiarities are abstracted by rtCheckRoutine + * into attributes like rtOneWay, etc. These are what + * code generation should use. It is Bad Form for code generation to + * test rtKind. + */ + +typedef enum +{ + rkRoutine, + rkSimpleRoutine +} routine_kind_t; + +typedef struct routine +{ + identifier_t rtName; + routine_kind_t rtKind; + argument_t *rtArgs; + u_int rtNumber; /* used for making msg ids */ + + identifier_t rtUserName; /* user-visible name (UserPrefix + Name) */ + identifier_t rtServerName; /* server-side name (ServerPrefix + Name) */ + + identifier_t rtErrorName; /* error-handler name */ + + boolean_t rtOneWay; /* SimpleRoutine */ + + boolean_t rtSimpleRequest; + boolean_t rtSimpleReply; + boolean_t rtUseSpecialReplyPort; + u_int rtConsumeOnSendError; + + u_int rtNumRequestVar; /* number of variable/inline args in request */ + u_int rtNumReplyVar; /* number of variable/inline args in reply */ + + u_int rtMaxRequestPos; /* maximum of argRequestPos */ + u_int rtMaxReplyPos; /* maximum of argReplyPos */ + + u_int rtRequestKPDs; /* number of Kernel Processed Data entries */ + u_int rtReplyKPDs; /* number of Kernel Processed Data entries */ + u_int rtOverwrite; /* number of Overwrite entries */ + u_int rtOverwriteKPDs; /* number of entries in the Overwrite template */ + + boolean_t rtNoReplyArgs; /* if so, no reply message arguments beyond + what the server dispatch routine inserts */ + + boolean_t rtRequestFits; /* Request fits within onstack limit */ + boolean_t rtReplyFits; /* Reply fits within onstack limit */ + boolean_t rtRequestUsedLimit;/* User type limit used in deciding whether + request fits within onstack limit */ + boolean_t rtReplyUsedLimit; /* User type limit used in deciding whether + reply fits within onstack limit */ + u_int rtRequestSizeKnown; /* Max size of known portion of request */ + u_int rtReplySizeKnown; /* Max size of known portion of request */ + + u_int rtServerImpl; /* Implicit data requested */ + u_int rtUserImpl; /* Implicit data requested */ + + /* distinguished arguments */ + argument_t *rtRetCArg; /* the Routine has this argument tagged as RetCode */ + argument_t *rtRequestPort; /* always non-NULL, defaults to first arg */ + argument_t *rtReplyPort; /* always non-NULL, defaults to Mig-supplied */ + argument_t *rtRetCode; /* always non-NULL */ + argument_t *rtNdrCode; /* always non-NULL */ + argument_t *rtWaitTime; /* if non-NULL, will use MACH_RCV_TIMEOUT */ + argument_t *rtMsgOption; /* always non-NULL, defaults to NONE */ + + /* more info's used only when UseEventLogger is turned on */ + u_int rtCountPortsIn; /* how many in-line Ports are sent */ + u_int rtCountOolPortsIn; /* how many out_of-line Ports are sent */ + u_int rtCountOolIn; /* how many bytes out_of-line are sent */ + + u_int rtCountPortsOut; /* how many in-line Ports are rcv'd */ + u_int rtCountOolPortsOut; /* how many out_of-line Ports are rcv'd */ + u_int rtCountOolOut; /* how many bytes out_of-line are rcv'd */ + + u_int rtTempBytesOnStack; /* A temporary for the short-circuiting + * code when -maxonstack is used. + */ + +} routine_t; + +#define rtNULL ((routine_t *) 0) +#define argNULL ((argument_t *) 0) +#define argKPD_NULL ((mach_msg_descriptor_type_t) -1) + +#define rtMessOnStack(rt) ((rt)->rtRequestFits && (rt)->rtReplyFits) + +/* + * These are the ways MiG organizes stub parameters + */ +#define IS_VARIABLE_SIZED_UNTYPED(x) ((x)->itVarArray && \ + (x)->itInLine && \ + !(x)->itPortType) +#define IS_KERN_PROC_DATA(x) (!(x)->itInLine || (x)->itPortType) +#define IS_OPTIONAL_NATIVE(x) ((x)->itNative && \ + (x)->itNativePointer && \ + (x)->itBadValue != NULL) + +/* + * I consider the case of fixed/variable bounded arrays of ports or ool or oolport + */ +#define IS_MULTIPLE_KPD(x) ((x)->itKPD_Number > 1) +/* + * I consider the case of MiG presenting data as it is inLine, even + * if it is sent/rcvd as out-of-line + */ +#define IS_MIG_INLINE_EMUL(x) ((x)->itMigInLine) + +extern u_int rtNumber; +/* rt->rtNumber will be initialized */ +extern routine_t *rtAlloc(void); +/* skip a number */ +extern void rtSkip(void); + +extern argument_t *argAlloc(void); + +extern boolean_t +rtCheckMask(argument_t *args, u_int mask); + +extern boolean_t +rtCheckMaskFunction(argument_t *args, u_int mask, + boolean_t (*func)(argument_t *arg)); + +extern routine_t * +rtMakeRoutine(identifier_t name, argument_t *args); +extern routine_t * +rtMakeSimpleRoutine(identifier_t name, argument_t *args); + +extern void rtPrintRoutine(routine_t *rt); +extern void rtCheckRoutine(routine_t *rt); + +extern char *rtRoutineKindToStr(routine_kind_t rk); + +extern int rtCountArgDescriptors(argument_t *args, int *argcount); + +extern void rtMinRequestSize(FILE *file, routine_t *rt, char *str); +extern void rtMinReplySize(FILE *file, routine_t *rt, char *str); + +#define RPCUserStruct(arg) (arg->argType->itStruct && arg->argType->itInLine) + +#define RPCString(arg) (arg->argType->itString && arg->argType->itInLine) + +#define RPCOutStruct(arg) (arg->argType->itStruct &&\ + argIsOut(arg) && (! arg->argType->itVarArray)) +#define RPCOutWord(arg) (RPCUserStruct(arg) &&\ + (arg->argType->itSize <= 32) &&\ + (arg->argType->itNumber == 1) && argIsOut(arg)) + +#define RPCPort(arg) (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR) + +#define RPCPortArray(arg) (arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR) + +#define RPCVariableArray(arg) ((arg->argType->itVarArray) &&\ + !RPCPort(arg) && !RPCPortArray(arg)) + +#define RPCFixedArray(arg) (((! arg->argType->itVarArray) &&\ + !RPCPort(arg) && !RPCPortArray(arg) &&\ + (arg->argType->itNumber > 1) &&\ + !RPCUserStruct(arg)) ||\ + RPCString(arg) ||\ + RPCOutWord(arg) ||\ + RPCOutStruct(arg)) + + +#endif /* _ROUTINE_H */ + + + diff --git a/bootstrap_cmds/migcom.tproj/server.c b/bootstrap_cmds/migcom.tproj/server.c new file mode 100644 index 0000000..7bbed53 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/server.c @@ -0,0 +1,2772 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * @OSF_COPYRIGHT@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +#include +#include "write.h" +#include "utils.h" +#include "global.h" +#include "error.h" + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* max */ + +void WriteLogDefines(FILE *file, string_t who); +void WriteIdentificationString(FILE *file); +static void WriteFieldDecl(FILE *file, argument_t *arg); + +static void +WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t varying, argument_t *arg, boolean_t bracket) +{ + ipc_type_t *it = arg->argType; + char string[MAX_STR_LEN]; + + fprintf(file, "\t{\n"); + fprintf(file, "\t %s\t*ptr;\n", it->itKPDType); + fprintf(file, "\t int\ti"); + if (varying && !in) + fprintf(file, ", j"); + fprintf(file, ";\n\n"); + + if (in) + sprintf(string, "In%dP", arg->argRequestPos); + else + sprintf(string, "OutP"); + + fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField); + + if (varying) { + argument_t *count = arg->argCount; + + if (in) + fprintf(file, "\t for (i = 0; i < In%dP->%s; ptr++, i++) %s\n", count->argRequestPos, count->argMsgField, (bracket) ? "{" : ""); + else { + fprintf(file, "\t j = min(%d, ", it->itKPD_Number); + if (akCheck(count->argKind, akbVarNeeded)) + fprintf(file, "%s);\n", count->argName); + else + fprintf(file, "%s->%s);\n", string, count->argMsgField); + fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n", (bracket) ? "{" : ""); + } +} + else + fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number, (bracket) ? "{" : ""); +} + +static void +WriteMyIncludes(FILE *file, statement_t *stats) +{ + if (ServerHeaderFileName == strNULL || UseSplitHeaders) + WriteIncludes(file, FALSE, FALSE); + if (ServerHeaderFileName != strNULL) + { + char *cp; + + /* Strip any leading path from ServerHeaderFileName. */ + cp = strrchr(ServerHeaderFileName, '/'); + if (cp == 0) + cp = ServerHeaderFileName; + else + cp++; /* skip '/' */ + fprintf(file, "#include \"%s\"\n", cp); + } + if (ServerHeaderFileName == strNULL || UseSplitHeaders) + WriteImplImports(file, stats, FALSE); + if (UseEventLogger) { + if (IsKernelServer) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "#include \n"); + fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n"); + } + fprintf(file, "#if MIG_DEBUG\n"); + fprintf(file, "#include \n"); + fprintf(file, "#endif /* MIG_DEBUG */\n"); + } + + fprintf(file, "\n"); +} + +static void +WriteGlobalDecls(FILE *file) +{ + if (BeAnsiC) { + fprintf(file, "#define novalue void\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "#define novalue void\n"); + fprintf(file, "#else\n"); + fprintf(file, "#define novalue int\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + fprintf(file, "\n"); + + if (RCSId != strNULL) + WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId); + + /* Used for locations in the request message, *not* reply message. + Reply message locations aren't dependent on IsKernelServer. */ + + if (IsKernelServer) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n"); + fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); + fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); + fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n"); + fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); + fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); + fprintf(file, "#else\n"); + } + fprintf(file, "#define msgh_request_port\tmsgh_local_port\n"); + fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); + fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); + fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n"); + fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); + fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); + if (IsKernelServer) { + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + fprintf(file, "\n"); + if (UseEventLogger) + WriteLogDefines(file, "MACH_MSG_LOG_SERVER"); + fprintf(file, "#define MIG_RETURN_ERROR(X, code)\t{\\\n"); + fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n"); + fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n"); + fprintf(file, "\t\t\t\treturn;\\\n"); + fprintf(file, "\t\t\t\t}\n"); + fprintf(file, "\n"); +} + + +static void +WriteForwardDeclarations(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* Forward Declarations */\n\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName); + fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n"); + } + fprintf(file, "\n"); +} + +static void +WriteMIGCheckDefines(FILE *file) +{ + fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName); + fprintf(file, "\n"); +} + +static void +WriteNDRDefines(FILE *file) +{ + fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName); + fprintf(file, "\n"); +} + +static void +WriteProlog(FILE *file, statement_t *stats) +{ + WriteIdentificationString(file); + fprintf(file, "\n"); + fprintf(file, "/* Module %s */\n", SubsystemName); + fprintf(file, "\n"); + WriteMIGCheckDefines(file); + if (CheckNDR) + WriteNDRDefines(file); + WriteMyIncludes(file, stats); + WriteBogusDefines(file); + WriteApplDefaults(file, "Rcv"); + WriteGlobalDecls(file); + if (ServerHeaderFileName == strNULL) { + WriteRequestTypes(file, stats); + WriteReplyTypes(file, stats); + WriteServerReplyUnion(file, stats); + } +} + +static void +WriteSymTabEntries(FILE *file, statement_t *stats) +{ + statement_t *stat; + u_int current = 0; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + int num = stat->stRoutine->rtNumber; + char *name = stat->stRoutine->rtName; + while (++current <= num) + fprintf(file,"\t\t\t{ \"\", 0, 0 },\n"); + fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name); + } + while (++current <= rtNumber) + fprintf(file,"\t{ \"\", 0, 0 },\n"); +} + +static void +WriteRoutineEntries(FILE *file, statement_t *stats) +{ + u_int current = 0; + statement_t *stat; + char *sig_array, *rt_name; + int arg_count, descr_count; + int offset = 0; + size_t serverSubsysNameLen = strlen(ServerSubsys); + + fprintf(file, "\t{\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + routine_t *rt = stat->stRoutine; + size_t rtNameLen = strlen(rt->rtName); + + // Include length of rt->rtName in calculation of necessary buffer size, since that string + // is actually written into the buffer along with the Server Subsystem name. + sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80); + rt_name = (char *) malloc(rtNameLen + 5); + while (current++ < rt->rtNumber) + fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n"); + // NOTE: if either of the two string constants in the sprintf() function calls below get + // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure + // that the allocated buffer is large enough. (Currently, I count 66 characters in the first + // string constant, 65 in the second. 80 ought to be enough for now...) + if (UseRPCTrap) { + sprintf(sig_array, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys, offset, rt->rtName); + } + else { + sprintf(sig_array, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtName); + } + sprintf(rt_name, "_X%s", rt->rtName); + descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count); + offset += descr_count; + WriteRPCRoutineDescriptor(file, rt, arg_count, (UseRPCTrap) ? descr_count : 0, rt_name, sig_array); + fprintf(file, ",\n"); + free(sig_array); + free(rt_name); + } + while (current++ < rtNumber) + fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n"); + + fprintf(file, "\t}"); +} + +static void +WriteArgDescriptorEntries(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, ",\n\n\t{\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + routine_t *rt = stat->stRoutine; + + /* For each arg of the routine, write an arg descriptor: + */ + WriteRPCRoutineArgDescriptor(file, rt); + } + fprintf(file, "\t},\n\n"); +} + + +/* + * Write out the description of this subsystem, for use in direct RPC + */ +static void +WriteSubsystem(FILE *file, statement_t *stats) +{ + statement_t *stat; + int descr_count = 0; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + routine_t *rt = stat->stRoutine; + descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0); + } + fprintf(file, "\n"); + if (ServerHeaderFileName == strNULL) { + WriteMigExternal(file); + fprintf(file, "boolean_t %s(", ServerDemux); + if (BeAnsiC) { + fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,"); + fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP"); + } + fprintf(file, ");\n\n"); + + WriteMigExternal(file); + fprintf(file, "mig_routine_t %s_routine(", ServerDemux); + if (BeAnsiC) { + fprintf(file, "\n\t\tmach_msg_header_t *InHeadP"); + } + fprintf(file, ");\n\n"); + } + fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n"); + if (ServerHeaderFileName == strNULL) { + fprintf(file, "const struct %s {\n", ServerSubsys); + if (UseRPCTrap) { + fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n"); + } + else { + fprintf(file, "\tmig_server_routine_t \tserver;\t/* Server routine */\n"); + } + fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n"); + fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n"); + fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n"); + if (UseRPCTrap) { + fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n"); + fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n"); + } + else { + fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n"); + fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n"); + } + fprintf(file, "\t\troutine[%d];\n", rtNumber); + if (UseRPCTrap) { + fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n"); + fprintf(file, "\t\targ_descriptor[%d];\n", descr_count); + } + fprintf(file, "} %s = {\n", ServerSubsys); + } + else { + fprintf(file, "const struct %s %s = {\n", ServerSubsys, ServerSubsys); + } + if (UseRPCTrap) { + fprintf(file, "\t0,\n"); + } + else { + fprintf(file, "\t%s_routine,\n", ServerDemux); + } + fprintf(file, "\t%d,\n", SubsystemBase); + fprintf(file, "\t%d,\n", SubsystemBase + rtNumber); + fprintf(file, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys); + if (UseRPCTrap) { + fprintf(file, "\t(vm_address_t)&%s,\n", ServerSubsys); + } + else { + fprintf(file, "\t(vm_address_t)0,\n"); + } + WriteRoutineEntries(file, stats); + + if (UseRPCTrap) + WriteArgDescriptorEntries(file, stats); + else + fprintf(file, "\n"); + + fprintf(file, "};\n\n"); +} + +#if NOT_CURRENTLY_USED + +static void +WriteArraySizes(FILE *file, statement_t *stats) +{ + u_int current = 0; + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + routine_t *rt = stat->stRoutine; + + while (current++ < rt->rtNumber) + fprintf(file, "\t\t0,\n"); + fprintf(file, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt->rtName); + } + while (current++ < rtNumber) + fprintf(file, "\t\t\t0,\n"); +} + +#endif /* NOT_CURRENTLY_USED */ + +void +WriteServerRequestUnion(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "\n"); + fprintf(file, "/* union of all requests */\n\n"); + fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys); + fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys); + fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + + rt = stat->stRoutine; + fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName); + } + } + fprintf(file, "};\n"); + fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys); +} + +void +WriteServerReplyUnion(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "\n"); + fprintf(file, "/* union of all replies */\n\n"); + fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys); + fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys); + fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + + rt = stat->stRoutine; + fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName); + } + } + fprintf(file, "};\n"); + fprintf(file, "#endif /* __ReplyUnion__%s__defined */\n", ServerSubsys); +} + +static void +WriteDispatcher(FILE *file, statement_t *stats) +{ + /* + * Write the subsystem stuff. + */ + fprintf(file, "\n"); + WriteSubsystem(file, stats); + + /* + * Then, the server routine + */ + fprintf(file, "mig_external boolean_t %s\n", ServerDemux); + if (BeAnsiC) { + fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); + fprintf(file, "#else\n"); + fprintf(file, "\t(InHeadP, OutHeadP)\n"); + fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + + fprintf(file, "{\n"); + fprintf(file, "\t/*\n"); + fprintf(file, "\t * typedef struct {\n"); + fprintf(file, "\t * \tmach_msg_header_t Head;\n"); + fprintf(file, "\t * \tNDR_record_t NDR;\n"); + fprintf(file, "\t * \tkern_return_t RetCode;\n"); + fprintf(file, "\t * } mig_reply_error_t;\n"); + fprintf(file, "\t */\n"); + fprintf(file, "\n"); + + fprintf(file, "\tmig_routine_t routine;\n"); + fprintf(file, "\n"); + + fprintf(file, "\tOutHeadP->msgh_bits = "); + fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n"); + fprintf(file, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n"); + fprintf(file, "\t/* Minimal size: routine() will update it if different */\n"); + fprintf(file, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n"); + fprintf(file, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n"); + fprintf(file, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n"); + fprintf(file, "\tOutHeadP->msgh_reserved = 0;\n"); + fprintf(file, "\n"); + + fprintf(file, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase + rtNumber - 1, SubsystemBase); + fprintf(file, "\t ((routine = %s.routine[InHeadP->msgh_id - %d].stub_routine) == 0)) {\n", ServerSubsys, SubsystemBase); + fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n"); + fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n"); + if (UseEventLogger) { + fprintf(file, "#if MIG_DEBUG\n"); + fprintf(file, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n"); + fprintf(file, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n"); + fprintf(file, "#endif /* MIG_DEBUG */\n"); + } + fprintf(file, "\t\treturn FALSE;\n"); + fprintf(file, "\t}\n"); + + /* Call appropriate routine */ + fprintf(file, "\t(*routine) (InHeadP, OutHeadP);\n"); + fprintf(file, "\treturn TRUE;\n"); + fprintf(file, "}\n"); + fprintf(file, "\n"); + + /* + * Then, the _server_routine routine + */ + fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux); + if (BeAnsiC) { + fprintf(file, "\t(mach_msg_header_t *InHeadP)\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "\t(mach_msg_header_t *InHeadP)\n"); + fprintf(file, "#else\n"); + fprintf(file, "\t(InHeadP)\n"); + fprintf(file, "\tmach_msg_header_t *InHeadP;\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + + fprintf(file, "{\n"); + fprintf(file, "\tint msgh_id;\n"); + fprintf(file, "\n"); + fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase); + fprintf(file, "\n"); + fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber - 1); + fprintf(file, "\t\treturn 0;\n"); + fprintf(file, "\n"); + fprintf(file, "\treturn %s.routine[msgh_id].stub_routine;\n", ServerSubsys); + fprintf(file, "}\n"); + + /* symtab */ + + if (GenSymTab) { + fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName); + WriteSymTabEntries(file,stats); + fprintf(file,"};\n"); + fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase); + fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber); + } +} + +#if NOT_CURRENTLY_USED +/* + * Returns the return type of the server-side work function. + * Suitable for "extern %s serverfunc()". + */ +static char * +ServerSideType(routine_t *rt) +{ + return rt->rtRetCode->argType->itTransType; +} +#endif /* NOT_CURRENTLY_USED */ + +static void +WriteRetCode(FILE *file, argument_t *ret) +{ + ipc_type_t *it = ret->argType; + + if (akCheck(ret->argKind, akbVarNeeded)) { + fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName); + } +} + +static void +WriteLocalVarDecl(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + ipc_type_t *btype = it->itElement; + + if (IS_VARIABLE_SIZED_UNTYPED(it)) + fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0); + else if (IS_MULTIPLE_KPD(it)) { + if (btype->itTransType != strNULL) + fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number); + else + /* arrays of ool or oolport */ + fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number); + } + else + fprintf(file, "\t%s %s", it->itTransType, arg->argVarName); +} + +#if NOT_CURRENTLY_USED +static void +WriteServerArgDecl(FILE *file, argument_t *arg) +{ + fprintf(file, "%s %s%s", arg->argType->itTransType, arg->argByReferenceServer ? "*" : "", arg->argVarName); +} +#endif /* NOT_CURRENTLY_USED */ + +/* + * Writes the local variable declarations which are always + * present: InP, OutP, the server-side work function. + */ +static void +WriteVarDecls(FILE *file, routine_t *rt) +{ + int i; + + fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n"); + for (i = 1; i <= rt->rtMaxRequestPos; i++) + fprintf(file, "\tRequest *In%dP;\n", i); + fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n"); + + /* if reply is variable, we may need msgh_size_delta and msgh_size */ + if (rt->rtNumReplyVar > 1) + fprintf(file, "\tunsigned int msgh_size;\n"); + if (rt->rtMaxReplyPos > 0) + fprintf(file, "\tunsigned int msgh_size_delta;\n"); + if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0) + fprintf(file, "\n"); + + if (rt->rtServerImpl) { + fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n"); + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tunsigned int trailer_size __attribute__((unused));\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + fprintf(file, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt->rtName); + fprintf(file, "\tkern_return_t check_result;\n"); + fprintf(file, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt->rtName); + fprintf(file, "\n"); +} + +static void +WriteReplyInit(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos) + /* WritheAdjustMsgSize() has been executed at least once! */ + fprintf(file, "\tOutP = (Reply *) OutHeadP;\n"); + + if (!rt->rtSimpleReply) /* complex reply message */ + fprintf(file, "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n"); + + if (rt->rtNumReplyVar == 0) { + fprintf(file, "\tOutP->Head.msgh_size = "); + rtMinReplySize(file, rt, "Reply"); + fprintf(file, ";\n"); + } + else if (rt->rtNumReplyVar > 1) + fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n"); + /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */ +} + +static void +WriteRetCArgCheckError(FILE *file, routine_t *rt) +{ + fprintf(file, "\tif (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n"); + fprintf(file, "\t (In0P->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n"); + fprintf(file, "\t{\n"); +} + +static void +WriteRetCArgFinishError(FILE *file, routine_t *rt) +{ + argument_t *retcode = rt->rtRetCArg; + + fprintf(file, "\treturn;\n"); + fprintf(file, "\t}\n"); + retcode->argMsgField = "KERN_SUCCESS"; +} + +static void +WriteCheckHead(FILE *file, routine_t *rt) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + if (rt->rtNumRequestVar > 0) + fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n"); + + if (rt->rtSimpleRequest) { + /* Expecting a simple message. */ + fprintf(file, "\tif ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); + if (rt->rtNumRequestVar > 0) { + fprintf(file, "\t (msgh_size < "); + rtMinRequestSize(file, rt, "__Request"); + fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n"); + } + else + fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n"); + } + else { + /* Expecting a complex message. */ + + fprintf(file, "\tif ("); + if (rt->rtRetCArg != argNULL) + fprintf(file, "("); + fprintf(file, "!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); + fprintf(file, "\t (In0P->msgh_body.msgh_descriptor_count != %d) ||\n", rt->rtRequestKPDs); + if (rt->rtNumRequestVar > 0) { + fprintf(file, "\t (msgh_size < "); + rtMinRequestSize(file, rt, "__Request"); + fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))"); + } + else + fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))"); + if (rt->rtRetCArg == argNULL) + fprintf(file, ")\n"); + else { + fprintf(file, ") &&\n"); + fprintf(file, "\t ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); + fprintf(file, "\t In0P->Head.msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n"); + fprintf(file, "\t ((mig_reply_error_t *)In0P)->RetCode == KERN_SUCCESS))\n"); + } + } + fprintf(file, "\t\treturn MIG_BAD_ARGUMENTS;\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); +} + +void +WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + fprintf(file, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); +} + +void +WriteRequestNDRConvertCharRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + fprintf(file, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); + else + fprintf(file, "0"); +} + +void +WriteRequestNDRConvertFloatRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); + else + fprintf(file, "0"); +} + +void +WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg) +{ + WriteNDRConvertArgDecl(file, arg, "int_rep", "Request"); +} + +void +WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + WriteNDRConvertArgDecl(file, arg, "char_rep", "Request"); +} + +void +WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + WriteNDRConvertArgDecl(file, arg, "float_rep", "Request"); +} + +void +WriteRequestNDRConvertArgUse(FILE *file, argument_t *arg, char *convert) +{ + routine_t *rt = arg->argRoutine; + argument_t *count = arg->argCount; + char argname[MAX_STR_LEN]; + + if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) && + (arg->argParent && akCheck(arg->argParent->argKind, akbSendNdr))) + return; + + if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) { + fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField); + fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos); + fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField); + } + + sprintf(argname, "(%s)(In%dP->%s.address)", FetchServerType(arg->argType), arg->argRequestPos, arg->argMsgField); + } + else { + sprintf(argname, "&In%dP->%s", arg->argRequestPos, arg->argMsgField); + } + + fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField); + fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert); + if (count) + fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField); + fprintf(file, ");\n"); + fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField); +} + +void +WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField); + fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep)\n"); + fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argRequestPos, arg->argMsgField, arg->argRequestPos); + fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField); +} + +void +WriteRequestNDRConvertIntRepArgUse(FILE *file, argument_t *arg) +{ + WriteRequestNDRConvertArgUse(file, arg, "int_rep"); +} + +void +WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + WriteRequestNDRConvertArgUse(file, arg, "char_rep"); +} + +void +WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) + WriteRequestNDRConvertArgUse(file, arg, "float_rep"); +} + +static void +WriteCalcArgSize(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + + if (PackMsg == FALSE) { + fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); + return; + } + + if (IS_OPTIONAL_NATIVE(ptype)) + fprintf(file, "(In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg->argRequestPos, arg->argMsgField, ptype->itServerType); + else { + ipc_type_t *btype = ptype->itElement; + argument_t *count = arg->argCount; + int multiplier = btype->itTypeSize; + + if (btype->itTypeSize % itWordAlign != 0) + fprintf(file, "_WALIGN_"); + fprintf(file, "("); + + if (multiplier > 1) + fprintf(file, "%d * ", multiplier); + fprintf(file, "In%dP->%s", count->argRequestPos, count->argMsgField); + fprintf(file, ")"); + } +} + +static void +WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator) +{ + ipc_type_t *ptype = arg->argType; + + + fprintf(file, "\tif (((msgh_size - "); + rtMinRequestSize(file, rt, "__Request"); + fprintf(file, ") "); + if (PackMsg == FALSE) { + fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize); + } else if (IS_OPTIONAL_NATIVE(ptype)) { + fprintf(file, "%s (In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argRequestPos, arg->argMsgField, ptype->itServerType); + } else { + ipc_type_t *btype = ptype->itElement; + argument_t *count = arg->argCount; + int multiplier = btype->itTypeSize; + + if (multiplier > 1) + fprintf(file, "/ %d ", multiplier); + fprintf(file, "< In%dP->%s) ||\n", count->argRequestPos, count->argMsgField); + fprintf(file, "\t (msgh_size %s ", comparator); + rtMinRequestSize(file, rt, "__Request"); + fprintf(file, " + "); + WriteCalcArgSize(file, arg); + fprintf(file, ")"); + } + fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n"); +} + +static void +WriteCheckMsgSize(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + if (arg->argCount && !arg->argSameCount) + WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount); + if (arg->argRequestPos == rt->rtMaxRequestPos) { + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */ + fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber); + fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file); + /* ...end... */ + + WriteCheckArgSize(file, rt, arg, "!="); + + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + else { + /* If there aren't any more variable-sized arguments after this, + then we must check for exact msg-size and we don't need to + update msgh_size. */ + + boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar; + + /* calculate the actual size in bytes of the data field. note + that this quantity must be a multiple of four. hence, if + the base type size isn't a multiple of four, we have to + round up. note also that btype->itNumber must + divide btype->itTypeSize (see itCalculateSizeInfo). */ + + fprintf(file, "\tmsgh_size_delta = "); + WriteCalcArgSize(file, arg); + fprintf(file, ";\n"); + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */ + fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber); + fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file); + /* ...end... */ + + /* Don't decrement msgh_size until we've checked that + it won't underflow. */ + WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<"); + + if (!LastVarArg) + fprintf(file, "\tmsgh_size -= msgh_size_delta;\n"); + + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + fprintf(file, "\n"); +} + +static char * +InArgMsgField(argument_t *arg, char *str) +{ + static char buffer[MAX_STR_LEN]; + char who[20] = {0}; + + /* + * Inside the kernel, the request and reply port fields + * really hold ipc_port_t values, not mach_port_t values. + * Hence we must cast the values. + */ + + if (!(arg->argFlags & flRetCode)) { + if (akCheck(arg->argKind, akbServerImplicit)) + sprintf(who, "TrailerP->"); + else + sprintf(who, "In%dP->", arg->argRequestPos); + } + +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer && + ((akIdent(arg->argKind) == akeRequestPort) || + (akIdent(arg->argKind) == akeReplyPort))) + sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); + else +#endif + sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); + + return buffer; +} + +static void +WriteExtractArgValue(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + string_t recast; + +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t") + && akIdent(arg->argKind) != akeRequestPort + && akIdent(arg->argKind) != akeReplyPort) + recast = "(mach_port_t)"; + else +#endif + recast = ""; + if (it->itInTrans != strNULL) + WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, "")); + else + WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, "")); + + fprintf(file, "\n"); +} + +/* + * argKPD_Extract discipline for Port types. + */ +static void +WriteExtractKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *recast = ""; + + WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); + /* translation function do not apply to complex types */ +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer) + recast = "(mach_port_t)"; +#endif + fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast); + fprintf(file, "\t}\n"); +} + +/* + * argKPD_Extract discipline for out-of-line types. + */ +static void +WriteExtractKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); + fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); + fprintf(file, "\t}\n"); +} + +/* + * argKPD_Extract discipline for out-of-line Port types. + */ +static void +WriteExtractKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); + fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); + fprintf(file, "\t}\n"); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendRcv)) { + argument_t *poly = arg->argPoly; + char *pref = poly->argByReferenceServer ? "*" : ""; + + fprintf(file, "\t%s%s = In%dP->%s[0].disposition;\n", pref, poly->argVarName, arg->argRequestPos, arg->argMsgField); + } +} + + +static void +WriteInitializeCount(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argParent->argType; + ipc_type_t *btype = ptype->itElement; + identifier_t newstr; + + /* + * Initialize 'count' argument for variable-length inline OUT parameter + * with maximum allowed number of elements. + */ + + if (akCheck(arg->argKind, akbVarNeeded)) + newstr = arg->argMsgField; + else + newstr = (identifier_t)strconcat("OutP->", arg->argMsgField); + + fprintf(file, "\t%s = ", newstr); + if (IS_MULTIPLE_KPD(ptype)) + fprintf(file, "%d;\n", ptype->itKPD_Number); + else + fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0); + + /* + * If the user passed in a count, then we use the minimum. + * We can't let the user completely override our maximum, + * or the user might convince the server to overwrite the buffer. + */ + + if (arg->argCInOut != argNULL) { + char *msgfield = InArgMsgField(arg->argCInOut, ""); + + fprintf(file, "\tif (%s < %s)\n", msgfield, newstr); + fprintf(file, "\t\t%s = %s;\n", newstr, msgfield); + } + + fprintf(file, "\n"); +} + +static void +WriteAdjustRequestMsgPtr(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + + if (PackMsg == FALSE) { + fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos); + return; + } + + fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos); + if (IS_OPTIONAL_NATIVE(ptype)) + fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType); + else + fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); + fprintf(file, ");\n\n"); +} + +static void +WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt) +{ + argument_t *arg; + + if (rt->rtServerImpl) + WriteCheckTrailerHead(file, rt, FALSE); + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akCheck(arg->argKind, akbServerImplicit)) + WriteCheckTrailerSize(file, FALSE, arg); + } +} + +static void +WriteExtractArg(FILE *file, argument_t *arg) +{ + if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) { + if (akCheck(arg->argKind, akbSendKPD)) + (*arg->argKPD_Extract)(file, arg); + else + WriteExtractArgValue(file, arg); + } + + if ((akIdent(arg->argKind) == akeCount) && + akCheck(arg->argKind, akbReturnSnd)) { + + ipc_type_t *ptype = arg->argParent->argType; + /* + * the count will be initialized to 0 in the case of + * unbounded arrays (MigInLine = TRUE): this is because + * the old interface used to pass to the target procedure + * the maximum in-line size (it was 2048 bytes) + */ + if (IS_VARIABLE_SIZED_UNTYPED(ptype) || + IS_MIG_INLINE_EMUL(ptype) || + (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray)) + WriteInitializeCount(file, arg); + } +} + +static void +WriteServerCallArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + boolean_t NeedClose = FALSE; + u_int elemsize = 0; + string_t at = (arg->argByReferenceServer || + it->itNativePointer) ? "&" : ""; + string_t star = (arg->argByReferenceServer) ? " *" : ""; + string_t msgfield = + (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField; + + if ((it->itInTrans != strNULL) && + akCheck(arg->argKind, akbSendRcv) && + !akCheck(arg->argKind, akbVarNeeded)) { + fprintf(file, "%s%s(", at, it->itInTrans); + NeedClose = TRUE; + } + + if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg)) + fprintf(file, "%s%s", at, arg->argVarName); + else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) { + if (!it->itInLine) + /* recast the void *, although it is not necessary */ + fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, "")); + else +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer && streql(it->itServerType, "ipc_port_t")) + /* recast the port to the kernel internal form value */ + fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, "")); + else +#endif + fprintf(file, "%s%s", at, InArgMsgField(arg, "")); + } + else if (akCheck(arg->argKind, akbSendRcv)) { + if (IS_OPTIONAL_NATIVE(it)) { + fprintf(file, "(%s ? ", InArgMsgField(arg, "__Present__")); + fprintf(file, "%s%s.__Real__%s : %s)", at, InArgMsgField(arg, ""), arg->argMsgField, it->itBadValue); + } + else { + if (akIdent(arg->argKind) == akeCount && arg->argParent) { + char *suffix = arg->argParent->argSuffix; + ipc_type_t *elemType = arg->argParent->argType->itElement; + /* temporarily squash any name suffix such as ".address" (we'll be adding our own) */ + arg->argParent->argSuffix = NULL; + switch (arg->argParent->argKPD_Type) { + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + /* count of the number of descriptors */ + fprintf(file, "%s%s.count", at, InArgMsgField(arg->argParent, "")); + break; + case MACH_MSG_OOL_DESCRIPTOR: + /* descriptor buffer size / element size */ + if (!(arg->argByReferenceServer || it->itNativePointer)) { + fprintf(file, "%s%s.size", at, InArgMsgField(arg->argParent, "")); + elemsize = ((elemType->itNumber * elemType->itSize) + 7) / 8; + if (elemsize > 1) { + fprintf(file, " / %d", elemsize); + } + } else { + fprintf(file, "%s%s", at, InArgMsgField(arg, "")); + } + break; + default: + fprintf(file, "%s%s", at, InArgMsgField(arg, "")); + break; + } + arg->argParent->argSuffix = suffix; + } else { + fprintf(file, "%s%s", at, InArgMsgField(arg, "")); + } + } + } + else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) { + if (!it->itInLine) + /* recast the void *, although it is not necessary */ + fprintf(file, "(%s%s)%s(OutP->%s)", it->itTransType, star, at, msgfield); + else +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer && streql(it->itServerType, "ipc_port_t")) + /* recast the port to the kernel internal form value */ + fprintf(file, "(mach_port_t%s)%s(OutP->%s)", star, at, msgfield); + else +#endif + fprintf(file, "%sOutP->%s", at, msgfield); + + } + else if (akCheck(arg->argKind, akbReturnSnd)) + fprintf(file, "%sOutP->%s", at, msgfield); + + if (NeedClose) + fprintf(file, ")"); +} + +/* + * Shrunk version of WriteServerCallArg, to implement the RetCode functionality: + * we have received a mig_reply_error_t, therefore we want to call the target + * routine with all 0s except for the error code (and the implicit data). + * We know that we are a SimpleRoutine. + */ +static void +WriteConditionalCallArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + boolean_t NeedClose = FALSE; + + if ((it->itInTrans != strNULL) && + akCheck(arg->argKind, akbSendRcv) && + !akCheck(arg->argKind, akbVarNeeded)) { + fprintf(file, "%s(", it->itInTrans); + NeedClose = TRUE; + } + + if (akCheck(arg->argKind, akbSendRcv)) { + if (akIdent(arg->argKind) == akeRequestPort || + akCheck(arg->argKind, akbServerImplicit)) + fprintf(file, "%s", InArgMsgField(arg, "")); + else if (akIdent(arg->argKind) == akeRetCode) + fprintf(file, "((mig_reply_error_t *)In0P)->RetCode"); + else + fprintf(file, "(%s)(0)", it->itTransType); + } + + if (NeedClose) + fprintf(file, ")"); +} + +static void +WriteDestroyArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + /* + * Deallocate IN/INOUT out-of-line args if specified by "auto" flag. + * + * We also have to deallocate in the cases where the target routine + * is given a itInLine semantic whereas the underlying transmission + * was out-of-line + */ + if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) && + arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR && + (arg->argFlags & flAuto)) + || + IS_MIG_INLINE_EMUL(it) + ) { + /* + * Deallocate only if out-of-line. + */ + argument_t *count = arg->argCount; + ipc_type_t *btype = it->itElement; + int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0; + + if (IsKernelServer) { + fprintf(file, "#if __MigKernelSpecificCode\n"); + fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, "")); + fprintf(file, "#else\n"); + } + fprintf(file, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg, "")); + if (it->itVarArray) { + char *suffix = arg->argSuffix; + /* + * temporarily squash any name suffix such as ".address" + * (we'll be adding our own) + */ + arg->argSuffix = NULL; + switch (arg->argKPD_Type) { + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + if (multiplier > 1) { + fprintf(file, "%d * ", multiplier); + } + fprintf(file, "%s.count);\n", InArgMsgField(arg, "")); + break; + case MACH_MSG_OOL_DESCRIPTOR: + fprintf(file, "%s.size);\n", InArgMsgField(arg, "")); + break; + default: + if (multiplier > 1) { + fprintf(file, "%d * ", multiplier); + } + fprintf(file, "%s);\n", InArgMsgField(count, "")); + break; + } + arg->argSuffix = suffix; + } + else + fprintf(file, "%d);\n", (it->itNumber * it->itSize + 7) / 8); + if (IsKernelServer) { + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + fprintf(file, "\t%s = (void *) 0;\n", InArgMsgField(arg, "")); + fprintf(file, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg->argRequestPos, arg->argMsgField, (RPCPortArray(arg) ? "count" : "size")); + } + else { + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName); + else + fprintf(file, "\t%s(%s);\n", it->itDestructor, InArgMsgField(arg, "")); + } +} + +static void +WriteDestroyPortArg(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + /* + * If a translated port argument occurs in the body of a request + * message, and the message is successfully processed, then the + * port right should be deallocated. However, the called function + * didn't see the port right; it saw the translation. So we have + * to release the port right for it. + * + * The test over it->itInTrans will exclude any complex type + * made out of ports + */ + if ((it->itInTrans != strNULL) && + (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) { + fprintf(file, "\n"); + fprintf(file, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg, "")); + fprintf(file, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, "")); + } +} + +/* + * Check whether WriteDestroyPortArg would generate any code for arg. + */ +boolean_t +CheckDestroyPortArg(argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + if ((it->itInTrans != strNULL) && + (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) { + return TRUE; + } + return FALSE; +} + +static void +WriteServerCall(FILE *file, routine_t *rt, void (*func)(FILE *, argument_t *)) +{ + argument_t *arg = rt->rtRetCode; + ipc_type_t *it = arg->argType; + boolean_t NeedClose = FALSE; + + fprintf(file, "\t"); + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "%s = ", arg->argMsgField); + else + fprintf(file, "OutP->%s = ", arg->argMsgField); + if (it->itOutTrans != strNULL) { + fprintf(file, "%s(", it->itOutTrans); + NeedClose = TRUE; + } + fprintf(file, "%s(", rt->rtServerName); + WriteList(file, rt->rtArgs, func, akbServerArg, ", ", ""); + if (NeedClose) + fprintf(file, ")"); + fprintf(file, ");\n"); +} + +static void +WriteCheckReturnValue(FILE *file, routine_t *rt) +{ + argument_t *arg = rt->rtRetCode; + char string[MAX_STR_LEN]; + + if (akCheck(arg->argKind, akbVarNeeded)) + sprintf(string, "%s", arg->argMsgField); + else + sprintf(string, "OutP->%s", arg->argMsgField); + fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string); + fprintf(file, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string); + fprintf(file, "\t}\n"); +} + +/* + * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport + * initializes the OutP KPD fields (this job cannot be done once + * the target routine has been called, otherwise informations + * would be lost) + */ +/* + * argKPD_Init discipline for Port types. + */ +static void +WriteInitKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *subindex = ""; + boolean_t close = FALSE; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + subindex = "[i]"; + close = TRUE; + } + else { + (void)sprintf(firststring, "OutP->%s", arg->argMsgField); + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + } + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + if (IS_MULTIPLE_KPD(it) && it->itVarArray) + fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string); + if (arg->argPoly == argNULL) { + if (IsKernelServer) { + fprintf(file, "#if __MigKernelSpecificCode\n"); + fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr); + fprintf(file, "#else\n"); + } + fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr); + if (IsKernelServer) + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + fprintf(file, "#if !(defined(KERNEL) && defined(__LP64__))\n"); + fprintf(file, "\t%spad1 = 0;\n", string); + fprintf(file, "#endif\n"); + fprintf(file, "\t%spad2 = 0;\n", string); + fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string); + fprintf(file, "#if defined(KERNEL)\n"); + fprintf(file, "\t%spad_end = 0;\n", string); + fprintf(file, "#endif\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + if (close) + fprintf(file, "\t }\n\t}\n"); + fprintf(file, "\n"); +} + +/* + * argKPD_Init discipline for out-of-line types. + */ +static void +WriteInitKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + boolean_t VarArray; + u_int howmany, howbig; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + howmany = it->itElement->itNumber; + howbig = it->itElement->itSize; + } + else { + (void)sprintf(firststring, "OutP->%s", arg->argMsgField); + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + howmany = it->itNumber; + howbig = it->itSize; + } + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + if (!VarArray) + fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8); + if (arg->argDeallocate != d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t%scopy = %s;\n", string, (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); +#ifdef ALIGNMENT + fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, arg->argMsgField, (howbig < 8) ? 1 : howbig / 8); +#endif + fprintf(file, "\t%spad1 = 0;\n", string); + fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string); + fprintf(file, "#if defined(KERNEL) && !defined(__LP64__)\n"); + fprintf(file, "\t%spad_end = 0;\n", string); + fprintf(file, "#endif\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); + fprintf(file, "\n"); +} + +/* + * argKPD_Init discipline for out-of-line Port types. + */ +static void +WriteInitKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + boolean_t VarArray; + ipc_type_t *howit; + u_int howmany; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + howmany = it->itElement->itNumber; + howit = it->itElement; + } + else { + (void)sprintf(firststring, "OutP->%s", arg->argMsgField); + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + howmany = it->itNumber; + howit = it; + } + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + + if (!VarArray) + fprintf(file, "\t%scount = %d;\n", string, howmany); + if (arg->argPoly == argNULL) { + if (IsKernelServer) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "\t%sdisposition = %s;\n", string, howit->itOutNameStr); + fprintf(file, "#else\n"); + } + fprintf(file, "\t%sdisposition = %s;\n", string, howit->itInNameStr); + if (IsKernelServer) + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + if (arg->argDeallocate != d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); + fprintf(file, "\n"); +} + +static void +WriteInitKPDValue(FILE *file, argument_t *arg) +{ + (*arg->argKPD_Init)(file, arg); +} + +static void +WriteAdjustMsgCircular(FILE *file, argument_t *arg) +{ + fprintf(file, "\n"); + + fprintf(file,"#if\t__MigKernelSpecificCode\n"); + if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC) + fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg->argPoly->argVarName); + + /* + * The carried port right can be accessed in OutP->XXXX. Normally + * the server function stuffs it directly there. If it is InOut, + * then it has already been copied into the reply message. + * If the server function deposited it into a variable (perhaps + * because the reply message is variable-sized) then it has already + * been copied into the reply message. + * + * The old MiG does not check for circularity in the case of + * array of ports. So do I ... + */ + + fprintf(file, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n"); + fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg->argMsgField); + fprintf(file, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg->argMsgField); + fprintf(file, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n"); + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); +} + +/* + * argKPD_Pack discipline for Port types. + */ +static void +WriteKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *subindex = ""; + char *recast = ""; + boolean_t close = FALSE; + char string[MAX_STR_LEN]; + ipc_type_t *real_it; + + if (akCheck(arg->argKind, akbVarNeeded)) { + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(string, "\tptr->"); + subindex = "[i]"; + close = TRUE; + real_it = it->itElement; + } + else { + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + real_it = it; + } +#ifdef MIG_KERNEL_PORT_CONVERSIONS + if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t")) + recast = "(mach_port_t)"; +#endif + + if (it->itOutTrans != strNULL && !close) + fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName); + else + fprintf(file, "\t%sname = %s%s%s;\n", string, recast, arg->argVarName, subindex); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) { + argument_t *poly = arg->argPoly; + + if (akCheck(arg->argPoly->argKind, akbVarNeeded)) + fprintf(file, "\t%sdisposition = %s;\n", string, poly->argVarName); + else if (close) + fprintf(file, "\t%sdisposition = OutP->%s;\n", string, poly->argSuffix); + } + if (close) + fprintf(file, "\t }\n\t}\n"); + fprintf(file, "\n"); + } + else if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd|akbVarNeeded)) + fprintf(file, "\tOutP->%s.disposition = %s;\n", arg->argMsgField, arg->argPoly->argVarName); + /* + * If this is a KernelServer, and the reply message contains + * a receive right, we must check for the possibility of a + * port/message circularity. If queueing the reply message + * would cause a circularity, we mark the reply message + * with the circular bit. + */ + if (IsKernelServer && !(IS_MULTIPLE_KPD(it)) && + ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) || + (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC))) + WriteAdjustMsgCircular(file, arg); +} + +/* + * argKPD_Pack discipline for out-of-line types. + */ +static void +WriteKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char string[MAX_STR_LEN]; + boolean_t VarArray; + argument_t *count; + u_int howbig; + char *subindex; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + count = arg->argSubCount; + howbig = it->itElement->itSize; + subindex = "[i]"; + } + else { + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + count = arg->argCount; + howbig = it->itSize; + subindex = ""; + } + + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex); + if (arg->argDealloc != argNULL) + if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + if (VarArray) { + fprintf(file, "\t%ssize = ", string); + if (akCheck(count->argKind, akbVarNeeded)) + fprintf(file, "%s%s", count->argName, subindex); + else + fprintf(file, "OutP->%s%s", count->argMsgField, subindex); + + if (count->argMultiplier > 1 || howbig > 8) + fprintf(file, " * %d;\n", count->argMultiplier * howbig / 8); + else + fprintf(file, ";\n"); + } + + if (IS_MULTIPLE_KPD(it)) { + fprintf(file, "\t }\n"); + if (it->itVarArray && !it->itElement->itVarArray) { + fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number); + /* since subordinate arrays aren't variable, they are initialized from template: + here we must no-op 'em */ + fprintf(file, "\t\tptr->size = 0;\n"); + } + fprintf(file, "\t}\n"); + } + fprintf(file, "\n"); +} + +/* + * argKPD_Pack discipline for out-of-line Port types. + */ +static void +WriteKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + boolean_t VarArray; + argument_t *count; + char *subindex, string[MAX_STR_LEN]; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + count = arg->argSubCount; + subindex = "[i]"; + } + else { + (void)sprintf(string, "OutP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + count = arg->argCount; + subindex = ""; + } + + if (akCheck(arg->argKind, akbVarNeeded)) + fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex); + if (arg->argDealloc != argNULL) + if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + if (VarArray) { + fprintf(file, "\t%scount = ", string); + if (akCheck(count->argKind, akbVarNeeded)) + fprintf(file, "%s%s;\n", count->argName, subindex); + else + fprintf(file, "OutP->%s%s;\n", count->argMsgField, subindex); + } + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) + if (akCheck(arg->argPoly->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) + fprintf(file, "\t%sdisposition = %s;\n", string, arg->argPoly->argVarName); + if (IS_MULTIPLE_KPD(it)) { + fprintf(file, "\t }\n"); + if (it->itVarArray && !it->itElement->itVarArray) { + fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number); + /* since subordinate arrays aren't variable, they are initialized from template: + here we must no-op 'em */ + fprintf(file, "\t%scount = 0;\n", string); + } + fprintf(file, "\t}\n"); + } + fprintf(file, "\n"); +} + +/* + * argKPD_TypeCheck discipline for Port types. + */ +static void +WriteTCheckKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab = ""; + char string[MAX_STR_LEN]; + boolean_t close = FALSE; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); + (void)sprintf(string, "ptr->"); + tab = "\t"; + close = TRUE; + } + else + (void)sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); + + fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string); + /* + * We can't check disposition on varArray + * (because some of the entries could be empty). + */ + if (!it->itVarArray) { + if (arg->argPoly != argNULL) { + switch (it->itOutName) { + + case MACH_MSG_TYPE_MOVE_RECEIVE: + fprintf(file, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string); + break; + + case MACH_MSG_TYPE_MOVE_SEND_ONCE: + fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab, string); + fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab, string); + break; + + case MACH_MSG_TYPE_MOVE_SEND: + fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab, string); + fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab, string); + fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab, string); + break; + } + } + else { + fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr); + } + } + fprintf(file, ")\n"); + fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n"); + if (close) + fprintf(file, "\t }\n\t}\n"); +} + +/* + * argKPD_TypeCheck discipline for out-of-line types. + */ +static void +WriteTCheckKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab, string[MAX_STR_LEN]; + boolean_t test; + u_int howmany, howbig; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); + tab = "\t\t\t"; + sprintf(string, "ptr->"); + howmany = it->itElement->itNumber; + howbig = it->itElement->itSize; + test = !it->itVarArray && !it->itElement->itVarArray; + } + else { + tab = ""; + sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); + howmany = it->itNumber; + howbig = it->itSize; + test = !it->itVarArray; + } + + fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string); + if (test) { + /* if VarArray we may use no-op; if itElement->itVarArray size might change */ + fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8); + } + + fprintf(file, ")\n"); + fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); + + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); +} + +/* + * argKPD_TypeCheck discipline for out-of-line Port types. + */ +static void +WriteTCheckKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab, string[MAX_STR_LEN]; + boolean_t test; + u_int howmany; + char *howstr; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + howmany = it->itElement->itNumber; + test = !it->itVarArray && !it->itElement->itVarArray; + howstr = it->itElement->itOutNameStr; + } + else { + tab = ""; + sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); + howmany = it->itNumber; + test = !it->itVarArray; + howstr = it->itOutNameStr; + } + + fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string); + if (test) + /* if VarArray we may use no-op; if itElement->itVarArray size might change */ + fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany); + if (arg->argPoly == argNULL) + fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr); + fprintf(file, ")\n"); + fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n"); + + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); +} + +/************************************************************* + * Writes code to check that the type of each of the arguments + * in the reply message is what is expected. Called by + * WriteRoutine for each in && typed argument in the request message. + *************************************************************/ +static void +WriteTypeCheck(FILE *file, argument_t *arg) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + (*arg->argKPD_TypeCheck)(file, arg); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + +static void +WritePackArgValueNormal(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { + if (it->itString) { + /* + * Copy variable-size C string with mig_strncpy. + * Save the string length (+ 1 for trailing 0) + * in the argument`s count field. + */ + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n"); + fprintf(file, "\t\tOutP->%s = (%s) mig_strncpy_zerofill(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber); + fprintf(file, "\t} else {\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + + fprintf(file, "\t\tOutP->%s = (%s) mig_strncpy(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber); + + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + + fprintf(file, "\tOutP->%sOffset = 0;\n", arg->argMsgField); + } + else if (it->itNoOptArray) + fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg->argMsgField, arg->argVarName, it->itTypeSize); + else { + argument_t *count = arg->argCount; + ipc_type_t *btype = it->itElement; + identifier_t newstr; + + /* Note btype->itNumber == count->argMultiplier */ + + fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg->argMsgField, arg->argVarName); + if (btype->itTypeSize > 1) + fprintf(file, "%d * ", btype->itTypeSize); + /* count is a akbVarNeeded if arg is akbVarNeeded */ + if (akCheck(count->argKind, akbVarNeeded)) + newstr = count->argVarName; + else + newstr = (identifier_t)strconcat("OutP->", count->argMsgField); + fprintf(file, "%s);\n", newstr); + } + } + else if (it->itOutTrans != strNULL) + WriteCopyType(file, it, TRUE, "OutP->%s", "/* %s */ %s(%s)", arg->argMsgField, it->itOutTrans, arg->argVarName); + else + WriteCopyType(file, it, TRUE, "OutP->%s", "/* %s */ %s", arg->argMsgField, arg->argVarName); + + if (arg->argPadName != NULL && it->itPadSize != 0) { + fprintf(file, "\t for (int i = 0; i < %d; i++)\n", it->itPadSize); + fprintf(file, "\t\t OutP->%s[i] = 0;\n", arg->argPadName); + } +} + +static void +WritePackArgValueVariable(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + /* + * only itString are treated here so far + */ + if (it->itString) { + /* + * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field + * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call + * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit). + */ + fputs("#ifdef __LP64__\n", file); + fprintf(file, "\t{\n" + "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg->argMsgField); + fputs( "\t\t" "if (strLength > 0xffffffff)\n" + "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file); + fprintf(file, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n" + "\t}\n", arg->argCount->argMsgField); + fputs("#else\n", file); + fprintf(file, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg->argCount->argMsgField, arg->argMsgField); + fputs("#endif /* __LP64__ */\n", file); + + } +} + +static void +WriteCopyArgValue(FILE *file, argument_t *arg) +{ + fprintf(file, "\n"); + WriteCopyType(file, arg->argType, TRUE, "/* %d */ OutP->%s", "In%dP->%s", arg->argRequestPos, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); +} + +static void +WriteInitArgValue(FILE *file, argument_t *arg) +{ + fprintf(file, "\n"); + fprintf(file, "\tOutP->%s = %s;\n\n", arg->argMsgField, arg->argVarName); +} + +/* + * Calculate the size of a variable-length message field. + */ +static void +WriteArgSize(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + int bsize = ptype->itElement->itTypeSize; + argument_t *count = arg->argCount; + + /* If the base type size of the data field isn`t a multiple of 4, + we have to round up. */ + if (bsize % itWordAlign != 0) + fprintf(file, "_WALIGN_"); + + /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the + * the beginning. + */ + fprintf(file, "(("); + if (bsize > 1) + fprintf(file, "%d * ", bsize); + if (ptype->itString || !akCheck(count->argKind, akbVarNeeded)) + /* get count from descriptor in message */ + fprintf(file, "OutP->%s", count->argMsgField); + else + /* get count from argument */ + fprintf(file, "%s", count->argVarName); + + /* + * If the base type size is not a multiple of sizeof(natural_t), + * we have to round up. + */ + if (bsize % sizeof(natural_t) != 0) + fprintf(file, " + %d) & ~%d)", (int)sizeof(natural_t)-1, (int)sizeof(natural_t)-1); + else + fprintf(file, "))"); +} + +/* + * Adjust message size and advance reply pointer. + * Called after packing a variable-length argument that + * has more arguments following. + */ +static void +WriteAdjustMsgSize(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + ipc_type_t *ptype = arg->argType; + + /* There are more Out arguments. We need to adjust msgh_size + and advance OutP, so we save the size of the current field + in msgh_size_delta. */ + + fprintf(file, "\tmsgh_size_delta = "); + WriteArgSize(file, arg); + fprintf(file, ";\n"); + + if (rt->rtNumReplyVar == 1) { + /* We can still address the message header directly. Fill + in the size field. */ + + fprintf(file, "\tOutP->Head.msgh_size = "); + rtMinReplySize(file, rt, "Reply"); + fprintf(file, " + msgh_size_delta;\n"); + } + else if (arg->argReplyPos == 0) { + /* First variable-length argument. The previous msgh_size value + is the minimum reply size. */ + + fprintf(file, "\tmsgh_size = "); + rtMinReplySize(file, rt, "Reply"); + fprintf(file, " + msgh_size_delta;\n"); + } + else + fprintf(file, "\tmsgh_size += msgh_size_delta;\n"); + + fprintf(file, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n", ptype->itTypeSize + ptype->itPadSize); +} + +/* + * Calculate the size of the message. Called after the + * last argument has been packed. + */ +static void +WriteFinishMsgSize(FILE *file, argument_t *arg) +{ + /* No more Out arguments. If this is the only variable Out + argument, we can assign to msgh_size directly. */ + + if (arg->argReplyPos == 0) { + fprintf(file, "\tOutP->Head.msgh_size = "); + rtMinReplySize(file, arg->argRoutine, "Reply"); + fprintf(file, " + ("); + WriteArgSize(file, arg); + fprintf(file, ");\n"); + } + else { + fprintf(file, "\tmsgh_size += "); + WriteArgSize(file, arg); + fprintf(file, ";\n"); + } +} + +/* + * Handle reply arguments - fill in message types and copy arguments + * that need to be copied. + */ +static void +WriteReplyArgs(FILE *file, routine_t *rt) +{ + argument_t *arg; + argument_t *lastVarArg; + + /* + * 1. The Kernel Processed Data + */ + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) + (*arg->argKPD_Pack)(file, arg); + /* + * 2. The Data Stream + */ + lastVarArg = argNULL; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + /* + * Adjust message size and advance message pointer if + * the last request argument was variable-length and the + * request position will change. + */ + if (lastVarArg != argNULL && + lastVarArg->argReplyPos < arg->argReplyPos) { + WriteAdjustMsgSize(file, lastVarArg); + lastVarArg = argNULL; + } + + if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded)) + WritePackArgValueNormal(file, arg); + else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable)) + WritePackArgValueVariable(file, arg); + + if (akCheck(arg->argKind, akbReplyCopy)) + WriteCopyArgValue(file, arg); + if (akCheck(arg->argKind, akbReplyInit)) + WriteInitArgValue(file, arg); + /* + * Remember whether this was variable-length. + */ + if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable)) + lastVarArg = arg; + } + /* + * Finish the message size. + */ + if (lastVarArg != argNULL) + WriteFinishMsgSize(file, lastVarArg); +} + +static void +WriteFieldDecl(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbSendKPD) || + akCheck(arg->argKind, akbReturnKPD)) + WriteFieldDeclPrim(file, arg, FetchKPDType); + else + WriteFieldDeclPrim(file, arg, FetchServerType); +} + +static void +InitKPD_Disciplines(argument_t *args) +{ + argument_t *arg; + extern void KPD_noop(FILE *file, argument_t *arg); + extern void KPD_error(FILE *file, argument_t *arg); + extern void WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in); + extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in); + extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in); + + /* + * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port, + * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool, + * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport + * are local to this module (which is the reason why this initialization + * takes place here rather than in utils.c). + * Common routines for user and server will be established SOON, and + * all of them (including the initialization) will be transfert to + * utils.c + * All the KPD disciplines are defaulted to be KPD_error(). + * Note that akbSendKPD and akbReturnKPd are not exclusive, + * because of inout type of parameters. + */ + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Extract = + (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_port : WriteExtractArgValue; + arg->argKPD_TypeCheck = WriteTCheckKPD_port; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_Template = WriteTemplateKPD_port; + arg->argKPD_Init = WriteInitKPD_port; + arg->argKPD_Pack = WriteKPD_port; + } + break; + + case MACH_MSG_OOL_DESCRIPTOR: + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Extract = + (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_ool : WriteExtractArgValue; + arg->argKPD_TypeCheck = WriteTCheckKPD_ool; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_Template = WriteTemplateKPD_ool; + arg->argKPD_Init = WriteInitKPD_ool; + arg->argKPD_Pack = WriteKPD_ool; + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Extract = + (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_oolport : WriteExtractArgValue; + arg->argKPD_TypeCheck = WriteTCheckKPD_oolport; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_Template = WriteTemplateKPD_oolport; + arg->argKPD_Init = WriteInitKPD_oolport; + arg->argKPD_Pack = WriteKPD_oolport; + } + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ +} + +static void WriteStringTerminatorCheck(FILE *file, routine_t *rt) +{ + // generate code to verify that the length of a C string is not greater than the size of the + // buffer in which it is stored. + argument_t *argPtr; + int msg_limit_calculated = FALSE; + int found_string_argument = FALSE; + int variable_length_args_present = (rt->rtMaxRequestPos > 0); + + // scan through arguments to see if there are any strings + for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { + if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) { + found_string_argument = TRUE; + break; + } + } + + if (found_string_argument) { + // create a new scope, for local variables + fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file); + + for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { + if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) { + //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber); + + if (!msg_limit_calculated) { + msg_limit_calculated = TRUE; // only need to do this once + fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file); + if (IsKernelServer) { + fputs("#if __MigKernelSpecificCode\n", file); + fputs("\t\t" "size_t strnlen_limit;" "\n", file); + fputs("#else\n", file); + } + fputs("\t\t" "size_t memchr_limit;" "\n", file); + if (IsKernelServer) { + fputs("#endif /* __MigKernelSpecificCode */" "\n", file); + } + fputc('\n', file); + } + + // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond + // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(), + // and let it look for the terminating null byte. + // (later...) + // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just + // have to emit some conditional code to use the appropriate runtime environment scanning function. + // + if (IsKernelServer) { + fputs("#if __MigKernelSpecificCode\n", file); + fputs("\t\t" "strnlen_limit = min((msg_limit - ", file); + // If there are variable-length arguments within the message, the proper (adjusted) + // pointers must be used to access those strings + fprintf(file, "In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); + fputs("\t\t" "if (", file); + fprintf(file, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); + fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file); + fputs("#else\n", file); + } + // If there are variable-length arguments within the message, the proper (adjusted) + // pointers must be used to access those strings + fprintf(file, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); + fputs("\t\t" "if (", file); + fprintf(file, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName); + fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file); + if (IsKernelServer) { + fputs("#endif /* __MigKernelSpecificCode */" "\n", file); + } + } + } + fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); // terminate new scope + } + + return; +} + +static void +WriteOOLSizeCheck(FILE *file, routine_t *rt) +{ + /* Emit code to validate the actual size of ool data vs. the reported size */ + + argument_t *argPtr; + boolean_t openedTypeCheckConditional = FALSE; + + // scan through arguments to see if there are any ool data blocks + for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { + if (akCheck(argPtr->argKind, akbSendKPD)) { + ipc_type_t *it = argPtr->argType; + boolean_t multiple_kpd = IS_MULTIPLE_KPD(it); + char string[MAX_STR_LEN]; + boolean_t test; + argument_t *argCountPtr; + char *tab; + + if (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + + if (multiple_kpd) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + test = !it->itVarArray && !it->itElement->itVarArray; + it = it->itElement; // point to element descriptor, so size calculation is correct + argCountPtr = argPtr->argSubCount; + } else { + tab = ""; + sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField); + test = !it->itVarArray; + argCountPtr = argPtr->argCount; + } + + if (!test) { + int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1; + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + fprintf(file, "\t%s" "if (%ssize ", tab, string); + if (multiplier > 1) + fprintf(file, "/ %d ", multiplier); + fprintf(file,"!= In%dP->%s%s", argCountPtr->argRequestPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : ""); + if (it->itOOL_Number) { + fprintf(file," || In%dP->%s%s > %d", argCountPtr->argRequestPos, + argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number); + } + + fprintf(file,")\n"); + fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); + } + + if (multiple_kpd) + fprintf(file, "\t }\n\t}\n"); + } else if (argPtr->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR) { + if (multiple_kpd) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + test = !it->itVarArray && !it->itElement->itVarArray; + it = it->itElement; // point to element descriptor, so size calculation is correct + argCountPtr = argPtr->argSubCount; + } else { + tab = ""; + sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField); + test = !it->itVarArray; + argCountPtr = argPtr->argCount; + } + + if (!test) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + fprintf(file, "\t%s" "if (%scount ", tab, string); + fprintf(file,"!= In%dP->%s%s", argCountPtr->argRequestPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : ""); + if (it->itOOL_Number) { + fprintf(file," || In%dP->%s%s > %d", argCountPtr->argRequestPos, + argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number); + } + fprintf(file,")\n"); + fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); + } + + if (multiple_kpd) + fprintf(file, "\t }\n\t}\n"); + } + } + } + + if ( openedTypeCheckConditional ) + fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); +} + + +void +WriteCheckRequest(FILE *file, routine_t *rt) +{ + int i; + + /* initialize the disciplines for the handling of KPDs */ + InitKPD_Disciplines(rt->rtArgs); + + fprintf(file, "\n"); + fprintf(file, "#if ( __MigTypeCheck "); + if (CheckNDR) + fprintf(file, "|| __NDR_convert__ "); + fprintf(file, ")\n"); + fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName); + fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName); + fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName); + if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) { + WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", ""); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", ""); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", ""); + } + fprintf(file, "\n"); + fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt->rtName, rt->rtName); + for (i = 1; i <= rt->rtMaxRequestPos; i++) + fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i); + fprintf(file, ")\n{\n"); + + fprintf(file, "\n\ttypedef __Request__%s_t __Request;\n", rt->rtName); + for (i = 1; i <= rt->rtMaxRequestPos; i++) + fprintf(file, "\t__Request *In%dP;\n", i); + if (rt->rtNumRequestVar > 0) { + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tunsigned int msgh_size;\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + if (rt->rtMaxRequestPos > 0) + fprintf(file, "\tunsigned int msgh_size_delta;\n"); + if (rt->rtNumRequestVar > 0 || rt->rtMaxRequestPos > 0) + fprintf(file, "\n"); + + WriteCheckHead(file, rt); + + WriteList(file, rt->rtArgs, WriteTypeCheck, akbSendKPD, "\n", "\n"); + + { + argument_t *arg, *lastVarArg; + + lastVarArg = argNULL; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (lastVarArg != argNULL && + lastVarArg->argRequestPos < arg->argRequestPos) { + WriteAdjustRequestMsgPtr(file, lastVarArg); + lastVarArg = argNULL; + } + if (akCheckAll(arg->argKind, akbSendRcv|akbSendBody)) { + if (akCheck(arg->argKind, akbVariable)) { + WriteCheckMsgSize(file, arg); + lastVarArg = arg; + } + } + } + } + + if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) { + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgCond, akbSendNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgUse, akbSendNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n"); + + WriteOOLSizeCheck(file, rt); + + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgCond, akbSendNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgUse, akbSendNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n"); + + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgCond, akbSendNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n"); + WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgUse, akbSendNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n"); + } else { + WriteOOLSizeCheck(file, rt); + } + + WriteStringTerminatorCheck(file, rt); + + fprintf(file, "\treturn MACH_MSG_SUCCESS;\n"); + fprintf(file, "}\n"); + fprintf(file, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName); + fprintf(file, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName); + fprintf(file, "#endif /* ( __MigTypeCheck "); + if (CheckNDR) + fprintf(file, "|| __NDR_convert__ "); + fprintf(file, ") */\n"); + fprintf(file, "\n"); +} + +void +WriteCheckRequestCall(FILE *file, routine_t *rt) +{ + int i; + + fprintf(file, "\n"); + fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName); + fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName); + for (i = 1; i <= rt->rtMaxRequestPos; i++) + fprintf(file, ", (__Request **)&In%dP", i); + fprintf(file, ");\n"); + fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n"); + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n"); + fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName); + fprintf(file, "\n"); +} + +void +WriteCheckRequests(FILE *file, statement_t *stats) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) + WriteCheckRequest(file, stat->stRoutine); +} + +static void +WriteRoutine(FILE *file, routine_t *rt) +{ + /* Declare the server work function: */ + if (ServerHeaderFileName == strNULL) + WriteServerRoutine(file, rt); + + fprintf(file, "\n"); + + fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); + fprintf(file, "mig_internal novalue _X%s\n", rt->rtName); + if (BeAnsiC) { + fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); + fprintf(file, "#else\n"); + fprintf(file, "\t(InHeadP, OutHeadP)\n"); + fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + + fprintf(file, "{\n"); + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE); + fprintf(file, "\ttypedef __Request__%s_t __Request;\n", rt->rtName); + fprintf(file, "\ttypedef __Reply__%s_t Reply __attribute__((unused));\n\n", rt->rtName); + + /* + * Define a Minimal Reply structure to be used in case of errors + */ + fprintf(file, "\t/*\n"); + fprintf(file, "\t * typedef struct {\n"); + fprintf(file, "\t * \tmach_msg_header_t Head;\n"); + fprintf(file, "\t * \tNDR_record_t NDR;\n"); + fprintf(file, "\t * \tkern_return_t RetCode;\n"); + fprintf(file, "\t * } mig_reply_error_t;\n"); + fprintf(file, "\t */\n"); + fprintf(file, "\n"); + + WriteVarDecls(file, rt); + + if (IsKernelServer) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + WriteList(file, rt->rtArgs, WriteTemplateDeclOut, akbReturnKPD, "\n", "\n"); + fprintf(file, "#else\n"); + } + WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbReturnKPD, "\n", "\n"); + if (IsKernelServer) { + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + WriteRetCode(file, rt->rtRetCode); + WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded | akbServerArg, ";\n", ";\n\n"); + WriteApplMacro(file, "Rcv", "Declare", rt); + WriteApplMacro(file, "Rcv", "Before", rt); + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + WriteRetCArgCheckError(file, rt); + if (rt->rtServerImpl) + WriteCheckTrailerHead(file, rt, FALSE); + WriteServerCall(file, rt, WriteConditionalCallArg); + WriteRetCArgFinishError(file, rt); + } + + WriteCheckRequestCall(file, rt); + WriteCheckRequestTrailerArgs(file, rt); + + /* + * Initialize the KPD records in the Reply structure with the + * templates. We do this beforehand because the call to the procedure + * will overwrite some of the values (after the call it would be impossible + * to initialize the KPD records from the static Templates, because we + * would lose data). + */ + WriteList(file, rt->rtArgs, WriteInitKPDValue, akbReturnKPD, "\n", "\n"); + + WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", ""); + + if (UseEventLogger) + WriteLogMsg(file, rt, LOG_SERVER, LOG_REQUEST); + + WriteServerCall(file, rt, WriteServerCallArg); + + WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", ""); + + /* + * For one-way routines, it doesn`t make sense to check the return + * code, because we return immediately afterwards. However, + * kernel servers may want to deallocate port arguments - and the + * deallocation must not be done if the return code is not KERN_SUCCESS. + */ + if (rt->rtOneWay || rt->rtNoReplyArgs) { + if (IsKernelServer) { + fprintf(file,"#if\t__MigKernelSpecificCode\n"); + if (rtCheckMaskFunction(rt->rtArgs, akbSendKPD, CheckDestroyPortArg)) { + WriteCheckReturnValue(file, rt); + } + WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", ""); + fprintf(file,"#endif /* __MigKernelSpecificCode */\n"); + } + /* although we have an empty reply, we still have to make sure that + some fields such as NDR get properly initialized */ + if (!rt->rtOneWay) + WriteList(file, rt->rtArgs, WriteInitArgValue, akbReplyInit, "\n", "\n"); + } + else { + WriteCheckReturnValue(file, rt); + + if (IsKernelServer) { + fprintf(file,"#if\t__MigKernelSpecificCode\n"); + WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", ""); + fprintf(file,"#endif /* __MigKernelSpecificCode */\n"); + } + WriteReplyArgs(file, rt); + WriteReplyInit(file, rt); + if (!rt->rtSimpleReply) + fprintf(file, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt->rtReplyKPDs); + } + if (UseEventLogger) + WriteLogMsg(file, rt, LOG_SERVER, LOG_REPLY); + + WriteApplMacro(file, "Rcv", "After", rt); + fprintf(file, "}\n"); +} + +void +WriteServer(FILE *file, statement_t *stats) +{ + statement_t *stat; + + WriteProlog(file, stats); + if (BeAnsiC) + WriteForwardDeclarations(file, stats); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: + WriteCheckRequest(file, stat->stRoutine); + WriteRoutine(file, stat->stRoutine); + break; + + case skIImport: + case skImport: + case skSImport: + case skDImport: + case skUImport: + break; + + default: + fatal("WriteServer(): bad statement_kind_t (%d)", + (int) stat->stKind); + } + WriteDispatcher(file, stats); +} diff --git a/bootstrap_cmds/migcom.tproj/statement.c b/bootstrap_cmds/migcom.tproj/statement.c new file mode 100644 index 0000000..5a2476d --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/statement.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "error.h" +#include "alloc.h" +#include "statement.h" + +statement_t *stats = stNULL; +static statement_t **last = &stats; + +statement_t * +stAlloc(void) +{ + statement_t *new; + + new = (statement_t *) malloc(sizeof *new); + if (new == stNULL) + fatal("stAlloc(): %s", strerror(errno)); + *last = new; + last = &new->stNext; + new->stNext = stNULL; + return new; +} diff --git a/bootstrap_cmds/migcom.tproj/statement.h b/bootstrap_cmds/migcom.tproj/statement.h new file mode 100644 index 0000000..ca3f5ba --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/statement.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University + * Created. + */ + +#ifndef _STATEMENT_H +#define _STATEMENT_H + +#include "routine.h" + +typedef enum statement_kind +{ + skRoutine, + skImport, + skUImport, + skSImport, + skDImport, + skIImport, + skRCSDecl +} statement_kind_t; + +typedef struct statement +{ + statement_kind_t stKind; + struct statement *stNext; + union + { + /* when stKind == skRoutine */ + routine_t *_stRoutine; + /* when stKind == skImport, skUImport, skSImport, skDImport, skIImport */ + string_t _stFileName; + } data; +} statement_t; + +#define stRoutine data._stRoutine +#define stFileName data._stFileName + +#define stNULL ((statement_t *) 0) + +/* stNext will be initialized to put the statement in the list */ +extern statement_t *stAlloc(void); + +/* list of statements, in order they occur in the .defs file */ +extern statement_t *stats; + +#endif /* _STATEMENT_H */ diff --git a/bootstrap_cmds/migcom.tproj/strdefs.h b/bootstrap_cmds/migcom.tproj/strdefs.h new file mode 100644 index 0000000..00a386d --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/strdefs.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * 91/02/05 17:55:57 mrt + * Changed to new Mach copyright + * [91/02/01 17:56:03 mrt] + * + * 90/06/02 15:05:49 rpd + * Created for new IPC. + * [90/03/26 21:13:56 rpd] + * + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 15-Jun-87 David Black (dlb) at Carnegie-Mellon University + * Fixed strNULL to be the null string instead of the null string + * pointer. + * + * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University + * Created. + */ + +#ifndef STRDEFS_H +#define STRDEFS_H + +#include +#include + +typedef char *string_t; +typedef string_t identifier_t; + +#define MAX_STR_LEN 200 + +#define strNULL ((string_t) 0) + +extern string_t strmake( char *string ); +extern string_t strconcat( string_t left, string_t right ); +extern string_t strphrase( string_t left, string_t right ); +extern void strfree( string_t string ); + +#define streql(a, b) (strcmp((a), (b)) == 0) + +extern char *strbool( boolean_t bool ); +extern char *strstring( string_t string ); +extern char *toupperstr( char *string ); + +#endif /* STRDEFS_H */ diff --git a/bootstrap_cmds/migcom.tproj/string.c b/bootstrap_cmds/migcom.tproj/string.c new file mode 100644 index 0000000..b7e0355 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/string.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include +#include "error.h" +#include "alloc.h" +#include "strdefs.h" + +string_t +strmake(char *string) +{ + string_t saved; + + saved = malloc(strlen(string) + 1); + if (saved == strNULL) + fatal("strmake('%s'): %s", string, strerror(errno)); + return strcpy(saved, string); +} + +string_t +strconcat(string_t left, string_t right) +{ + string_t saved; + + saved = malloc(strlen(left) + strlen(right) + 1); + if (saved == strNULL) + fatal("strconcat('%s', '%s'): %s", left, right, strerror(errno)); + return strcat(strcpy(saved, left), right); +} + +string_t +strphrase(string_t left, string_t right) +{ + string_t saved; + string_t current; + size_t llen; + + llen = strlen(left); + saved = malloc(llen + strlen(right) + 2); + if (saved == strNULL) + fatal("strphrase('%s', '%s'): %s", left, right, strerror(errno)); + strcpy(saved, left); + current = saved + llen; + *(current++) = ' '; + strcpy(current, right); + free(left); + return(saved); +} + +void +strfree(string_t string) +{ + free(string); +} + +char * +strbool(boolean_t bool) +{ + if (bool) + return "TRUE"; + else + return "FALSE"; +} + +char * +strstring(string_t string) +{ + if (string == strNULL) + return "NULL"; + else + return string; +} + +char * +toupperstr(char *p) +{ + char *s = p; + char c; + + while ((c = *s)) { + if (islower(c)) + *s = toupper(c); + s++; + } + return(p); +} diff --git a/bootstrap_cmds/migcom.tproj/type.c b/bootstrap_cmds/migcom.tproj/type.c new file mode 100644 index 0000000..db9473f --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/type.c @@ -0,0 +1,899 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include "type.h" +#include +#include +#include +#include +#include "mig_machine.h" +#include "routine.h" +#include "error.h" +#include "alloc.h" +#include "global.h" +#include + +#define PortSize (sizeof (mach_port_t) * NBBY) + +ipc_type_t *itRetCodeType; /* used for return codes */ +ipc_type_t *itNdrCodeType; /* used for NDR format labels */ +ipc_type_t *itDummyType; /* used for camelot dummy args */ +ipc_type_t *itTidType; /* used for camelot tids */ +ipc_type_t *itRequestPortType; /* used for default Request port arg */ +ipc_type_t *itZeroReplyPortType;/* used for dummy Reply port arg */ +ipc_type_t *itRealReplyPortType;/* used for default Reply port arg */ +ipc_type_t *itWaitTimeType; /* used for dummy WaitTime args */ +ipc_type_t *itMsgOptionType; /* used for dummy MsgOption args */ + +static ipc_type_t *list = itNULL; + +static char *machine_integer_name; +static u_int machine_integer_size; +static u_int machine_integer_bits; + +/* + * Searches for a named type. We use a simple + * self-organizing linked list. + */ +ipc_type_t * +itLookUp(identifier_t name) +{ + ipc_type_t *it, **last; + + for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext)) + if (streql(name, it->itName)) { + /* move this type to the front of the list */ + *last = it->itNext; + it->itNext = list; + list = it; + + return it; + } + + return itNULL; +} + +/* + * Enters a new name-type association into + * our self-organizing linked list. + */ +void +itInsert(identifier_t name, ipc_type_t *it) +{ + it->itName = name; + it->itNext = list; + list = it; +} + +static ipc_type_t * +itAlloc(void) +{ + static ipc_type_t prototype = + { + strNULL, /* identifier_t itName */ + 0, /* ipc_type_t *itNext */ + 0, /* u_int itTypeSize */ + 0, /* u_int itPadSize */ + 0, /* u_int itMinTypeSize */ + 0, /* u_int itInName */ + 0, /* u_int itOutName */ + 0, /* u_int itSize */ + 1, /* u_int itNumber */ + 0, /* u_int itKPD_Number */ + TRUE, /* boolean_t itInLine */ + FALSE, /* boolean_t itMigInLine */ + FALSE, /* boolean_t itPortType */ + strNULL, /* string_t itInNameStr */ + strNULL, /* string_t itOutNameStr */ + TRUE, /* boolean_t itStruct */ + FALSE, /* boolean_t itString */ + FALSE, /* boolean_t itVarArray */ + FALSE, /* boolean_t itNoOptArray */ + FALSE, /* boolean_t itNative */ + FALSE, /* boolean_t itNativePointer */ + itNULL, /* ipc_type_t *itElement */ + strNULL, /* identifier_t itUserType */ + strNULL, /* identifier_t itServerType */ + strNULL, /* identifier_t itTransType */ + strNULL, /* identifier_t itUserKPDType */ + strNULL, /* identifier_t itServerKPDType */ + strNULL, /* identifier_t itInTrans */ + strNULL, /* identifier_t itOutTrans */ + strNULL, /* identifier_t itDestructor */ + }; + ipc_type_t *new; + + new = (ipc_type_t *) malloc(sizeof *new); + if (new == itNULL) + fatal("itAlloc(): %s", strerror(errno)); + *new = prototype; + return new; +} + +/* + * Convert an IPC type-name into a string. + */ +static char * +itNameToString(u_int name) +{ + char buffer[100]; + + (void) sprintf(buffer, "%u", name); + return strmake(buffer); +} + +/* + * Calculate itTypeSize, itPadSize, itMinTypeSize + * Every type needs this info; it is recalculated + * when itInLine, itNumber, or itSize changes. + */ +static void +itCalculateSizeInfo(ipc_type_t *it) +{ + if (!IS_KERN_PROC_DATA(it)) + { + u_int bytes = (it->itNumber * it->itSize + 7) / 8; + u_int padding = machine_padding(bytes); + + it->itTypeSize = bytes; + it->itPadSize = padding; + if (IS_VARIABLE_SIZED_UNTYPED(it)) { + /* + * for these arrays, the argCount is not a akbRequest|akbReply, + * therefore we need to account here for the space of the count + * (itMinTypeSize is used only in rtFindSize) + */ + it->itMinTypeSize = sizeof (mach_msg_type_number_t); + /* + * NDR encoded VarString carry the extra offset 4-bytes fields + * for MIG, it should be always 0; + */ + if (it->itString) + it->itMinTypeSize += sizeof (mach_msg_type_number_t); + } + else + it->itMinTypeSize = bytes + padding; + } + else { + /* + * 1) ports 2) OOL 3) ports OOL + * all have the same size = sizeof(mach_msg_descriptor_t) + */ + u_int bytes; + if (IS_MULTIPLE_KPD(it)) + bytes = it->itKPD_Number * 12 /* sizeof(mach_msg_descriptor_t) */; + else + bytes = 12 /* sizeof(mach_msg_descriptor_t) */; + + it->itTypeSize = bytes; + it->itPadSize = 0; + it->itMinTypeSize = bytes; + } + + /* Unfortunately, these warning messages can't give a type name; + we haven't seen a name yet (it might stay anonymous.) */ + + if ((it->itTypeSize == 0) && !it->itVarArray && !it->itNative) + warn("sizeof(%s) == 0"); +} + +/* + * Fill in default values for some fields used in code generation: + * itInNameStr, itOutNameStr, itUserType, itServerType, itTransType + * Every argument's type should have these values filled in. + */ +static void +itCalculateNameInfo(ipc_type_t *it) +{ + if (it->itInNameStr == strNULL) + it->itInNameStr = strmake(itNameToString(it->itInName)); + if (it->itOutNameStr == strNULL) + it->itOutNameStr = strmake(itNameToString(it->itOutName)); + + if (it->itUserType == strNULL) + it->itUserType = it->itName; + if (it->itServerType == strNULL) + it->itServerType = it->itName; +#if 0 + /* + * KernelServer and KernelUser interfaces get special treatment here. + * On the kernel side of the interface, ports are really internal + * port pointers (ipc_port_t), not port names (mach_port_t). + * At this point, we don't know if the argument is in or out, + * so we don't know if we should look at itInName or itOutName. + * Looking at both should be OK. + * + * This is definitely a hack, but I think it is cleaner than + * mucking with type declarations throughout the kernel .def files, + * hand-conditionalizing on KERNEL_SERVER and KERNEL_USER. + */ + + if (IsKernelServer && + streql(it->itServerType, "mach_port_t") && + (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) && + (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) || + MACH_MSG_TYPE_PORT_ANY(it->itInName) || + MACH_MSG_TYPE_PORT_ANY(it->itOutName))) + it->itServerType = "ipc_port_t"; + + if (IsKernelUser && + streql(it->itUserType, "mach_port_t") && + (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) && + (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) || + MACH_MSG_TYPE_PORT_ANY(it->itInName) || + MACH_MSG_TYPE_PORT_ANY(it->itOutName))) + it->itUserType = "ipc_port_t"; +#endif /* 0 */ + + if (it->itTransType == strNULL) + it->itTransType = it->itServerType; +} + +/****************************************************** + * Checks for non-implemented types, conflicting type + * flags and whether the long or short form of msg type + * descriptor is appropriate. Called after each type statement + * is parsed. + ******************************************************/ +static void +itCheckDecl(identifier_t name, ipc_type_t *it) +{ + it->itName = name; + + itCalculateNameInfo(it); + + /* do a bit of error checking, mostly necessary because of + limitations in Mig */ + + if (it->itVarArray) { + if ((it->itInTrans != strNULL) || (it->itOutTrans != strNULL)) + error("%s: can't translate variable-sized arrays", name); + + if (it->itDestructor != strNULL) + error("%s: can't destroy variable-sized array", name); + } +} + +/* + * Pretty-prints translation/destruction/type information. + */ +static void +itPrintTrans(ipc_type_t *it) +{ + if (!streql(it->itName, it->itUserType)) + printf("\tCUserType:\t%s\n", it->itUserType); + + if (!streql(it->itName, it->itServerType)) + printf("\tCServerType:\t%s\n", it->itServerType); + + if (it->itInTrans != strNULL) + printf("\tInTran:\t\t%s %s(%s)\n", it->itTransType, it->itInTrans, it->itServerType); + + if (it->itOutTrans != strNULL) + printf("\tOutTran:\t%s %s(%s)\n", it->itServerType, it->itOutTrans, it->itTransType); + + if (it->itDestructor != strNULL) + printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType); +} + +/* + * Pretty-prints type declarations. + */ +static void +itPrintDecl(identifier_t name, ipc_type_t *it) +{ + printf("Type %s = ", name); + if (!it->itInLine) + printf("^ "); + if (it->itVarArray) + if (it->itNumber == 0 || it->itMigInLine) + printf("array [] of "); + else + printf("array [*:%d] of ", it->itNumber); + else if (it->itStruct && ((it->itNumber != 1) || + (it->itInName == MACH_MSG_TYPE_STRING_C))) + printf("struct [%d] of ", it->itNumber); + else if (it->itNumber != 1) + printf("array [%d] of ", it->itNumber); + + if (streql(it->itInNameStr, it->itOutNameStr)) + printf("(%s,", it->itInNameStr); + else + printf("(%s|%s", it->itInNameStr, it->itOutNameStr); + + printf(" %d)\n", it->itSize); + + itPrintTrans(it); + + printf("\n"); +} + +/* + * Handles named type-specs, which can occur in type + * declarations or in argument lists. For example, + * type foo = type-spec; // itInsert will get called later + * routine foo(arg : bar = type-spec); // itInsert won't get called + */ +void +itTypeDecl(identifier_t name, ipc_type_t *it) +{ + itCheckDecl(name, it); + + if (BeVerbose) + itPrintDecl(name, it); +} + +/* + * Handles declarations like + * type new = name; + * type new = inname|outname; + */ +ipc_type_t * +itShortDecl(u_int inname, string_t instr, u_int outname, string_t outstr, u_int defsize) +{ + ipc_type_t *it; + + if (defsize == 0) + error("must use full IPC type decl"); + + it = itAlloc(); + it->itInName = inname; + it->itInNameStr = instr; + it->itOutName = outname; + it->itOutNameStr = outstr; + it->itSize = defsize; + if (inname == MACH_MSG_TYPE_STRING_C) + { + it->itStruct = FALSE; + it->itString = TRUE; + } + /* + * I check only inname, because outname + * has to be a port as well (polymorphic types + * are now restricted to port rights) + */ + if (MACH_MSG_TYPE_PORT_ANY(inname) || + inname == MACH_MSG_TYPE_POLYMORPHIC) { + it->itPortType = TRUE; + it->itKPD_Number = 1; + } + + itCalculateSizeInfo(it); + return it; +} + +static ipc_type_t * +itCopyType(ipc_type_t *old) +{ + ipc_type_t *new = itAlloc(); + + *new = *old; + new->itName = strNULL; + new->itNext = itNULL; + new->itElement = old; + + /* size info still valid */ + return new; +} + +/* + * A call to itCopyType is almost always followed with itResetType. + * The exception is itPrevDecl. Also called before adding any new + * translation/destruction/type info (see parser.y). + * + * type new = old; // new doesn't get old's info + * type new = array[*:10] of old; + * // new doesn't get old's info, but new->itElement does + * type new = array[*:10] of struct[3] of old; + * // new and new->itElement don't get old's info + */ + +ipc_type_t * +itResetType(ipc_type_t *old) +{ + /* reset all special translation/destruction/type info */ + + old->itInTrans = strNULL; + old->itOutTrans = strNULL; + old->itDestructor = strNULL; + old->itUserType = strNULL; + old->itServerType = strNULL; + old->itTransType = strNULL; + return old; +} + +/* + * Handles the declaration + * type new = old; + */ +ipc_type_t * +itPrevDecl(identifier_t name) +{ + ipc_type_t *old; + + old = itLookUp(name); + if (old == itNULL) { + error("type '%s' not defined", name); + return itAlloc(); + } + else + return itCopyType(old); +} + +/* + * Handles the declarations + * type new = array[] of old; // number is oo + * type new = array[*] of old; // number is oo + * type new = array[*:number] of old; + */ +ipc_type_t * +itVarArrayDecl(u_int number, ipc_type_t *old) +{ + ipc_type_t *it = itResetType(itCopyType(old)); + + if (!it->itInLine) { + /* already an initialized KPD */ + if (it->itKPD_Number != 1 || !number) + error("IPC type decl is too complicated for Kernel Processed Data"); + it->itKPD_Number *= number; + it->itNumber = 1; + it->itInLine = FALSE; + it->itStruct = FALSE; + it->itOOL_Number = number; + } + else if (it->itVarArray) + error("IPC type decl is too complicated"); + else if (number) { + it->itNumber *= number; + /* + * Bounded [Scalar, Port] VarArray: in-line! + */ + it->itInLine = TRUE; + it->itStruct = FALSE; + if (it->itPortType) + it->itKPD_Number *= number; + it->itOOL_Number = number; + } + else { + it->itNumber = 0; + /* + * UnBounded [Scalar, Port] VarArray: always in-line + * interface and out-of-line mechanism! + */ + it->itMigInLine = TRUE; + it->itInLine = FALSE; + it->itStruct = TRUE; + it->itKPD_Number = 1; + it->itOOL_Number = 0; + } + + it->itVarArray = TRUE; + it->itString = FALSE; + + itCalculateSizeInfo(it); + return it; +} + +/* + * Handles the declaration + * type new = array[number] of old; + */ +ipc_type_t * +itArrayDecl(u_int number, ipc_type_t *old) +{ + ipc_type_t *it = itResetType(itCopyType(old)); + + if (!it->itInLine) { + /* already an initialized KPD */ + if (it->itKPD_Number != 1) + error("IPC type decl is too complicated for Kernel Processed Data"); + it->itKPD_Number *= number; + it->itNumber = 1; + it->itStruct = FALSE; + it->itString = FALSE; + it->itVarArray = FALSE; + } + else if (it->itVarArray) + error("IPC type decl is too complicated"); + else { + it->itNumber *= number; + it->itStruct = FALSE; + it->itString = FALSE; + if (it->itPortType) + it->itKPD_Number *= number; + } + + itCalculateSizeInfo(it); + return it; +} + +/* + * Handles the declaration + * type new = ^ old; + */ +ipc_type_t * +itPtrDecl(ipc_type_t *it) +{ + if (!it->itInLine && !it->itMigInLine) + error("IPC type decl is already defined to be Out-Of-Line"); + it->itInLine = FALSE; + it->itStruct = TRUE; + it->itString = FALSE; + it->itMigInLine = FALSE; + it->itKPD_Number = 1; + + itCalculateSizeInfo(it); + return it; +} + +/* + * Handles the declaration + * type new = struct[number] of old; + */ +ipc_type_t * +itStructDecl(u_int number, ipc_type_t *old) +{ + ipc_type_t *it = itResetType(itCopyType(old)); + + if (!it->itInLine || it->itVarArray) + error("IPC type decl is too complicated"); + it->itNumber *= number; + it->itStruct = TRUE; + it->itString = FALSE; + + itCalculateSizeInfo(it); + return it; +} + +/* + * Treat 'c_string[n]' as + * 'array[n] of (MSG_TYPE_STRING_C, 8)' + */ +ipc_type_t * +itCStringDecl(int count, boolean_t varying) +{ + ipc_type_t *it; + ipc_type_t *itElement; + + itElement = itShortDecl(MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", 8); + itCheckDecl("char", itElement); + + it = itResetType(itCopyType(itElement)); + it->itNumber = count; + it->itVarArray = varying; + it->itStruct = FALSE; + it->itString = TRUE; + + itCalculateSizeInfo(it); + return it; +} + +extern ipc_type_t * +itMakeSubCountType(int count, boolean_t varying, string_t name) +{ + ipc_type_t *it; + ipc_type_t *itElement; + + itElement = itShortDecl(machine_integer_size, machine_integer_name, machine_integer_size, machine_integer_name, machine_integer_bits); + itCheckDecl("mach_msg_type_number_t", itElement); + + it = itResetType(itCopyType(itElement)); + it->itNumber = count; + /* + * I cannot consider it as a Fixed array, otherwise MiG will try + * to follow the path for efficient copy of arrays + */ + it->itVarArray = FALSE; + it->itStruct = FALSE; + it->itString = FALSE; + it->itInLine = TRUE; + it->itName = "mach_msg_type_number_t *"; + if (varying) + it->itVarArray = TRUE; + else + /* to skip the optimized copy of fixed array: in fact we need to + * reference each element and we also miss a user type for it */ + it->itNoOptArray = TRUE; + + itCalculateSizeInfo(it); + itCalculateNameInfo(it); + return it; +} + +extern ipc_type_t * +itMakeCountType(void) +{ + ipc_type_t *it = itAlloc(); + + it->itName = "mach_msg_type_number_t"; + it->itInName = machine_integer_size; + it->itInNameStr = machine_integer_name; + it->itOutName = machine_integer_size; + it->itOutNameStr = machine_integer_name; + it->itSize = machine_integer_bits; + + itCalculateSizeInfo(it); + itCalculateNameInfo(it); + return it; +} + +extern ipc_type_t * +itMakePolyType(void) +{ + ipc_type_t *it = itAlloc(); + + it->itName = "mach_msg_type_name_t"; + it->itInName = machine_integer_size; + it->itInNameStr = machine_integer_name; + it->itOutName = machine_integer_size; + it->itOutNameStr = machine_integer_name; + it->itSize = machine_integer_bits; + + itCalculateSizeInfo(it); + itCalculateNameInfo(it); + return it; +} + +extern ipc_type_t * +itMakeDeallocType(void) +{ + ipc_type_t *it = itAlloc(); + + it->itName = "boolean_t"; + it->itInName = MACH_MSG_TYPE_BOOLEAN; + it->itInNameStr = "MACH_MSG_TYPE_BOOLEAN"; + it->itOutName = MACH_MSG_TYPE_BOOLEAN; + it->itOutNameStr = "MACH_MSG_TYPE_BOOLEAN"; + it->itSize = machine_integer_bits; + + itCalculateSizeInfo(it); + itCalculateNameInfo(it); + return it; +} + +extern ipc_type_t * +itNativeType(identifier_t id, boolean_t ptr, identifier_t badval) +{ + ipc_type_t *it = itAlloc(); + + it->itInName = MACH_MSG_TYPE_BYTE; + it->itInNameStr = "MACH_MSG_TYPE_BYTE"; + it->itOutName = MACH_MSG_TYPE_BYTE; + it->itOutNameStr = "MACH_MSG_TYPE_BYTE"; + it->itInLine = TRUE; + it->itNative = TRUE; + it->itNativePointer = ptr; + it->itServerType = id; + it->itUserType = id; + it->itTransType = id; + it->itBadValue = badval; + + itCalculateSizeInfo(it); + itCalculateNameInfo(it); + return it; +} + +/* + * Initializes the pre-defined types. + */ +void +init_type(void) +{ + u_int size; + + size = NBBY * sizeof (natural_t); + if (size == 32) { + machine_integer_name = "MACH_MSG_TYPE_INTEGER_32"; + machine_integer_size = MACH_MSG_TYPE_INTEGER_32; + } + else if (size == 64) { + machine_integer_name = "MACH_MSG_TYPE_INTEGER_64"; + machine_integer_size = MACH_MSG_TYPE_INTEGER_64; + } + else + error("init_type unknown size %d", size); + + machine_integer_bits = size; + + itRetCodeType = itAlloc(); + itRetCodeType->itName = "kern_return_t"; + itRetCodeType->itInName = machine_integer_size; + itRetCodeType->itInNameStr = machine_integer_name; + itRetCodeType->itOutName = machine_integer_size; + itRetCodeType->itOutNameStr = machine_integer_name; + itRetCodeType->itSize = machine_integer_bits; + itCalculateSizeInfo(itRetCodeType); + itCalculateNameInfo(itRetCodeType); + + itNdrCodeType = itAlloc(); + itNdrCodeType->itName = "NDR_record_t"; + itNdrCodeType->itInName = 0; + itNdrCodeType->itInNameStr = "NDR_record_t"; + itNdrCodeType->itOutName = 0; + itNdrCodeType->itOutNameStr = "NDR_record_t"; + itNdrCodeType->itSize = sizeof(NDR_record_t) * 8; + itCalculateSizeInfo(itNdrCodeType); + itCalculateNameInfo(itNdrCodeType); + + itDummyType = itAlloc(); + itDummyType->itName = "char *"; + itDummyType->itInName = MACH_MSG_TYPE_UNSTRUCTURED; + itDummyType->itInNameStr = "MACH_MSG_TYPE_UNSTRUCTURED"; + itDummyType->itOutName = MACH_MSG_TYPE_UNSTRUCTURED; + itDummyType->itOutNameStr = "MACH_MSG_TYPE_UNSTRUCTURED"; + itDummyType->itSize = PortSize; + itCalculateSizeInfo(itDummyType); + itCalculateNameInfo(itDummyType); + + itTidType = itAlloc(); + itTidType->itName = "tid_t"; + itTidType->itInName = machine_integer_size; + itTidType->itInNameStr = machine_integer_name; + itTidType->itOutName = machine_integer_size; + itTidType->itOutNameStr = machine_integer_name; + itTidType->itSize = machine_integer_bits; + itTidType->itNumber = 6; + itCalculateSizeInfo(itTidType); + itCalculateNameInfo(itTidType); + + itRequestPortType = itAlloc(); + itRequestPortType->itName = "mach_port_t"; + itRequestPortType->itInName = MACH_MSG_TYPE_COPY_SEND; + itRequestPortType->itInNameStr = "MACH_MSG_TYPE_COPY_SEND"; + itRequestPortType->itOutName = MACH_MSG_TYPE_PORT_SEND; + itRequestPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND"; + itRequestPortType->itSize = PortSize; + itCalculateSizeInfo(itRequestPortType); + itCalculateNameInfo(itRequestPortType); + + itZeroReplyPortType = itAlloc(); + itZeroReplyPortType->itName = "mach_port_t"; + itZeroReplyPortType->itInName = 0; + itZeroReplyPortType->itInNameStr = "0"; + itZeroReplyPortType->itOutName = 0; + itZeroReplyPortType->itOutNameStr = "0"; + itZeroReplyPortType->itSize = PortSize; + itCalculateSizeInfo(itZeroReplyPortType); + itCalculateNameInfo(itZeroReplyPortType); + + itRealReplyPortType = itAlloc(); + itRealReplyPortType->itName = "mach_port_t"; + itRealReplyPortType->itInName = MACH_MSG_TYPE_MAKE_SEND_ONCE; + itRealReplyPortType->itInNameStr = "MACH_MSG_TYPE_MAKE_SEND_ONCE"; + itRealReplyPortType->itOutName = MACH_MSG_TYPE_PORT_SEND_ONCE; + itRealReplyPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND_ONCE"; + itRealReplyPortType->itSize = PortSize; + itCalculateSizeInfo(itRealReplyPortType); + itCalculateNameInfo(itRealReplyPortType); + + itWaitTimeType = itMakeCountType(); + itMsgOptionType = itMakeCountType(); +} + +/****************************************************** + * Make sure return values of functions are assignable. + ******************************************************/ +void +itCheckReturnType(identifier_t name, ipc_type_t *it) +{ + if (!it->itStruct) + error("type of %s is too complicated", name); + if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) || + (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) + error("type of %s can't be polymorphic", name); +} + + +/****************************************************** + * Called by routine.c to check that request ports are + * simple and correct ports with send rights. + ******************************************************/ +void +itCheckRequestPortType(identifier_t name, ipc_type_t *it) +{ + /* error("Port size = %d %d name = %s\n", PortSize, it->itSize, it->itName); + error("server = %s user = %x\n",it->itServerType, it->itUserType); + */ + if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) && + (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) && + (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC)) || + (it->itNumber != 1) || + (it->itSize != PortSize) || + !it->itInLine || + !it->itStruct || + it->itVarArray) + error("argument %s isn't a proper request port", name); +} + + +/****************************************************** + * Called by routine.c to check that reply ports are + * simple and correct ports with send rights. + ******************************************************/ +void +itCheckReplyPortType(identifier_t name, ipc_type_t *it) +{ + if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) && + (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) && + (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) && + (it->itOutName != 0)) || + (it->itNumber != 1) || + (it->itSize != PortSize) || + !it->itInLine || + !it->itStruct || + it->itVarArray) + error("argument %s isn't a proper reply port", name); +} + + +/****************************************************** + * Used by routine.c to check that WaitTime is a + * simple bit machine_integer_bits integer. + ******************************************************/ +void +itCheckIntType(identifier_t name, ipc_type_t *it) +{ + if ((it->itInName != machine_integer_size) || + (it->itOutName != machine_integer_size) || + (it->itNumber != 1) || + (it->itSize != machine_integer_bits) || + !it->itInLine || + !it->itStruct || + it->itVarArray) + error("argument %s isn't a proper integer", name); +} + +void +itCheckTokenType(identifier_t name, ipc_type_t *it) +{ + if (it->itMigInLine || it->itNoOptArray || it->itString || + it->itTypeSize != 8 || !it->itInLine || !it->itStruct || + it->itVarArray || it->itPortType) + error("argument %s isn't a proper Token", name); + +} diff --git a/bootstrap_cmds/migcom.tproj/type.h b/bootstrap_cmds/migcom.tproj/type.h new file mode 100644 index 0000000..b1b514b --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/type.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* HISTORY + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University + * Changed itVarArrayDecl to take a 'max' parameter. + * Added itDestructor. + * + * 18-Aug-87 Mary Thompson @ Carnegie Mellon + * Added itPortType + * Added itTidType + */ + +#ifndef _TYPE_H +#define _TYPE_H + +#include +#include "strdefs.h" + +#ifdef linux +#include +#else /* linux */ +#include +#endif /* linux */ +typedef u_int ipc_flags_t; + +/* + * MIG built-in types + */ +#define MACH_MSG_TYPE_UNSTRUCTURED 0 +#define MACH_MSG_TYPE_BIT 0 +#define MACH_MSG_TYPE_BOOLEAN 0 +#define MACH_MSG_TYPE_INTEGER_8 9 +#define MACH_MSG_TYPE_INTEGER_16 1 +#define MACH_MSG_TYPE_INTEGER_32 2 +#define MACH_MSG_TYPE_INTEGER_64 3 +#define MACH_MSG_TYPE_CHAR 8 +#define MACH_MSG_TYPE_BYTE 9 +#define MACH_MSG_TYPE_REAL_32 10 +#define MACH_MSG_TYPE_REAL_64 11 +#define MACH_MSG_TYPE_STRING 12 +#define MACH_MSG_TYPE_STRING_C 12 + +#define flNone (0x00) +#define flPhysicalCopy (0x01) /* Physical Copy specified */ +#define flOverwrite (0x02) /* Overwrite mode specified */ +#define flDealloc (0x04) /* Dealloc specified */ +#define flNotDealloc (0x08) /* NotDealloc specified */ +#define flMaybeDealloc (0x10) /* Dealloc[] specified */ +#define flSameCount (0x20) /* SamCount specified, used by co-bounded arrays */ +#define flCountInOut (0x40) /* CountInOut specified */ +#define flRetCode (0x80) /* RetCode specified */ +#define flAuto (0x100) /* Will not be referenced by server after RPC */ +#define flConst (0x200) /* Will not be modified by server during RPC */ + +typedef enum dealloc { + d_NO, /* do not deallocate */ + d_YES, /* always deallocate */ + d_MAYBE /* deallocate according to parameter */ +} dealloc_t; + +/* Convert dealloc_t to TRUE/FALSE */ +#define strdealloc(d) (strbool(d == d_YES)) + +/* + * itName and itNext are internal fields (not used for code generation). + * They are only meaningful for types entered into the symbol table. + * The symbol table is a simple self-organizing linked list. + * + * The function itCheckDecl checks & fills in computed information. + * Every type actually used (pointed at by argType) is so processed. + * + * The itInName, itOutName, itSize, itNumber, fields correspond directly + * to mach_msg_type_t fields. + * For out-of-line variable sized types, itNumber is zero. For + * in-line variable sized types, itNumber is the maximum size of the + * array. itInName is the name value supplied to the kernel, + * and itOutName is the name value received from the kernel. + * When the type describes a MACH port, either or both may be + * MACH_MSG_TYPE_POLYMORPHIC, indicating a "polymorphic" name. + * For itInName, this means the user supplies the value with an argument. + * For itOutName, this means the value is returned in an argument. + * + * The itInNameStr and itOutNameStr fields contain "printing" versions + * of the itInName and itOutName values. The mapping from number->string + * is not into (eg, MACH_MSG_TYPE_UNSTRUCTURED/MACH_MSG_TYPE_BOOLEAN/ + * MACH_MSG_TYPE_BIT). These fields are used for code-generation and + * pretty-printing. + * + * itTypeSize is the calculated size of the C type, in bytes. + * itPadSize is the size of any padded needed after the data field. + * itMinTypeSize is the minimum size of the data field, including padding. + * For variable-length inline data, it is zero. + * + * itUserType, itServerType, itTransType are the C types used in + * code generation. itUserType is the C type passed to the user-side stub + * and used for msg declarations in the user-side stub. itServerType + * is the C type used for msg declarations in the server-side stub. + * itTransType is the C type passed to the server function by the + * server-side stub. Normally it differs from itServerType only when + * translation functions are defined. + * + * itInTrans and itOutTrans are translation functions. itInTrans + * takes itServerType values and returns itTransType values. itOutTrans + * takes itTransType vaulues and returns itServerType values. + * itDestructor is a finalization function applied to In arguments + * after the server-side stub calls the server function. It takes + * itTransType values. Any combination of these may be defined. + * + * The following type specification syntax modifies these values: + * type new = old + * ctype: name // itUserType and itServerType + * cusertype: itUserType + * cservertype: itServerType + * intran: itTransType itInTrans(itServerType) + * outtran: itServerType itOutTrans(itTransType) + * destructor: itDestructor(itTransType); + * + * At most one of itStruct and itString should be TRUE. If both are + * false, then this is assumed to be an array type (msg data is passed + * by reference). If itStruct is TRUE, then msg data is passed by value + * and can be assigned with =. If itString is TRUE, then the msg_data + * is a null-terminated string, assigned with strncpy. The itNumber + * value is a maximum length for the string; the msg field always + * takes up this much space. + * NoOptArray has been introduced for the cases where the special + * code generated for array assignments would not work (either because + * there is not a ctype (array of automagically generated MiG variables) + * or because we need to reference the single elements of the array + * (array of variable sized ool regions). + * + * itVarArray means this is a variable-sized array. If it is inline, + * then itStruct and itString are FALSE. If it is out-of-line, then + * itStruct is TRUE (because pointers can be assigned). + * + * itMigInLine means this is an indefinite-length array. Although the + * argument was not specified as out-of-line, MIG will send it anyway + * os an out-of-line. + * + * itUserKPDType (itServerKPDType) identify the type of Kernel Processed + * Data that we must deal with: it can be either "mach_msg_port_descriptor_t" + * or "mach_msg_ool_ports_descriptor_t" or "mach_msg_ool_descriptor_t". + * + * itKPD_Number is used any time a single argument require more than + * one Kernel Processed Data entry: i.e., an in-line array of ports, an array + * of pointers (out-of-line data) + * + * itElement points to any substructure that the type may have. + * It is only used with variable-sized array types. + */ + +typedef struct ipc_type + { + identifier_t itName; /* Mig's name for this type */ + struct ipc_type *itNext; /* next type in symbol table */ + + u_int itTypeSize; /* size of the C type */ + u_int itPadSize; /* amount of padding after data */ + u_int itMinTypeSize; /* minimal amount of space occupied by data */ + + u_int itInName; /* name supplied to kernel in sent msg */ + u_int itOutName; /* name in received msg */ + u_int itSize; + u_int itNumber; + u_int itKPD_Number; /* number of Kernel Processed Data entries */ + boolean_t itInLine; + boolean_t itMigInLine; /* MiG presents data as InLine, although it is sent OOL */ + boolean_t itPortType; + + string_t itInNameStr; /* string form of itInName */ + string_t itOutNameStr; /* string form of itOutName */ + + boolean_t itStruct; + boolean_t itString; + boolean_t itVarArray; + boolean_t itNoOptArray; + boolean_t itNative; /* User specified a native (C) type. */ + boolean_t itNativePointer;/* The user will pass a pointer to the */ + /* native C type. */ + + struct ipc_type *itElement; /* may be NULL */ + + identifier_t itUserType; + identifier_t itServerType; + identifier_t itTransType; + + identifier_t itKPDType; /* descriptors for KPD type of arguments */ + + identifier_t itInTrans; /* may be NULL */ + identifier_t itOutTrans; /* may be NULL */ + identifier_t itDestructor;/* may be NULL */ + identifier_t itBadValue; /* Excluded value for PointerToIfNot. May + be NULL. */ + u_int itOOL_Number; + } ipc_type_t; + +enum { + ConsumeOnSendErrorNone, + ConsumeOnSendErrorTimeout, + ConsumeOnSendErrorAny, +}; + + +#define itNULL ((ipc_type_t *) 0) + +#define itWordAlign sizeof(natural_t) + +extern ipc_type_t *itLookUp(identifier_t name); +extern void itInsert(identifier_t name, ipc_type_t *it); +extern void itTypeDecl(identifier_t name, ipc_type_t *it); + +extern ipc_type_t *itShortDecl(u_int inname, string_t instr, + u_int outname, string_t outstr, + u_int dfault); +extern ipc_type_t *itPrevDecl(identifier_t name); +extern ipc_type_t *itResetType(ipc_type_t *it); +extern ipc_type_t *itVarArrayDecl(u_int number, ipc_type_t *it); +extern ipc_type_t *itArrayDecl(u_int number, ipc_type_t *it); +extern ipc_type_t *itPtrDecl(ipc_type_t *it); +extern ipc_type_t *itStructDecl(u_int number, ipc_type_t *it); +extern ipc_type_t *itCStringDecl(int count, boolean_t varying); +extern ipc_type_t *itNativeType(identifier_t CType, boolean_t pointer, + identifier_t NotVal); + +extern ipc_type_t *itRetCodeType; +extern ipc_type_t *itNdrCodeType; +extern ipc_type_t *itDummyType; +extern ipc_type_t *itTidType; +extern ipc_type_t *itRequestPortType; +extern ipc_type_t *itZeroReplyPortType; +extern ipc_type_t *itRealReplyPortType; +extern ipc_type_t *itWaitTimeType; +extern ipc_type_t *itMsgOptionType; +extern ipc_type_t *itMakeCountType(void); +extern ipc_type_t *itMakeSubCountType(int count, boolean_t varying, string_t name); +extern ipc_type_t *itMakePolyType(void); +extern ipc_type_t *itMakeDeallocType(void); + +extern void init_type(void); + +extern void itCheckReturnType(identifier_t name, ipc_type_t *it); +extern void itCheckRequestPortType(identifier_t name, ipc_type_t *it); +extern void itCheckReplyPortType(identifier_t name, ipc_type_t *it); +extern void itCheckIntType(identifier_t name, ipc_type_t *it); +extern void itCheckTokenType(identifier_t name, ipc_type_t *it); + +#endif /* _TYPE_H */ diff --git a/bootstrap_cmds/migcom.tproj/user.c b/bootstrap_cmds/migcom.tproj/user.c new file mode 100644 index 0000000..839732d --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/user.c @@ -0,0 +1,3260 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include + +#include +#include "write.h" +#include "error.h" +#include "utils.h" +#include "global.h" + +#ifndef DISABLE_SPECIAL_REPLY_PORT_IN_CHROOT +#define DISABLE_SPECIAL_REPLY_PORT_IN_CHROOT 1 +#endif + +#ifndef DISABLE_SPECIAL_REPLY_PORT_IN_SIMULATOR +#define DISABLE_SPECIAL_REPLY_PORT_IN_SIMULATOR 1 +#endif + +#ifndef USE_IMMEDIATE_SEND_TIMEOUT +#define USE_IMMEDIATE_SEND_TIMEOUT 0 +#endif + +char *MessAllocRoutine = "mig_user_allocate"; +char *MessFreeRoutine = "mig_user_deallocate"; + +char stRetCode[] = "ReturnValue"; +char stRetNone[] = ""; + +void WriteLogDefines(FILE *file, string_t who); +void WriteIdentificationString(FILE *file); + +static void +WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t overwrite, boolean_t varying, argument_t *arg, boolean_t bracket) +{ + ipc_type_t *it = arg->argType; + char string[MAX_STR_LEN]; + + fprintf(file, "\t{\n"); + fprintf(file, "\t %s\t*ptr;\n", it->itKPDType); + fprintf(file, "\t int\ti"); + if (varying && !in) + fprintf(file, ", j"); + fprintf(file, ";\n\n"); + + if (in) + sprintf(string, "InP"); + else if (overwrite) + sprintf(string, "InOvTemplate"); + else + sprintf(string, "Out%dP", arg->argRequestPos); + + fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField); + + if (varying) { + argument_t *count = arg->argCount; + char *cref = count->argByReferenceUser ? "*" : ""; + + if (in || overwrite) { + fprintf(file, "\t if (%s%s > %d)\n", cref, count->argVarName, it->itKPD_Number); + WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE"); + fprintf(file, "\t for (i = 0; i < %s%s; ptr++, i++) %s\n", cref, count->argVarName, (bracket) ? "{" : ""); + } + else { + fprintf(file, "\t j = min(Out%dP->%s, %s%s);\n", count->argReplyPos, count->argVarName, cref, count->argVarName); + fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n",(bracket) ? "{" : ""); +} + } + else + fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number, (bracket) ? "{" : ""); +} + +/************************************************************* + * Writes the standard includes. The subsystem specific + * includes are in .h and writen by + * header:WriteHeader. Called by WriteProlog. + *************************************************************/ +static void +WriteMyIncludes(FILE *file, statement_t *stats) +{ +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelServer) + { + /* + * We want to get the user-side definitions of types + * like task_t, ipc_space_t, etc. in mach/mach_types.h. + */ + + fprintf(file, "#undef\tMACH_KERNEL\n"); + + if (InternalHeaderFileName != strNULL) + { + char *cp; + + /* Strip any leading path from InternalHeaderFileName. */ + cp = strrchr(InternalHeaderFileName, '/'); + if (cp == 0) + cp = InternalHeaderFileName; + else + cp++; /* skip '/' */ + fprintf(file, "#include \"%s\"\n", cp); + } + } +#endif + + if (UserHeaderFileName == strNULL || UseSplitHeaders) + WriteIncludes(file, TRUE, FALSE); + if (UserHeaderFileName != strNULL) + { + char *cp; + + /* Strip any leading path from UserHeaderFileName. */ + cp = strrchr(UserHeaderFileName, '/'); + if (cp == 0) + cp = UserHeaderFileName; + else + cp++; /* skip '/' */ + fprintf(file, "#include \"%s\"\n", cp); + } + if (UseSplitHeaders) + WriteImplImports(file, stats, TRUE); + + if (UseEventLogger) { + if (IsKernelUser) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "#include \n"); + fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n"); + } + fprintf(file, "#if MIG_DEBUG\n"); + fprintf(file, "#include \n"); + fprintf(file, "#endif /* MIG_DEBUG */\n"); + } + if (HasConsumeOnSendError && !IsKernelUser) { + fprintf(file, "#include \n"); + } + if (BeLint) { + fprintf(file, "/* LINTLIBRARY */\n"); + } + fprintf(file, "\n"); + if (!BeAnsiC) { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "#else\t/* %s */\n", NewCDecl); + fprintf(file, "extern mach_port_t mig_get_reply_port();\n"); + fprintf(file, "extern void mig_dealloc_reply_port();\n"); + fprintf(file, "extern char *%s();\n", MessAllocRoutine); + fprintf(file, "extern void %s();\n", MessFreeRoutine); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + if (HasUseSpecialReplyPort) { + fprintf(file, "\n"); + fprintf(file, "#include \n"); + fprintf(file, "#include \n"); +#if DISABLE_SPECIAL_REPLY_PORT_IN_SIMULATOR + fprintf(file, "#ifndef __MigCanUseSpecialReplyPort\n"); + fprintf(file, "#if TARGET_OS_SIMULATOR\n"); + fprintf(file, "#define __MigCanUseSpecialReplyPort 0\n"); + fprintf(file, "#define mig_get_special_reply_port() MACH_PORT_DEAD\n"); + fprintf(file, "#define mig_dealloc_special_reply_port(port) __builtin_trap()\n"); + fprintf(file, "#endif\n"); + fprintf(file, "#endif /* __MigCanUseSpecialReplyPort */\n"); +#endif +#if DISABLE_SPECIAL_REPLY_PORT_IN_CHROOT + fprintf(file, "#ifndef __MigCanUseSpecialReplyPort\n"); + fprintf(file, "#if TARGET_OS_OSX\n"); + fprintf(file, "extern _Bool _os_xbs_chrooted;\n"); + fprintf(file, "#define __MigCanUseSpecialReplyPort (!_os_xbs_chrooted)\n"); + fprintf(file, "#endif\n"); + fprintf(file, "#endif /* __MigCanUseSpecialReplyPort */\n"); +#endif + fprintf(file, "#ifndef __MigCanUseSpecialReplyPort\n"); + fprintf(file, "#define __MigCanUseSpecialReplyPort 1\n"); + fprintf(file, "#endif /* __MigCanUseSpecialReplyPort */\n"); + fprintf(file, "#ifndef __MigSpecialReplyPortMsgOption\n"); + fprintf(file, "#define __MigSpecialReplyPortMsgOption (__MigCanUseSpecialReplyPort ? " + "(MACH_SEND_SYNC_OVERRIDE|MACH_SEND_SYNC_USE_THRPRI|MACH_RCV_SYNC_WAIT) : MACH_MSG_OPTION_NONE)\n"); + fprintf(file, "#endif /* __MigSpecialReplyPortMsgOption */\n"); + } + /* + * extern the definition of mach_msg_destroy + * (to avoid inserting mach/mach.h everywhere) + */ + fprintf(file, "/* TODO: #include */\n"); + fprintf(file, "#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n"); + fprintf(file, "extern void mach_msg_destroy(mach_msg_header_t *);\n"); + fprintf(file, "#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n"); + + fprintf(file, "\n"); +} + +static void +WriteGlobalDecls(FILE *file) +{ + if (RCSId != strNULL) + WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId); + + fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n"); + fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n"); + fprintf(file, "\n"); + if (UseEventLogger) + WriteLogDefines(file, "MACH_MSG_LOG_USER"); + fprintf(file, "\n"); +} + +static void +WriteOneMachErrorDefine(FILE *file, char *name, boolean_t timeout, boolean_t SpecialReplyPort) +{ + fprintf(file, "#ifndef\t%s\n", name); + fprintf(file, "#define\t%s(_R_) { \\\n", name); + fprintf(file, "\tswitch (_R_) { \\\n"); + fprintf(file, "\tcase MACH_SEND_INVALID_DATA: \\\n"); + fprintf(file, "\tcase MACH_SEND_INVALID_DEST: \\\n"); + fprintf(file, "\tcase MACH_SEND_INVALID_HEADER: \\\n"); + if (SpecialReplyPort) { + fprintf(file, "\t\tif (!__MigCanUseSpecialReplyPort) { \\\n"); + fprintf(file, "\t\t\tmig_put_reply_port(InP->Head.msgh_reply_port); \\\n"); + fprintf(file, "\t\t} \\\n"); + } else { + fprintf(file, "\t\tmig_put_reply_port(InP->Head.msgh_reply_port); \\\n"); + } + fprintf(file, "\t\tbreak; \\\n"); + if (timeout) { + fprintf(file, "\tcase MACH_SEND_TIMED_OUT: \\\n"); + fprintf(file, "\tcase MACH_RCV_TIMED_OUT: \\\n"); + } + fprintf(file, "\tdefault: \\\n"); + if (SpecialReplyPort) { + fprintf(file, "\t\tif (__MigCanUseSpecialReplyPort) { \\\n"); + fprintf(file, "\t\t\tmig_dealloc_special_reply_port(InP->Head.msgh_reply_port); \\\n"); + fprintf(file, "\t\t} else { \\\n"); + fprintf(file, "\t\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n"); + fprintf(file, "\t\t} \\\n"); + } else { + fprintf(file, "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n"); + } + fprintf(file, "\t} \\\n}\n"); + fprintf(file, "#endif\t/* %s */\n", name); + fprintf(file, "\n"); +} + +static void +WriteMachErrorDefines(FILE *file) +{ + WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeout", TRUE, FALSE); + WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeout", FALSE, FALSE); + if (HasUseSpecialReplyPort) { + WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeoutSRP", TRUE, TRUE); + WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeoutSRP", FALSE, TRUE); + } +} + +static void +WriteMIGCheckDefines(FILE *file) +{ + fprintf(file, "#define\t__MIG_check__Reply__%s_subsystem__ 1\n", SubsystemName); + fprintf(file, "\n"); +} + +static void +WriteNDRDefines(FILE *file) +{ + fprintf(file, "#define\t__NDR_convert__Reply__%s_subsystem__ 1\n", SubsystemName); + fprintf(file, "#define\t__NDR_convert__mig_reply_error_subsystem__ 1\n"); + fprintf(file, "\n"); +} + +/************************************************************* + * Writes the standard #includes, #defines, and + * RCS declaration. Called by WriteUser. + *************************************************************/ +static void +WriteProlog(FILE *file, statement_t *stats) +{ + WriteIdentificationString(file); + WriteMIGCheckDefines(file); + if (CheckNDR) + WriteNDRDefines(file); + WriteMyIncludes(file, stats); + WriteBogusDefines(file); + WriteMachErrorDefines(file); + WriteApplDefaults(file, "Send"); + WriteGlobalDecls(file); +} + +/*ARGSUSED*/ +static void +WriteEpilog(FILE *file) +{ + /* nothing to see here, move along... */ +} + +static string_t +WriteHeaderPortType(argument_t *arg) +{ + if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC) + return arg->argPoly->argVarName; + else + return arg->argType->itInNameStr; +} + +static void +WriteRequestHead(FILE *file, routine_t *rt) +{ + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) + fprintf(file, "ready_to_send:\n"); + + if (rt->rtMaxRequestPos > 0) { + if (rt->rtOverwrite) + fprintf(file, "\tInP = &MessRequest;\n"); + else + fprintf(file, "\tInP = &Mess%sIn;\n", (rtMessOnStack(rt) ? "." : "->")); + } + + fprintf(file, "\tInP->Head.msgh_bits ="); + if (rt->rtRetCArg == argNULL && !rt->rtSimpleRequest) + fprintf(file, " MACH_MSGH_BITS_COMPLEX|"); + fprintf(file, "\n"); + fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n", WriteHeaderPortType(rt->rtRequestPort), WriteHeaderPortType(rt->rtReplyPort)); + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + fprintf(file, "\tif (!%s)\n", rt->rtRetCArg->argVarName); + fprintf(file, "\t\tInP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n"); + } + + + fprintf(file, "\t/* msgh_size passed as argument */\n"); + + /* + * KernelUser stubs need to cast the request and reply ports + * from ipc_port_t to mach_port_t. + */ + +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelUser) + fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", rt->rtRequestPort->argMsgField, rt->rtRequestPort->argVarName); + else +#endif + fprintf(file, "\tInP->%s = %s;\n", rt->rtRequestPort->argMsgField, rt->rtRequestPort->argVarName); + + if (akCheck(rt->rtReplyPort->argKind, akbUserArg)) { +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelUser) + fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName); + else +#endif + fprintf(file, "\tInP->%s = %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName); + } + else if (rt->rtOneWay) + fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n", rt->rtReplyPort->argMsgField); + else if (rt->rtUseSpecialReplyPort) + fprintf(file, "\tInP->%s = __MigCanUseSpecialReplyPort ? mig_get_special_reply_port() : mig_get_reply_port();\n", rt->rtReplyPort->argMsgField); + else + fprintf(file, "\tInP->%s = mig_get_reply_port();\n", rt->rtReplyPort->argMsgField); + + fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase); + fprintf(file, "\tInP->Head.msgh_reserved = 0;\n"); + + + if (IsVoucherCodeAllowed && !IsKernelUser && !IsKernelServer) { + fprintf(file, "\t\n/* BEGIN VOUCHER CODE */\n\n"); + fprintf(file, "#ifdef USING_VOUCHERS\n"); + fprintf(file, "\tif (voucher_mach_msg_set != NULL) {\n"); + fprintf(file, "\t\tvoucher_mach_msg_set(&InP->Head);\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif // USING_VOUCHERS\n"); + fprintf(file, "\t\n/* END VOUCHER CODE */\n"); + } +} + +/************************************************************* + * Writes declarations for the message types, variables + * and return variable if needed. Called by WriteRoutine. + *************************************************************/ +static void +WriteVarDecls(FILE *file, routine_t *rt) +{ + int i; + + if (rt->rtOverwrite) { + fprintf(file, "\tRequest MessRequest;\n"); + fprintf(file, "\tRequest *InP = &MessRequest;\n\n"); + + fprintf(file, "\tunion {\n"); + fprintf(file, "\t\tOverwriteTemplate In;\n"); + fprintf(file, "\t\tReply Out;\n"); + fprintf(file, "\t} MessReply;\n"); + + fprintf(file, "\tOverwriteTemplate *InOvTemplate = &MessReply.In;\n"); + fprintf(file, "\tReply *Out0P = &MessReply.Out;\n"); + for (i = 1; i <= rt->rtMaxReplyPos; i++) + fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i); + } + else { + if (rtMessOnStack(rt)) + fprintf(file, "\tunion {\n"); + else + fprintf(file, "\tunion %sMessU {\n", rt->rtName); + fprintf(file, "\t\tRequest In;\n"); + if (!rt->rtOneWay) + fprintf(file, "\t\tReply Out;\n"); + if (rtMessOnStack(rt)) + fprintf(file, "\t} Mess;\n"); + else + fprintf(file, "\t} *Mess = (union %sMessU *) %s(sizeof(*Mess));\n", + rt->rtName, MessAllocRoutine); + fprintf(file, "\n"); + + fprintf(file, "\tRequest *InP = &Mess%sIn;\n", (rtMessOnStack(rt) ? "." : "->")); + if (!rt->rtOneWay) { + fprintf(file, "\tReply *Out0P = &Mess%sOut;\n", (rtMessOnStack(rt) ? "." : "->")); + for (i = 1; i <= rt->rtMaxReplyPos; i++) + fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i); + } + } + + fprintf(file, "\n"); + + fprintf(file, "\tmach_msg_return_t msg_result;\n"); + + /* if request is variable, we need msgh_size_delta and msgh_size */ + if (rt->rtNumRequestVar > 0) + fprintf(file, "\tunsigned int msgh_size;\n"); + if (rt->rtMaxRequestPos > 0) + fprintf(file, "\tunsigned int msgh_size_delta;\n"); + if (rt->rtNumRequestVar > 1 || rt->rtMaxRequestPos > 0) + fprintf(file, "\n"); + + if (rt->rtUserImpl) { + fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n"); + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tunsigned int trailer_size __attribute__((unused));\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + fprintf(file, "\n"); + fprintf(file, "#ifdef\t__MIG_check__Reply__%s_t__defined\n", rt->rtName); + fprintf(file, "\tkern_return_t check_result;\n"); + fprintf(file, "#endif\t/* __MIG_check__Reply__%s_t__defined */\n", rt->rtName); + fprintf(file, "\n"); + WriteApplMacro(file, "Send", "Declare", rt); + fprintf(file, "\n"); +} + +static void +WriteReturn(FILE *file, routine_t *rt, char *before, char *value, char *after, boolean_t deallocate_mess) +{ + if (rtMessOnStack(rt)) { + if (value != stRetCode) { + /* get the easy case (no braces needed) out of the way */ + fprintf(file, "%sreturn%s%s;%s", before, (*value ? " " : ""), value, after); + return; + } + else { + fprintf(file, "%s{\n", before); + fprintf(file, "%s\treturn Out0P->RetCode;\n%s}%s", before, before, after); + return; + } + } + + if (value == stRetCode) { + fprintf(file, "%s{\n%s\t%s ReturnValue;\n", before, before, ReturnTypeStr(rt)); + fprintf(file, "%s\tReturnValue = Out0P->RetCode;\n%s\t", before, before); + } + else { + fprintf(file, "%s{ ", before); + } + + if (deallocate_mess) { + fprintf(file, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine); + } + + if (value == stRetCode) + fprintf(file, "return ReturnValue;\n%s}%s", before, after); + else if (value == stRetNone) + fprintf(file, "return; }%s", after); + else + fprintf(file, "return %s; }%s", value, after); +} + +static void +WriteRetCodeArg(FILE *file, routine_t *rt) +{ + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + argument_t *arg = rt->rtRetCArg; + + fprintf(file, "\tif (%s) {\n", arg->argVarName); + fprintf(file, "\t\t((mig_reply_error_t *)InP)->RetCode = %s;\n", arg->argVarName); + fprintf(file, "\t\t((mig_reply_error_t *)InP)->NDR = NDR_record;\n"); + fprintf(file, "\t\tgoto ready_to_send;\n"); + fprintf(file, "\t}\n\n"); + } +} + +/************************************************************* + * Writes the logic to check for a message send timeout, and + * deallocate any relocated ool data so as not to leak. + *************************************************************/ +static void +WriteMsgCheckForSendErrors(FILE *file, routine_t *rt) +{ + if (rt->rtConsumeOnSendError != ConsumeOnSendErrorAny && rt->rtWaitTime == argNULL) { + return; + } + + if (rt->rtConsumeOnSendError == ConsumeOnSendErrorAny) { + // other errors mean the kernel consumed some of the rights + // and we can't possibly know if there's something left to destroy + fputs("\n" + "\t" "if (msg_result == MACH_SEND_INVALID_DEST ||" "\n" + "\t\t" "msg_result == MACH_SEND_TIMED_OUT) {" "\n", file); + } else { + fputs("\n" + "\t" "if (msg_result == MACH_SEND_TIMED_OUT) {" "\n", file); + } + + if (rt->rtConsumeOnSendError == ConsumeOnSendErrorNone) { + argument_t *arg_ptr; + + // iterate over arg list + for (arg_ptr = rt->rtArgs; arg_ptr != NULL; arg_ptr = arg_ptr->argNext) { + + // if argument contains ool data + if (akCheck(arg_ptr->argKind, akbSendKPD) && arg_ptr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + // generate code to test current arg address vs. address before the msg_send call + // if not at the same address, mig_deallocate the argument + fprintf(file, "\t\t" "if((vm_offset_t) InP->%s.address != (vm_offset_t) %s)\n", + arg_ptr->argVarName, arg_ptr->argVarName); + fprintf(file, "\t\t\t" "mig_deallocate((vm_offset_t) InP->%s.address, " + "(vm_size_t) InP->%s.size);\n", arg_ptr->argVarName, arg_ptr->argVarName); + } + } + } else { + /* + * The original MIG would leak most resources on send timeout without + * leaving a chance for callers to know how to dispose of most of the + * resources, as the caller can't possibly guess the new names + * picked during pseudo-receive. + */ + if (IsKernelUser) { + fputs("#if\t__MigKernelSpecificCode" "\n", file); + fputs("\t\t" "mach_msg_destroy_from_kernel(&InP->Head);" "\n", file); + fputs("#endif\t/* __MigKernelSpecificCode */" "\n", file); + } else { + fputs("\t\t" "/* mach_msg_destroy doesn't handle the local port */" "\n", file); + fputs("\t\t" "switch (MACH_MSGH_BITS_LOCAL(InP->Head.msgh_bits)) {" "\n", file); + fputs("\t\t" "case MACH_MSG_TYPE_MOVE_SEND:" "\n", file); + fputs("\t\t\t" "mach_port_deallocate(mach_task_self(), InP->Head.msgh_local_port);" "\n", file); + fputs("\t\t\t" "break;" "\n", file); + fputs("\t\t" "}" "\n", file); + fputs("\t\t" "mach_msg_destroy(&InP->Head);" "\n", file); + } + } + + fputs("\t" "}" "\n\n", file); + return; +} + +/************************************************************* + * Writes the send call when there is to be no subsequent + * receive. Called by WriteRoutine SimpleRoutines + *************************************************************/ +static void +WriteMsgSend(FILE *file, routine_t *rt) +{ + char *SendSize = ""; + char string[MAX_STR_LEN]; + + if (rt->rtNumRequestVar == 0) + SendSize = "(mach_msg_size_t)sizeof(Request)"; + else + SendSize = "msgh_size"; + + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName); + SendSize = strconcat(string, SendSize); + } + + if (IsKernelUser) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "\tmsg_result = mach_msg_send_from_kernel("); + fprintf(file, "&InP->Head, %s);\n", SendSize); + fprintf(file, "#else\n"); + } + fprintf(file, "\tmsg_result = mach_msg(" + "&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, MACH_PORT_NULL, %s, MACH_PORT_NULL);\n", + rt->rtWaitTime !=argNULL ? "MACH_SEND_TIMEOUT|" : "", + rt->rtMsgOption->argVarName, + SendSize, + rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName:"MACH_MSG_TIMEOUT_NONE"); + + if (IsKernelUser) { + fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); + } + + WriteApplMacro(file, "Send", "After", rt); + + WriteMsgCheckForSendErrors(file, rt); + + WriteReturn(file, rt, "\t", "msg_result", "\n", TRUE); +} + +/************************************************************* + * Writes to code to check for error returns from receive. + * Called by WriteMsgSendReceive and WriteMsgRPC + *************************************************************/ +static void +WriteMsgCheckReceiveCleanupMigReplyPort(FILE *file, routine_t *rt, char *success) +{ + if (!akCheck(rt->rtReplyPort->argKind, akbUserArg)) + { + /* If we aren't using a user-supplied reply port, then + deallocate the reply port when it is invalid or + for TIMED_OUT errors. */ + fprintf(file, "\tif (msg_result != %s) {\n", success); + if (rt->rtWaitTime != argNULL) { + fprintf(file, "\t\t__MachMsgErrorWithTimeout%s(msg_result);\n", + rt->rtUseSpecialReplyPort ? "SRP" : ""); + } else { + fprintf(file, "\t\t__MachMsgErrorWithoutTimeout%s(msg_result);\n", + rt->rtUseSpecialReplyPort ? "SRP" : ""); + } + fprintf(file, "\t}\n"); + } +} + +static void +WriteMsgCheckReceive(FILE *file, routine_t *rt, char *success) +{ + fprintf(file, "\tif (msg_result != %s) {\n", success); + WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result"); + fprintf(file, "\t}\n"); +} + +/************************************************************* + * Writes the send and receive calls and code to check + * for errors. Normally the rpc code is generated instead + * although, the subsytem can be compiled with the -R option + * which will cause this code to be generated. Called by + * WriteRoutine if UseMsgRPC option is false. + *************************************************************/ +static void +WriteMsgSendReceive(FILE *file, routine_t *rt) +{ + char *SendSize = ""; + char string[MAX_STR_LEN]; + + if (rt->rtNumRequestVar == 0) + SendSize = "(mach_msg_size_t)sizeof(Request)"; + else + SendSize = "msgh_size"; + + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName); + SendSize = strconcat(string, SendSize); + } + + /* IsKernelUser to be done! */ + fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, ", rt->rtWaitTime != argNULL ? "MACH_SEND_TIMEOUT|" : "", rt->rtMsgOption->argVarName, SendSize); + fprintf(file, " MACH_PORT_NULL, %s, MACH_PORT_NULL);\n", +#if !USE_IMMEDIATE_SEND_TIMEOUT + (rt->rtWaitTime != argNULL) ? rt->rtWaitTime->argVarName : +#endif + "MACH_MSG_TIMEOUT_NONE"); + fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n"); + WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result"); + fprintf(file, "\n"); + + fprintf(file, "\tmsg_result = mach_msg(&Out0P->Head, MACH_RCV_MSG|%s%s%s, 0, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n", + rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "", + (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? "MACH_RCV_TIMEOUT|" : "", + rt->rtMsgOption->argVarName, + (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE"); + WriteApplMacro(file, "Send", "After", rt); + WriteMsgCheckReceiveCleanupMigReplyPort(file, rt, "MACH_MSG_SUCCESS"); + WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS"); + fprintf(file, "\n"); +} + +/************************************************************* + * Writes the rpc call and the code to check for errors. + * This is the default code to be generated. Called by WriteRoutine + * for all routine types except SimpleRoutine. + *************************************************************/ +static void +WriteMsgRPC(FILE *file, routine_t *rt) +{ + char *SendSize = ""; + char string[MAX_STR_LEN]; + + if (rt->rtNumRequestVar == 0) + SendSize = "(mach_msg_size_t)sizeof(Request)"; + else + SendSize = "msgh_size"; + + if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { + sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName); + SendSize = strconcat(string, SendSize); + } + + if (IsKernelUser) { + fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNELSPECIFIC_CODE_)\n"); + fprintf(file, "\tmsg_result = mach_msg_rpc_from_kernel(&InP->Head, %s, (mach_msg_size_t)sizeof(Reply));\n", SendSize); + fprintf(file, "#else\n"); + } + if (rt->rtOverwrite) { + fprintf(file, "\tmsg_result = mach_msg_overwrite(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_OVERWRITE|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL, ", + rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "", + rt->rtWaitTime != argNULL ? + (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "", + rt->rtMsgOption->argVarName, + SendSize, + rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE"); + fprintf(file, " &InOvTemplate->Head, (mach_msg_size_t)sizeof(OverwriteTemplate));\n"); + } + else { + fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n", + rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "", + rt->rtWaitTime != argNULL ? + (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "", + rt->rtMsgOption->argVarName, + SendSize, + rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE"); + } + if (IsKernelUser) + fprintf(file,"#endif /* __MigKernelSpecificCode */\n"); + WriteApplMacro(file, "Send", "After", rt); + + WriteMsgCheckReceiveCleanupMigReplyPort(file, rt, "MACH_MSG_SUCCESS"); + WriteMsgCheckForSendErrors(file, rt); + + WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS"); + fprintf(file, "\n"); +} + +/* + * argKPD_Pack discipline for Port types. + */ +static void +WriteKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *subindex = ""; + char *recast = ""; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + char *ref = arg->argByReferenceUser ? "*" : ""; + ipc_type_t *real_it; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + subindex = "[i]"; + real_it = it->itElement; + } + else { + (void)sprintf(firststring, "InP->%s", arg->argMsgField); + (void)sprintf(string, "InP->%s.", arg->argMsgField); + real_it = it; + } + +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t")) + recast = "(mach_port_t)"; +#endif + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + /* ref is required also in the Request part, because of inout parameters */ + fprintf(file, "\t%sname = %s%s%s%s;\n", string, recast, ref, arg->argVarName, subindex); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) { + argument_t *poly = arg->argPoly; + + fprintf(file, "\t%sdisposition = %s%s;\n", string, poly->argByReferenceUser ? "*" : "", poly->argVarName); + } + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + fprintf(file, "\t%sname = %s%s%s%s;\n", string, recast, ref, arg->argVarName, subindex); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) { + argument_t *poly = arg->argPoly; + + fprintf(file, "\t%sdisposition = %s%s;\n", string, poly->argByReferenceUser ? "*" : "", poly->argVarName); + } + else + fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr); + fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + if (IS_MULTIPLE_KPD(it)) { + fprintf(file, "\t }\n"); + if (it->itVarArray) { + fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg->argCount->argVarName, it->itKPD_Number); + /* fill the rest of the statically allocated KPD entries with MACH_PORT_NULL */ + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string); + fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\t }\n"); + } + fprintf(file, "\t}\n"); + } + fprintf(file, "\n"); +} + +static void +WriteKPD_ool_varsize(FILE *file, argument_t *arg, char *who, char *where, boolean_t iscomplex) +{ + ipc_type_t *it = arg->argType; + argument_t *count; + char *cref; + + if (iscomplex) { + it = it->itElement; + count = arg->argSubCount; + } + else + count = arg->argCount; + cref = count->argByReferenceUser ? "*" : ""; + + /* size has to be expressed in bytes! */ + if (count->argMultiplier > 1 || it->itSize > 8) + fprintf(file, "\t%s->%s = %s%s%s * %d;\n", who, where, cref, count->argVarName, (iscomplex)? "[i]" : "", count->argMultiplier * it->itSize / 8); + else + fprintf(file, "\t%s->%s = %s%s%s;\n", who, where, cref, count->argVarName, (iscomplex)? "[i]" : ""); +} + +/* + * argKPD_Pack discipline for out-of-line types. + */ +static void +WriteKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *ref = arg->argByReferenceUser ? "*" : ""; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + boolean_t VarArray; + u_int howmany, howbig; + char *subindex; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + howmany = it->itElement->itNumber; + howbig = it->itElement->itSize; + subindex = "[i]"; + } + else { + (void)sprintf(firststring, "InP->%s", arg->argMsgField); + (void)sprintf(string, "InP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + howmany = it->itNumber; + howbig = it->itSize; + subindex = ""; + } + + fprintf(file, "#if\tUseStaticTemplates\n"); + + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string, ref, arg->argVarName, subindex); + if (VarArray) { + if (IS_MULTIPLE_KPD(it)) + WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE); + else + WriteKPD_ool_varsize(file, arg, "InP", strconcat(arg->argMsgField, ".size"), FALSE); + } + + if (arg->argDeallocate == d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + + fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string, ref, arg->argVarName, subindex); + if (VarArray) + if (IS_MULTIPLE_KPD(it)) + WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE); + else + WriteKPD_ool_varsize(file, arg, "InP", strconcat(arg->argMsgField, ".size"), FALSE); + else + fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8); + if (arg->argDeallocate == d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + else + fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t%scopy = %s;\n", string, (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); +#ifdef ALIGNMENT + fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, (it->itElement->itSize < 8) ? 1 : it->itElement->itSize / 8); +#endif + fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string); + + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + if (IS_MULTIPLE_KPD(it)) { + fprintf(file, "\t }\n"); + if (it->itVarArray) { + fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg->argCount->argVarName, it->itKPD_Number); + /* fill the rest of the statically allocated KPD entries with size NULL */ + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + if (!VarArray) + fprintf(file, "\t%ssize = 0;\n", string); + /* otherwise the size in the template would be != 0! */ + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + fprintf(file, "\t%ssize = 0;\n", string); + fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\t }\n"); + } + fprintf(file, "\t}\n"); + } + fprintf(file, "\n"); +} + +/* + * argKPD_Pack discipline for out-of-line Port types. + */ +static void +WriteKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *ref = arg->argByReferenceUser ? "*" : ""; + argument_t *count; + boolean_t VarArray; + string_t howstr; + u_int howmany; + char *subindex; + char firststring[MAX_STR_LEN]; + char string[MAX_STR_LEN]; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE); + (void)sprintf(firststring, "\t*ptr"); + (void)sprintf(string, "\tptr->"); + VarArray = it->itElement->itVarArray; + howmany = it->itElement->itNumber; + howstr = it->itElement->itInNameStr; + count = arg->argSubCount; + subindex = "[i]"; + } + else { + (void)sprintf(firststring, "InP->%s", arg->argMsgField); + (void)sprintf(string, "InP->%s.", arg->argMsgField); + VarArray = it->itVarArray; + howmany = it->itNumber; + howstr = it->itInNameStr; + count = arg->argCount; + subindex = ""; + } + + fprintf(file, "#if\tUseStaticTemplates\n"); + + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string, ref, arg->argVarName, subindex); + if (VarArray) + fprintf(file, "\t%scount = %s%s%s;\n", string, count->argByReferenceUser ? "*" : "", count->argVarName, subindex); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) { + argument_t *poly = arg->argPoly; + char *pref = poly->argByReferenceUser ? "*" : ""; + + fprintf(file, "\t%sdisposition = %s%s;\n", string, pref, poly->argVarName); + } + if (arg->argDeallocate == d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + + fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string, ref, arg->argVarName, subindex); + if (VarArray) + fprintf(file, "\t%scount = %s%s%s;\n", string, count->argByReferenceUser ? "*" : "", count->argVarName, subindex); + else + fprintf(file, "\t%scount = %d;\n", string, howmany); + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) { + argument_t *poly = arg->argPoly; + char *pref = poly->argByReferenceUser ? "*" : ""; + + fprintf(file, "\t%sdisposition = %s%s;\n", string, pref, poly->argVarName); + } + else + fprintf(file, "\t%sdisposition = %s;\n", string, howstr); + if (arg->argDeallocate == d_MAYBE) + fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); + else + fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string); + + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\n"); + + if (IS_MULTIPLE_KPD(it)) { + fprintf(file, "\t }\n"); + if (it->itVarArray) { + fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg->argCount->argVarName, it->itKPD_Number); + /* fill the rest of the statically allocated KPD entries with size NULL */ + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); + if (!VarArray) + fprintf(file, "\t%scount = 0;\n", string); + /* otherwise the size in the template would be != 0! */ + fprintf(file, "#else\t/* UseStaticTemplates */\n"); + fprintf(file, "\t%scount = 0;\n", string); + fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\t }\n"); + } + fprintf(file, "\t}\n"); + } + fprintf(file, "\n"); +} + +static void +WriteOverwriteTemplate(FILE *file, routine_t *rt) +{ + argument_t *arg; + char string[MAX_STR_LEN]; + char *subindex = ""; + boolean_t finish = FALSE; + + fprintf(file, "\t/* Initialize the template for overwrite */\n"); + fprintf(file, "\tInOvTemplate->msgh_body.msgh_descriptor_count = %d;\n", rt->rtOverwriteKPDs); + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + char *ref = arg->argByReferenceUser ? "*" : ""; + argument_t *count; + char *cref; + boolean_t VarIndex; + u_int howmany, howbig; + + if (akCheck(arg->argKind, akbOverwrite)) { + if (arg->argFlags & flOverwrite) { + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, TRUE, it->itVarArray, arg, TRUE); + if (it->itVarArray) + finish = TRUE; + sprintf(string, "\tptr->"); + subindex = "[i]"; + count = arg->argSubCount; + VarIndex = it->itElement->itVarArray; + howmany = it->itElement->itNumber; + howbig = it->itElement->itSize; + } + else { + sprintf(string, "InOvTemplate->%s.", arg->argMsgField); + subindex = ""; + count = arg->argCount; + VarIndex = it->itVarArray; + howmany = it->itNumber; + howbig = it->itSize; + } + + fprintf(file, "\t%saddress = (void *) %s%s%s;\n", string, ref, arg->argVarName, subindex); + + if (it->itPortType) { + fprintf(file, "\t%scount = ", string); + if (VarIndex) { + cref = count->argByReferenceUser ? "*" : ""; + fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex); + } + else + fprintf(file, "%d;\n", howmany); + } + else { + fprintf(file, "\t%ssize = ", string); + if (VarIndex) { + cref = count->argByReferenceUser ? "*" : ""; + if (count->argMultiplier > 1 || howbig > 8) + fprintf(file, "%s%s%s * %d;\n", cref, count->argVarName, subindex, count->argMultiplier * howbig / 8); + else + fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex); + } + else + fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8); + } + fprintf(file, "\t%scopy = MACH_MSG_OVERWRITE;\n", string); + fprintf(file, "\t%stype = MACH_MSG_OOL_%sDESCRIPTOR;\n", string, (it->itPortType) ? "PORTS_" : ""); + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n"); + if (finish) { + fprintf(file, "\t for (i = %s%s; i < %d; ptr++, i++) {\n", (arg->argCount->argByReferenceUser) ? "*" : "", arg->argCount->argVarName, it->itKPD_Number); + fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n"); + fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n", (it->itPortType) ? "PORTS_" : ""); + fprintf(file, "\t }\n"); + } + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t}\n"); + } + else { + /* just a placeholder */ + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, TRUE, FALSE, arg, TRUE); + fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n"); + fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n", (it->itPortType) ? "PORTS_" : ""); + fprintf(file, "\t }\n\t}\n"); + } + else { + fprintf(file, "\tInOvTemplate->%s.copy = MACH_MSG_ALLOCATE;\n", arg->argMsgField); + /* not sure whether this is needed */ + fprintf(file, "\tInOvTemplate->%s.type = MACH_MSG_OOL_%sDESCRIPTOR;\n", arg->argMsgField, (it->itPortType) ? "PORTS_" : ""); + } + } + } + } + fprintf(file, "\n"); +} + +/************************************************************* + * Writes code to copy an argument into the request message. + * Called by WriteRoutine for each argument that is to placed + * in the request message. + *************************************************************/ + +static void +WritePackArgValueNormal(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *ref = (arg->argByReferenceUser || + it->itNativePointer) ? "*" : ""; + + if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { + if (it->itString) { + /* + * Copy variable-size C string with mig_strncpy. + * Save the string length (+ 1 for trailing 0) + * in the argument`s count field. + */ + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n"); + fprintf(file, "\t\tInP->%s = (%s) mig_strncpy_zerofill(InP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber); + fprintf(file, "\t} else {\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + + fprintf(file, "\t\tInP->%s = (%s) mig_strncpy(InP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber); + + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + + fprintf(file, "\tInP->%sOffset = 0;\n", arg->argMsgField); + } + else if (it->itNoOptArray) + fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, %d);\n", arg->argMsgField, ref, arg->argVarName, it->itTypeSize); + else { + + /* + * Copy in variable-size inline array with (void)memcpy, + * after checking that number of elements doesn`t + * exceed declared maximum. + */ + argument_t *count = arg->argCount; + char *countRef = count->argByReferenceUser ? "*" : ""; + ipc_type_t *btype = it->itElement; + + /* Note btype->itNumber == count->argMultiplier */ + + if (akIdent(arg->argKind) != akeSubCount) { + /* we skip the SubCount case, as we have already taken care of */ + fprintf(file, "\tif (%s%s > %d) {\n", countRef, count->argVarName, it->itNumber/btype->itNumber); + WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE"); + fprintf(file, "\t}\n"); + } + + fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, ", arg->argMsgField, ref, arg->argVarName); + if (btype->itTypeSize > 1) + fprintf(file, "%d * ", btype->itTypeSize); + fprintf(file, "%s%s);\n", countRef, count->argVarName); + } + } + else if (IS_OPTIONAL_NATIVE(it)) { + fprintf(file, "\tif ((InP->__Present__%s = (%s != %s))) {\n", arg->argMsgField, arg->argVarName, it->itBadValue); + WriteCopyType(file, it, TRUE, "\tInP->%s.__Real__%s", "/* %s%s */ %s%s", arg->argMsgField, arg->argMsgField, ref, arg->argVarName); + fprintf(file, "\t}\n"); + } + else + WriteCopyType(file, it, TRUE, "InP->%s", "/* %s */ %s%s", arg->argMsgField, ref, arg->argVarName); + + if (arg->argPadName != NULL && it->itPadSize != 0) { + fprintf(file, "\t for (int i = 0; i < %d; i++)\n", it->itPadSize); + fprintf(file, "\t\t InP->%s[i] = 0;\n", arg->argPadName); + } + fprintf(file, "\n"); +} + +/* + * Calculate the size of a variable-length message field. + */ +static void +WriteArgSizeVariable(FILE *file, argument_t *arg, ipc_type_t *ptype) +{ + int bsize = ptype->itElement->itTypeSize; + argument_t *count = arg->argCount; + + if (PackMsg == FALSE) { + fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); + return; + } + + /* If the base type size of the data field isn`t a multiple of 4, + we have to round up. */ + if (bsize % itWordAlign != 0) + fprintf(file, "_WALIGN_"); + fprintf(file, "("); + if (bsize > 1) + fprintf(file, "%d * ", bsize); + if (ptype->itString) + /* get count from descriptor in message */ + fprintf(file, "InP->%s", count->argMsgField); + else + /* get count from argument */ + fprintf(file, "%s%s", count->argByReferenceUser ? "*" : "", count->argVarName); + fprintf(file, ")"); +} + +static void +WriteArgSizeOptional(FILE *file, argument_t *arg, ipc_type_t *ptype) +{ + fprintf(file, "(InP->__Present__%s ? _WALIGNSZ_(%s) : 0)", arg->argVarName, ptype->itUserType); +} + +static void +WriteArgSize(FILE *file, argument_t *arg) + +{ + ipc_type_t *ptype = arg->argType; + + if (IS_OPTIONAL_NATIVE(ptype)) + WriteArgSizeOptional(file, arg, ptype); + else + WriteArgSizeVariable(file, arg, ptype); +} + +/* + * Adjust message size and advance request pointer. + * Called after packing a variable-length argument that + * has more arguments following. + */ +static void +WriteAdjustMsgSize(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + + /* There are more In arguments. We need to adjust msgh_size + and advance InP, so we save the size of the current field + in msgh_size_delta. */ + + fprintf(file, "\tmsgh_size_delta = "); + WriteArgSize(file, arg); + fprintf(file, ";\n"); + + if (arg->argRequestPos == 0) { + /* First variable-length argument. The previous msgh_size value + is the minimum request size. */ + + fprintf(file, "\tmsgh_size = "); + rtMinRequestSize(file, arg->argRoutine, "Request"); + fprintf(file, " + msgh_size_delta;\n"); + } + else + fprintf(file, "\tmsgh_size += msgh_size_delta;\n"); + + if (PackMsg == TRUE) { + fprintf(file, "\tInP = (Request *) ((pointer_t) InP + msgh_size_delta - "); + if (IS_OPTIONAL_NATIVE(ptype)) + fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType); + else + fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); + fprintf(file, ");\n\n"); + } +} + +/* + * Calculate the size of the message. Called after the + * last argument has been packed. + */ +static void +WriteFinishMsgSize(FILE *file, argument_t *arg) +{ + /* No more In arguments. If this is the only variable In + argument, the previous msgh_size value is the minimum + request size. */ + + if (arg->argRequestPos == 0) { + fprintf(file, "\tmsgh_size = "); + rtMinRequestSize(file, arg->argRoutine, "Request"); + fprintf(file, " + ("); + WriteArgSize(file, arg); + fprintf(file, ");\n"); + } + else { + fprintf(file, "\tmsgh_size += "); + WriteArgSize(file, arg); + fprintf(file, ";\n"); + } +} + +static void +WriteInitializeCount(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argCInOut->argParent->argType; + ipc_type_t *btype = ptype->itElement; + + fprintf(file, "\tif (%s%s < %d)\n", arg->argByReferenceUser ? "*" : "", arg->argVarName, ptype->itNumber/btype->itNumber); + fprintf(file, "\t\tInP->%s = %s%s;\n", arg->argMsgField, arg->argByReferenceUser ? "*" : "", arg->argVarName); + fprintf(file, "\telse\n"); + fprintf(file, "\t\tInP->%s = %d;\n", arg->argMsgField, ptype->itNumber/btype->itNumber); + fprintf(file, "\n"); +} + +/* + * Generate code to fill in all of the request arguments and their + * message types. + */ +static void +WriteRequestArgs(FILE *file, routine_t *rt) +{ + argument_t *arg; + argument_t *lastVarArg; + + /* + * 1. The Kernel Processed Data + */ + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, akbSendSnd|akbSendKPD)) + (*arg->argKPD_Pack)(file, arg); + + /* + * 2. The Data Stream + */ + lastVarArg = argNULL; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + /* + * Adjust message size and advance message pointer if + * the last request argument was variable-length and the + * request position will change. + */ + if (lastVarArg != argNULL && + lastVarArg->argRequestPos < arg->argRequestPos) { + WriteAdjustMsgSize(file, lastVarArg); + lastVarArg = argNULL; + } + + if ((akIdent(arg->argKind) == akeCountInOut) && + akCheck(arg->argKind, akbSendSnd)) + WriteInitializeCount(file, arg); + else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody)) + WritePackArgValueNormal(file, arg); + /* + * Remember whether this was variable-length. + */ + if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody|akbVariable)) + lastVarArg = arg; + } + /* + * Finish the message size. + */ + if (lastVarArg != argNULL) + WriteFinishMsgSize(file, lastVarArg); +} + +/************************************************************* + * Writes code to check that the return msgh_id is correct and that + * the size of the return message is correct. Called by + * WriteRoutine. + *************************************************************/ +static void +WriteCheckIdentity(FILE *file, routine_t *rt) +{ + fprintf(file, "\tif (Out0P->Head.msgh_id != %d) {\n", rt->rtNumber + SubsystemBase + 100); + fprintf(file, "\t if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n"); + fprintf(file, "\t\t{ return MIG_SERVER_DIED; }\n"); + fprintf(file, "\t else\n"); + fprintf(file, "\t\t{ return MIG_REPLY_MISMATCH; }\n"); + fprintf(file, "\t}\n"); + fprintf(file, "\n"); + if (!rt->rtSimpleReply) + fprintf(file, "\tmsgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n"); + fprintf(file, "#if\t__MigTypeCheck\n"); + + if (!rt->rtNoReplyArgs) + fprintf(file, "\tmsgh_size = Out0P->Head.msgh_size;\n\n"); + + if (rt->rtSimpleReply) { + /* Expecting a simple message. We can factor out the check for + * a simple message, since the error reply message is also simple. + */ + fprintf(file, "\tif ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); + if (rt->rtNoReplyArgs) + fprintf(file, "\t (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))\n"); + else { + /* + * We have an error iff: + * 1) the message size is not the one expected AND + * 2) the message size is also different from sizeof(mig_reply_error_t) + * or the RetCode == KERN_SUCCESS + */ + if (rt->rtNumReplyVar > 0) { + fprintf(file, "\t ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < "); + rtMinReplySize(file, rt, "__Reply"); + fprintf(file, ") &&\n"); + } + else + fprintf(file, "\t ((msgh_size != (mach_msg_size_t)sizeof(__Reply)) &&\n"); + fprintf(file, "\t (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n"); + fprintf(file, "\t Out0P->RetCode == KERN_SUCCESS)))\n"); + } + } + else { + /* Expecting a complex message. */ + + fprintf(file, "\t" "if ((msgh_simple || Out0P->msgh_body.msgh_descriptor_count != %d ||\n", rt->rtReplyKPDs); + if (rt->rtNumReplyVar > 0) { + fprintf(file, "\t msgh_size < "); + rtMinReplySize(file, rt, "__Reply"); + fprintf(file, " || msgh_size > (mach_msg_size_t)sizeof(__Reply)) &&\n"); + } + else + fprintf(file, "\t msgh_size != (mach_msg_size_t)sizeof(__Reply)) &&\n"); + fprintf(file, "\t (!msgh_simple || msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n"); + fprintf(file, "\t ((mig_reply_error_t *)Out0P)->RetCode == KERN_SUCCESS))\n"); + } + fprintf(file, "\t\t{ return MIG_TYPE_ERROR ; }\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + fprintf(file, "\n"); +} + +/************************************************************* + * Write code to generate error handling code if the RetCode + * argument of a Routine is not KERN_SUCCESS. + *************************************************************/ +static void +WriteRetCodeCheck(FILE *file, routine_t *rt) +{ + if (rt->rtSimpleReply) + fprintf(file, "\tif (Out0P->RetCode != KERN_SUCCESS) {\n"); + else + fprintf(file, "\tif (msgh_simple) {\n"); + if (CheckNDR) { + fprintf(file, "#ifdef\t__NDR_convert__mig_reply_error_t__defined\n"); + fprintf(file, "\t\t__NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P);\n"); + fprintf(file, "#endif\t/* __NDR_convert__mig_reply_error_t__defined */\n"); + } + fprintf(file, "\t\treturn ((mig_reply_error_t *)Out0P)->RetCode;\n"); + fprintf(file, "\t}\n"); + fprintf(file, "\n"); +} + +/* + * argKPD_TypeCheck discipline for Port types. + */ +static void +WriteTCheckKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab = ""; + char string[MAX_STR_LEN]; + boolean_t close = FALSE; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE); + (void)sprintf(string, "ptr->"); + tab = "\t"; + close = TRUE; + } + else + (void)sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField); + fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string); + if (arg->argPoly == argNULL && !it->itVarArray) + /* we can't check disposition when poly or VarArray, + (because some of the entries could be empty) */ + fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr); + fprintf(file, + ") {\n" + "\t\t%s" "return MIG_TYPE_ERROR;\n" + "\t%s" "}\n" + , tab, tab); + if (close) + fprintf(file, "\t }\n\t}\n"); +} + +/* + * argKPD_TypeCheck discipline for out-of-line types. + */ +static void +WriteTCheckKPD_ool(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab, string[MAX_STR_LEN]; + boolean_t test; + u_int howmany, howbig; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + howmany = it->itElement->itNumber; + howbig = it->itElement->itSize; + test = !it->itVarArray && !it->itElement->itVarArray; + } + else { + tab = ""; + sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField); + howmany = it->itNumber; + howbig = it->itSize; + test = !it->itVarArray; + } + + fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string); + if (test) + /* if VarArray we may use no-op; if itElement->itVarArray size might change */ + fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8); + fprintf(file, + ") {\n" + "\t\t%s" "return MIG_TYPE_ERROR;\n" + "\t%s" "}\n" + , tab, tab); + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); +} + +/* + * argKPD_TypeCheck discipline for out-of-line Port types. + */ +static void +WriteTCheckKPD_oolport(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *tab, string[MAX_STR_LEN]; + boolean_t test; + u_int howmany; + char *howstr; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + howmany = it->itElement->itNumber; + test = !it->itVarArray && !it->itElement->itVarArray; + howstr = it->itElement->itOutNameStr; + } + else { + tab = ""; + sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField); + howmany = it->itNumber; + test = !it->itVarArray; + howstr = it->itOutNameStr; + } + + fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string); + if (test) + /* if VarArray we may use no-op; if itElement->itVarArray size might change */ + fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany); + if (arg->argPoly == argNULL) + fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr); + fprintf(file, ") {\n" + "\t\t%s" "return MIG_TYPE_ERROR;\n" + "\t%s" "}\n" + ,tab, tab); + if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t }\n\t}\n"); +} + +/************************************************************* + * Writes code to check that the type of each of the arguments + * in the reply message is what is expected. Called by + * WriteRoutine for each out && typed argument in the reply message. + *************************************************************/ +static void +WriteTypeCheck(FILE *file, argument_t *arg) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + (*arg->argKPD_TypeCheck)(file, arg); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + + +/* + * argKPD_Extract discipline for Port types. + */ +static void +WriteExtractKPD_port(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char *ref = arg->argByReferenceUser ? "*" : ""; + char *subindex; + char *recast = ""; + ipc_type_t *real_it; + + real_it = (IS_MULTIPLE_KPD(it)) ? it->itElement : it; +#ifdef MIG_KERNEL_PORT_CONVERSION + if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t")) + recast = "(mach_port_t)"; +#endif + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE); + + fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast); + if (it->itVarArray) { + argument_t *count = arg->argCount; + char *cref = count->argByReferenceUser ? "*" : ""; + + fprintf(file, "\t if (Out%dP->%s >",count->argReplyPos, count->argVarName); + if (arg->argCountInOut) { + fprintf(file, " %s%s)\n", cref, count->argVarName); + } + else { + fprintf(file, " %d)\n", it->itNumber/it->itElement->itNumber); + } + WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE"); + } + fprintf(file, "\t}\n"); + subindex = "[0]"; + } + else { + fprintf(file, "\t%s%s = %sOut%dP->%s.name;\n", ref, arg->argVarName, recast, arg->argReplyPos, arg->argMsgField); + subindex = ""; + } + + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) { + argument_t *poly = arg->argPoly; + char *pref = poly->argByReferenceUser ? "*" : ""; + + fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n", pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex); + } +} + +/* + * argKPD_Extract discipline for out-of-line types. + */ +static void +WriteExtractKPD_ool(FILE *file, argument_t *arg) +{ + char *ref = arg->argByReferenceUser ? "*" : ""; + ipc_type_t *it = arg->argType; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE); + fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); + fprintf(file, "\t}\n"); + } + else + fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref, arg->argVarName, arg->argType->itUserType, arg->argReplyPos, arg->argMsgField); + /* + * In case of variable sized arrays, + * the count field will be retrieved from the untyped + * section of the message + */ +} + +/* + * argKPD_Extract discipline for out-of-line Port types. + */ +static void +WriteExtractKPD_oolport(FILE *file, argument_t *arg) +{ + char *ref = arg->argByReferenceUser ? "*" : ""; + ipc_type_t *it = arg->argType; + char *subindex; + + if (IS_MULTIPLE_KPD(it)) { + WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE); + fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); + fprintf(file, "\t}\n"); + subindex = "[0]"; + } + else { + fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref, arg->argVarName, arg->argType->itUserType, arg->argReplyPos, arg->argMsgField); + subindex = ""; + } + /* + * In case of variable sized arrays, + * the count field will be retrieved from the untyped + * section of the message + */ + if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) { + argument_t *poly = arg->argPoly; + char *pref = poly->argByReferenceUser ? "*" : ""; + + fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n", pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex); + } +} + +/************************************************************* + * Write code to copy an argument from the reply message + * to the parameter. Called by WriteRoutine for each argument + * in the reply message. + *************************************************************/ + +static void +WriteExtractArgValueNormal(FILE *file, argument_t *arg) +{ + ipc_type_t *argType = arg->argType; + char *ref = arg->argByReferenceUser ? "*" : ""; + char who[20]; + + if (akCheck(arg->argKind, akbUserImplicit)) + sprintf(who, "TrailerP"); + else + sprintf(who, "Out%dP", arg->argReplyPos); + + if (IS_VARIABLE_SIZED_UNTYPED(argType) || argType->itNoOptArray) { + if (argType->itString) { + /* + * Copy out variable-size C string with mig_strncpy, not the zerofill variant. + * We don't risk leaking process / kernel memory on this copy-out because + * we've already zero-filled the buffer on copy-in. + */ + fprintf(file, "\t(void) mig_strncpy(%s%s, %s->%s, %d);\n", ref, arg->argVarName, who, arg->argMsgField, argType->itNumber); + } + else if (argType->itNoOptArray) + fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) %s->%s, %d);\n", ref, arg->argVarName, who, arg->argMsgField, argType->itTypeSize); + else { + + /* + * Copy out variable-size inline array with (void)memcpy, + * after checking that number of elements doesn`t + * exceed user`s maximum. + */ + argument_t *count = arg->argCount; + char *countRef = count->argByReferenceUser ? "*" : ""; + ipc_type_t *btype = argType->itElement; + + /* Note count->argMultiplier == btype->itNumber */ + /* Note II: trailer logic isn't supported in this case */ + fprintf(file, "\tif (Out%dP->%s", count->argReplyPos, count->argMsgField); + if (arg->argCountInOut) { + fprintf(file, " > %s%s) {\n", countRef, count->argVarName); + } + else { + fprintf(file, " > %d) {\n", argType->itNumber/btype->itNumber); + } + + /* + * If number of elements is too many for user receiving area, + * fill user`s area as much as possible. Return the correct + * number of elements. + */ + fprintf(file, "\t\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ", ref, arg->argVarName, arg->argReplyPos, arg->argMsgField); + if (btype->itTypeSize > 1) + fprintf(file, "%d * ", btype->itTypeSize); + if (arg->argCountInOut) { + fprintf(file, " %s%s);\n", countRef, count->argVarName); + } + else { + fprintf(file, " %d);\n", argType->itNumber/btype->itNumber); + } + fprintf(file, "\t\t%s%s = Out%dP->%s", countRef, count->argVarName, count->argReplyPos, count->argMsgField); + fprintf(file, ";\n"); + WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE"); + + fprintf(file, "\t}\n"); + + fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ", ref, arg->argVarName, arg->argReplyPos, arg->argMsgField); + if (btype->itTypeSize > 1) + fprintf(file, "%d * ", btype->itTypeSize); + fprintf(file, "Out%dP->%s);\n", count->argReplyPos, count->argMsgField); + } + } + else + WriteCopyType(file, argType, FALSE, "%s%s", "/* %s%s */ %s->%s", ref, arg->argVarName, who, arg->argMsgField); + fprintf(file, "\n"); +} + +static void +WriteCalcArgSize(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + ipc_type_t *btype = ptype->itElement; + argument_t *count = arg->argCount; + int multiplier = btype->itTypeSize; + + /* If the base type size of the data field isn`t a multiple of 4, + we have to round up. */ + if (btype->itTypeSize % itWordAlign != 0) + fprintf(file, "_WALIGN_("); + + fprintf(file, "Out%dP->%s", count->argReplyPos, count->argMsgField); + if (multiplier > 1) + fprintf(file, " * %d", multiplier); + + if (btype->itTypeSize % itWordAlign != 0) + fprintf(file, ")"); +} + +static void +WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator) +{ + ipc_type_t *ptype = arg->argType; + ipc_type_t *btype = ptype->itElement; + argument_t *count = arg->argCount; + int multiplier = btype->itTypeSize; + + fprintf(file, "\tif (((msgh_size - "); + rtMinReplySize(file, rt, "__Reply"); + fprintf(file, ")"); + if (multiplier > 1) + fprintf(file, " / %d", multiplier); + fprintf(file, "< Out%dP->%s) ||\n", count->argReplyPos, count->argMsgField); + fprintf(file, "\t (msgh_size %s ", comparator); + rtMinReplySize(file, rt, "__Reply"); + fprintf(file, " + "); + WriteCalcArgSize(file, arg); + fprintf(file, ")"); + fprintf(file, ")\n\t\t{ return MIG_TYPE_ERROR ; }\n"); +} + + +/* NDR Conversion routines */ + + +void +WriteReplyNDRConvertIntRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + fprintf(file, "defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField); +} + +void +WriteReplyNDRConvertCharRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + fprintf(file, "defined(__NDR_convert__char_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField); + else + fprintf(file, "0"); +} + +void +WriteReplyNDRConvertFloatRepArgCond(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + fprintf(file, "defined(__NDR_convert__float_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField); + else + fprintf(file, "0"); +} + +void +WriteReplyNDRConvertIntRepArgDecl(FILE *file, argument_t *arg) +{ + WriteNDRConvertArgDecl(file, arg, "int_rep", "Reply"); +} + +void +WriteReplyNDRConvertCharRepArgDecl(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + WriteNDRConvertArgDecl(file, arg, "char_rep", "Reply"); +} + +void +WriteReplyNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + WriteNDRConvertArgDecl(file, arg, "float_rep", "Reply"); +} + + + +void +WriteReplyNDRConvertArgUse(FILE *file, argument_t *arg, char *convert) +{ + routine_t *rt = arg->argRoutine; + argument_t *count = arg->argCount; + char argname[MAX_STR_LEN]; + + if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) && + (arg->argParent && akCheck(arg->argParent->argKind, akbReturnNdr))) + return; + + if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) { + fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, count->argMsgField); + fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argReplyPos, count->argMsgField, count->argReplyPos); + fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, count->argMsgField); + } + + sprintf(argname, "(%s)(Out%dP->%s.address)", FetchServerType(arg->argType), arg->argReplyPos, arg->argMsgField); + } + else { + sprintf(argname, "&Out%dP->%s", arg->argReplyPos, arg->argMsgField); + } + + fprintf(file, "#if defined(__NDR_convert__%s__Reply__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField); + fprintf(file, "\t\t__NDR_convert__%s__Reply__%s_t__%s(%s, Out0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert); + if (count) + fprintf(file, ", Out%dP->%s", count->argReplyPos, count->argMsgField); + fprintf(file, ");\n"); + fprintf(file, "#endif /* __NDR_convert__%s__Reply__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField); +} + +void +WriteReplyNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField); + fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep)\n"); + fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argReplyPos, arg->argMsgField, arg->argReplyPos); + fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField); +} + +void +WriteReplyNDRConvertIntRepArgUse(FILE *file, argument_t *arg) +{ + WriteReplyNDRConvertArgUse(file, arg, "int_rep"); +} + +void +WriteReplyNDRConvertCharRepArgUse(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + WriteReplyNDRConvertArgUse(file, arg, "char_rep"); +} + +void +WriteReplyNDRConvertFloatRepArgUse(FILE *file, argument_t *arg) +{ + if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode) + WriteReplyNDRConvertArgUse(file, arg, "float_rep"); +} + +static void +WriteCheckMsgSize(FILE *file, argument_t *arg) +{ + routine_t *rt = arg->argRoutine; + + /* If there aren't any more Out args after this, then + we can use the msgh_size_delta value directly in + the TypeCheck conditional. */ + + if (CheckNDR && arg->argCount && !arg->argSameCount) + WriteReplyNDRConvertIntRepOneArgUse(file, arg->argCount); + + if (arg->argReplyPos == rt->rtMaxReplyPos) { + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* + * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type. + */ + fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber); + fputs("\t\t" "return MIG_TYPE_ERROR;\n", file); + /* ...end... */ + + WriteCheckArgSize(file, rt, arg, "!="); + + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + else { + /* If there aren't any more variable-sized arguments after this, + then we must check for exact msg-size and we don't need + to update msgh_size. */ + + boolean_t LastVarArg = arg->argReplyPos+1 == rt->rtNumReplyVar; + + /* calculate the actual size in bytes of the data field. note + that this quantity must be a multiple of four. hence, if + the base type size isn't a multiple of four, we have to + round up. note also that btype->itNumber must + divide btype->itTypeSize (see itCalculateSizeInfo). */ + + fprintf(file, "\tmsgh_size_delta = "); + WriteCalcArgSize(file, arg); + fprintf(file, ";\n"); + fprintf(file, "#if\t__MigTypeCheck\n"); + + /* + * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type. + */ + fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber); + fputs("\t\t" "return MIG_TYPE_ERROR;\n", file); + /* ...end... */ + + WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<"); + + if (!LastVarArg) + fprintf(file, "\tmsgh_size -= msgh_size_delta;\n"); + + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + fprintf(file, "\n"); +} + +void +WriteAdjustReplyMsgPtr(FILE *file, argument_t *arg) +{ + ipc_type_t *ptype = arg->argType; + + fprintf(file, "\t*Out%dPP = Out%dP = (__Reply *) ((pointer_t) Out%dP + msgh_size_delta - %d);\n\n", + arg->argReplyPos+1, arg->argReplyPos +1, arg->argReplyPos, ptype->itTypeSize + ptype->itPadSize); +} + +static void +WriteReplyArgs(FILE *file, routine_t *rt) +{ + argument_t *arg; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) { + WriteExtractArgValueNormal(file, arg); + } + else if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnKPD)) { + /* + * KPDs have argReplyPos 0, therefore they escape the above logic + */ + (*arg->argKPD_Extract)(file, arg); + } + else if (akCheck(arg->argKind, akbUserImplicit)) { + WriteExtractArgValueNormal(file, arg); + } + } +} + +/************************************************************* + * Writes code to return the return value. Called by WriteRoutine + * for routines and functions. + *************************************************************/ +static void +WriteReturnValue(FILE *file, routine_t *rt) +{ + /* If returning RetCode, we have already checked that it is KERN_SUCCESS */ + WriteReturn(file, rt, "\t", "KERN_SUCCESS", "\n", TRUE); +} + +/************************************************************* + * Writes the elements of the message type declaration: the + * msg_type structure, the argument itself and any padding + * that is required to make the argument a multiple of 4 bytes. + * Called by WriteRoutine for all the arguments in the request + * message first and then the reply message. + *************************************************************/ +static void +WriteFieldDecl(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbSendKPD) || + akCheck(arg->argKind, akbReturnKPD)) + WriteFieldDeclPrim(file, arg, FetchKPDType); + else + WriteFieldDeclPrim(file, arg, FetchUserType); +} + +/* Fill in the string with an expression that refers to the size + * of the specified array: + */ +static void +GetArraySize(argument_t *arg, char *size) +{ + ipc_type_t *it = arg->argType; + + if (it->itVarArray) { + if (arg->argCount->argByReferenceUser) { + sprintf(size, "*%s", arg->argCount->argVarName); + } + else + sprintf(size, "%s", arg->argCount->argVarName); + } + else { + sprintf(size, "%d", (it->itNumber * it->itSize + 7) / 8); + } +} + + +static void +WriteRPCPortDisposition(FILE *file, argument_t *arg) +{ + /* + * According to the MIG specification, the port disposition could be different + * on input and output. If we stay with this then a new bitfield will have + * to be added. Right now the port disposition is the same for in and out cases. + */ + switch(arg->argType->itInName) { + + case MACH_MSG_TYPE_MOVE_RECEIVE: + fprintf(file, " | MACH_RPC_MOVE_RECEIVE"); + break; + + case MACH_MSG_TYPE_MOVE_SEND: + fprintf(file, " | MACH_RPC_MOVE_SEND"); + break; + + case MACH_MSG_TYPE_MOVE_SEND_ONCE: + fprintf(file, " | MACH_RPC_MOVE_SEND_ONCE"); + break; + + case MACH_MSG_TYPE_COPY_SEND: + fprintf(file, " | MACH_RPC_COPY_SEND"); + break; + + case MACH_MSG_TYPE_MAKE_SEND: + fprintf(file, " | MACH_RPC_MAKE_SEND"); + break; + + case MACH_MSG_TYPE_MAKE_SEND_ONCE: + fprintf(file, " | MACH_RPC_MAKE_SEND_ONCE"); + break; + } +} + +static void +WriteRPCArgDescriptor(FILE *file, argument_t *arg, int offset) +{ + fprintf(file, " {\n 0 "); + if (RPCPort(arg)) { + fprintf(file, "| MACH_RPC_PORT "); + if (arg->argType->itNumber > 1) + fprintf(file, "| MACH_RPC_ARRAY "); + if (arg->argType->itVarArray) + fprintf(file, "| MACH_RPC_VARIABLE "); + WriteRPCPortDisposition(file, arg); + } + else if (RPCPortArray(arg)) { + fprintf(file, "| MACH_RPC_PORT_ARRAY "); + if (arg->argType->itVarArray) + fprintf(file, "| MACH_RPC_VARIABLE "); + WriteRPCPortDisposition(file, arg); + } + else if (RPCFixedArray(arg)) + fprintf(file, "| MACH_RPC_ARRAY_FIXED "); + else if (RPCVariableArray(arg)) + fprintf(file, "| MACH_RPC_ARRAY_VARIABLE "); + if (argIsIn(arg)) + fprintf(file, " | MACH_RPC_IN "); + if (argIsOut(arg)) + fprintf(file, " | MACH_RPC_OUT "); + if ((! arg->argType->itInLine) && (! arg->argType->itMigInLine)) + fprintf(file, " | MACH_RPC_POINTER "); + if (arg->argFlags & flDealloc) + fprintf(file, " | MACH_RPC_DEALLOCATE "); + if (arg->argFlags & flPhysicalCopy) + fprintf(file, " | MACH_RPC_PHYSICAL_COPY "); + fprintf(file, ",\n"); + fprintf(file, " %d,\n", (arg->argType->itSize / 8)); + fprintf(file, " %d,\n", arg->argType->itNumber); + fprintf(file, " %d,\n },\n", offset); +} + +void +WriteRPCRoutineDescriptor(FILE *file, routine_t *rt, int arg_count, int descr_count, string_t stub_routine, string_t sig_array) +{ + fprintf(file, " { (mig_impl_routine_t) 0,\n\ + (mig_stub_routine_t) %s, ", stub_routine); + fprintf(file, "%d, %d, %s}", arg_count, descr_count, sig_array); +} + +void +WriteRPCRoutineArgDescriptor(FILE *file, routine_t *rt) +{ + argument_t *arg; + int offset = 0; + int size = 0; + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + boolean_t compound = arg->argType->itStruct && arg->argType->itInLine; + + if (RPCPort(arg) || RPCPortArray(arg) || + RPCFixedArray(arg) || RPCVariableArray(arg)) { + WriteRPCArgDescriptor(file, arg, offset); + size = 4; + } + if (! size) { + if (compound) + size = arg->argType->itNumber * (arg->argType->itSize / 8); + else + size = (arg->argType->itSize / 8); + } + if (akCheck(arg->argKind, akbServerArg)) + offset += size; + size = 0; + } +} + + +static void +WriteRPCSignature(FILE *file, routine_t *rt) +{ + int arg_count = 0; + int descr_count = 0; + + fprintf(file, " kern_return_t rtn;\n"); + descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count); + fprintf(file, " const static struct\n {\n"); + fprintf(file, " struct rpc_routine_descriptor rd;\n"); + fprintf(file, " struct rpc_routine_arg_descriptor rad[%d];\n", descr_count); + fprintf(file, " } sig =\n {\n"); + WriteRPCRoutineDescriptor(file, rt, arg_count, descr_count, "0", "sig.rad, 0"); + fprintf(file, ",\n"); + fprintf(file, " {\n"); + WriteRPCRoutineArgDescriptor(file, rt); + fprintf(file, "\n }\n"); + fprintf(file, "\n };\n\n"); +} + +static void +WriteRPCCall(FILE *file, routine_t *rt) +{ + argument_t *arg; + int i; + + i = 0; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akIdent(arg->argKind) == akeRequestPort) { + fprintf(file, " rtn = (MACH_RPC(&sig, (mach_msg_size_t)sizeof(sig), %d, %s,\n", rt->rtNumber + SubsystemBase, arg->argVarName); + fprintf(file, " (%s", arg->argVarName); + } + else if (akCheck(arg->argKind, akbServerArg)) { + if (i && (i++ % 6 == 0)) + fprintf(file, ",\n "); + else + fprintf(file, ", "); + fprintf(file, "%s", arg->argVarName); + } + } + fprintf(file, ")));\n"); + fprintf(file, "\n"); + fprintf(file, " if (rtn != KERN_NO_ACCESS) return rtn;\n\n"); + fprintf(file, "/* The following message rpc code is generated for the network case */\n\n"); +} + +static int +CheckRPCCall(routine_t *rt) +{ + argument_t *arg; + int i; + + i = 0; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akCheck(arg->argKind, akbUserArg) && + ((arg->argType->itOutName == -1) || (arg->argType->itInName == -1))) { + return FALSE; + } + if (arg->argFlags & flMaybeDealloc) { + return FALSE; + } + } + return TRUE; +} + +static void +WriteRPCRoutine(FILE *file, routine_t *rt) +{ + if (CheckRPCCall(rt)) { + WriteRPCSignature(file, rt); + WriteRPCCall(file, rt); + } +} + +/********************** End UserRPCTrap Routines*************************/ + +/* Process an IN/INOUT arg before the short-circuited RPC */ +static void +WriteShortCircInArgBefore(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char size[128]; + + fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName); + + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) { + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + break; + + case MACH_MSG_OOL_DESCRIPTOR: + /* Arg is an out-of-line array: */ + if (!(arg->argFlags & flDealloc) && + (!(arg->argFlags & flAuto) || !(arg->argFlags & flConst))) { + /* Need to map a copy of the array: */ + GetArraySize(arg, size); + fprintf(file, "\t(void)vm_read(mach_task_self(),\n"); + fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size, arg->argVarName); + /* Point argument at the copy: */ + fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, arg->argVarName); + } + else if ((arg->argFlags & flDealloc) && + ((arg->argFlags & flAuto) || it->itMigInLine)) { + /* Point the temp var at the original argument: */ + fprintf(file, "\t_%sTemp_ = (char *) %s%s;\n", arg->argVarName, (arg->argByReferenceUser ? "*" : ""), arg->argVarName); + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ + } + else if (it->itNumber > 1) { + if (it->itStruct) { + /* Arg is a struct -- nothing to do. */ + } + else { + /* Arg is a C string or an in-line array: */ + if (!argIsOut(arg) && !(arg->argFlags & flConst)) { + /* Have to copy it into a temp. Use a stack var, if this would + * not overflow the -maxonstack specification: + * Conservatively assume ILP32 thresholds + */ + if (it->itTypeSize <= sizeof(natural_t) || + rtMessOnStack(arg->argRoutine) || + arg->argRoutine->rtTempBytesOnStack + + it->itTypeSize <= MaxMessSizeOnStack) { + fprintf(file, "\t{ char _%sTemp_[%d];\n", arg->argVarName, it->itTypeSize); + arg->argRoutine->rtTempBytesOnStack += it->itTypeSize; + arg->argTempOnStack = TRUE; + } + else { + fprintf(file, "\t{ _%sTemp_ = (char *) %s(%d);\n", arg->argVarName, MessAllocRoutine, it->itTypeSize); + arg->argTempOnStack = FALSE; + } + WriteCopyArg(file, arg, TRUE, "_%sTemp_", "/* %s */ (char *) %s", arg->argVarName, arg->argVarName); + /* Point argument at temp: */ + fprintf(file, "\t *(char **)&%s%s = _%sTemp_;\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, arg->argVarName); + fprintf(file, "\t}\n"); + } + } + } +} + + +/* Process an INOUT/OUT arg before the short-circuited RPC */ +static void +WriteShortCircOutArgBefore(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName); + + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) { + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + break; + + case MACH_MSG_OOL_DESCRIPTOR: + /* Arg is an out-of-line array: */ + if (!argIsIn(arg) && (arg->argFlags & flOverwrite)) { + /* Point the temp var at the original argument: */ + fprintf(file, "\t _%sTemp_ = (char *) %s%s;\n", arg->argVarName, (arg->argByReferenceUser ? "*" : ""), arg->argVarName); + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ + } + else if (it->itNumber > 1) { + /* Arg is an in-line array: */ + } +} + + + +/* Process an IN arg after the short-circuited RPC */ +static void +WriteShortCircInArgAfter(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char size[128]; + + fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName); + + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) { + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + break; + + case MACH_MSG_OOL_DESCRIPTOR: + /* Arg is an out-of-line array: */ + GetArraySize(arg, size); + if ((!(arg->argFlags & flAuto) && it->itMigInLine) || + ((arg->argFlags & flAuto) && + ((arg->argFlags & flDealloc) || + !(arg->argFlags & flConst)) + )) { + /* Need to dealloc the temporary: */ + fprintf(file, "\t(void)vm_deallocate(mach_task_self(),"); + fprintf(file, " (vm_address_t *) _%sTemp_, %s);\n", arg->argVarName, size); + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ + } + else if (it->itNumber > 1) { + if (it->itStruct) { + /* Arg is a struct -- nothing to do. */ + } + else { + /* Arg is a C string or an in-line array: */ + if (!argIsOut(arg) && !(arg->argFlags & flConst)) { + /* A temp needs to be deallocated, if not on stack: */ + if (!arg->argTempOnStack) { + fprintf(file, "\t%s(_%sTemp_, %d);\n", MessFreeRoutine, arg->argVarName, it->itTypeSize); + } + } + } + } +} + +static void +WriteShortCircOutArgAfter(FILE *file, argument_t *arg) +{ + ipc_type_t *it = arg->argType; + char size[128]; + + fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName); + + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) { + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + break; + + case MACH_MSG_OOL_DESCRIPTOR: + /* Arg is an out-of-line array: */ + + /* Calculate size of array: */ + GetArraySize(arg, size); + if (!(arg->argFlags & flDealloc) || (arg->argFlags & flOverwrite)) { + /* Copy argument to vm_allocated Temp: */ + fprintf(file, "\t(void)vm_read(mach_task_self(),\n"); + fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size, arg->argVarName); + if (!argIsIn(arg) && (arg->argFlags & flDealloc) && + (arg->argFlags & flOverwrite)) { + /* Deallocate argument returned by server */ + fprintf(file, "\t(void)vm_deallocate(mach_task_self(),"); + fprintf(file, " (vm_address_t *) %s%s, %s);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size); + } + /* Point argument at new temporary: */ + fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, arg->argVarName); + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ + } + else if (it->itNumber != 1) { + /* Arg is an in-line array: */ + } +} + + +static void +WriteShortCircRPC(FILE *file, routine_t *rt) +{ + argument_t *arg; + int server_argc, i; + boolean_t ShortCircOkay = TRUE; + boolean_t first_OOL_arg = TRUE; + + fprintf(file, " if (0 /* Should be: !(%s & 0x3) XXX */) {\n", rt->rtRequestPort->argVarName); + + if (rt->rtOneWay) { + /* Do not short-circuit simple routines: */ + ShortCircOkay = FALSE; + } + else { + /* Scan for any types we can't yet handle. If found, give up on short- + * circuiting and fall back to mach_msg: + */ + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (arg->argFlags & flMaybeDealloc) { + ShortCircOkay = FALSE; + break; + } + /* Can't yet handle ports: */ + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) && + (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR || + arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)) { + ShortCircOkay = FALSE; + break; + } + } + } + + if (ShortCircOkay) { + + fprintf(file," rpc_subsystem_t subsystem = ((rpc_port_t)%s)->rp_subsystem;\n", rt->rtRequestPort->argVarName); + fprintf(file, "\n"); + fprintf(file, " if (subsystem && subsystem->start == %d) {\n", SubsystemBase); + fprintf(file, "\tkern_return_t rtn;\n"); + fprintf(file, "\n"); + + /* Declare temp vars for out-of-line array args, and for all array + * args, if -maxonstack has forced us to allocate in-line arrays + * off the stack: + */ + rt->rtTempBytesOnStack = 0; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + arg->argTempOnStack = FALSE; + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) && + arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + if (first_OOL_arg) { + /* Need a garbage temporary to hold the datacount + * returned by vm_read, which we always ignore: + */ + fprintf(file, "\tmach_msg_type_number_t _MIG_Ignore_Count_;\n"); + first_OOL_arg = FALSE; + } + } + else if (!rtMessOnStack(rt) && + arg->argType->itNumber > 1 && !arg->argType->itStruct) { + } + else + continue; + fprintf(file, "\tchar *_%sTemp_;\n", arg->argVarName); + /* Conservatively assume ILP32 thresholds */ + rt->rtTempBytesOnStack += sizeof(natural_t); + } + + /* Process the IN arguments, in order: */ + + fprintf(file, "\t/* Pre-Process the IN arguments: */\n"); + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (argIsIn(arg)) + WriteShortCircInArgBefore(file, arg); + if (argIsOut(arg)) + WriteShortCircOutArgBefore(file, arg); + } + fprintf(file, "\n"); + + /* Count the number of server args: */ + server_argc = 0; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, akbServerArg)) + server_argc++; + + /* Call RPC_SIMPLE to switch to server stack and function: */ + i = 0; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akIdent(arg->argKind) == akeRequestPort) { + fprintf(file, "\trtn = RPC_SIMPLE(%s, %d, %d, (", arg->argVarName, rt->rtNumber + SubsystemBase, server_argc); + fprintf(file, "%s", arg->argVarName); + } + else if (akCheck(arg->argKind, akbServerArg)) { + if (i++ % 6 == 0) + fprintf(file, ",\n\t\t"); + else + fprintf(file, ", "); + fprintf(file, "%s", arg->argVarName); + } + } + fprintf(file, "));\n"); + fprintf(file, "\n"); + + /* Process the IN and OUT arguments, in order: */ + fprintf(file, "\t/* Post-Process the IN and OUT arguments: */\n"); + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (argIsIn(arg)) + WriteShortCircInArgAfter(file, arg); + if (argIsOut(arg)) + WriteShortCircOutArgAfter(file, arg); + } + fprintf(file, "\n"); + + fprintf(file, "\treturn rtn;\n"); + fprintf(file, " }\n"); + } + + /* In latest design, the following is not necessary, because in + * kernel-loaded tasks, the Mach port name is the same as the handle + * used by the RPC mechanism, namely a pointer to the ipc_port, and + * in user-mode tasks, the Mach port name gets renamed to be a pointer + * to the user-mode rpc_port_t struct. + */ +#if 0 + if (IsKernelUser) + fprintf(file, " %s = (ipc_port_t)%s->rp_receiver_name;\n", rt->rtRequestPort->argVarName, rt->rtRequestPort->argVarName); + else + fprintf(file, " %s = ((rpc_port_t)%s)->rp_receiver_name;\n", rt->rtRequestPort->argVarName, rt->rtRequestPort->argVarName); +#endif + + fprintf(file, " }\n"); +} + +static void +WriteStubDecl(FILE *file, routine_t *rt) +{ + fprintf(file, "\n"); + fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); + fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName); + if (BeAnsiC) { + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n"); + fprintf(file, ")\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "(\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n"); + fprintf(file, ")\n"); + fprintf(file, "#else\n"); + fprintf(file, "\t("); + WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", ""); + fprintf(file, ")\n"); + WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + fprintf(file, "{\n"); +} + +static void +InitKPD_Disciplines(argument_t *args) +{ + argument_t *arg; + extern void KPD_noop(FILE *file, argument_t *arg); + extern void KPD_error(FILE *file, argument_t *arg); + extern void WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in); + extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in); + extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in); + + /* + * WriteKPD_port, WriteExtractKPD_port, + * WriteKPD_ool, WriteExtractKPD_ool, + * WriteKPD_oolport, WriteExtractKPD_oolport + * are local to this module (which is the reason why this initialization + * takes place here rather than in utils.c). + * Common routines for user and server will be established SOON, and + * all of them (including the initialization) will be transfert to + * utils.c + * All the KPD disciplines are defaulted to be KPD_error(). + * Note that akbSendKPD and akbReturnKPd are not exclusive, + * because of inout type of parameters. + */ + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) + switch (arg->argKPD_Type) { + + case MACH_MSG_PORT_DESCRIPTOR: + arg->argKPD_Init = KPD_noop; + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Template = WriteTemplateKPD_port; + arg->argKPD_Pack = WriteKPD_port; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_Extract = WriteExtractKPD_port; + arg->argKPD_TypeCheck = WriteTCheckKPD_port; + } + break; + + case MACH_MSG_OOL_DESCRIPTOR: + arg->argKPD_Init = KPD_noop; + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Template = WriteTemplateKPD_ool; + arg->argKPD_Pack = WriteKPD_ool; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_TypeCheck = WriteTCheckKPD_ool; + arg->argKPD_Extract = WriteExtractKPD_ool; + } + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: + arg->argKPD_Init = KPD_noop; + if akCheck(arg->argKind, akbSendKPD) { + arg->argKPD_Template = WriteTemplateKPD_oolport; + arg->argKPD_Pack = WriteKPD_oolport; + } + if akCheck(arg->argKind, akbReturnKPD) { + arg->argKPD_TypeCheck = WriteTCheckKPD_oolport; + arg->argKPD_Extract = WriteExtractKPD_oolport; + } + break; + + default: + printf("MiG internal error: type of kernel processed data unknown\n"); + exit(1); + } /* end of switch */ +} + +static void +WriteLimitCheck(FILE *file, routine_t *rt) +{ + if (MaxMessSizeOnStack == -1 || UserTypeLimit == -1) + return; + if (!rt->rtRequestUsedLimit && !rt->rtReplyUsedLimit) + return; + fprintf(file, "#if LimitCheck\n"); + if (rt->rtRequestUsedLimit) { + if (rt->rtRequestFits) { + fprintf(file, "\tif ((sizeof(Request) - %d) > %d)\n", rt->rtRequestSizeKnown, UserTypeLimit); + fprintf(file, "\t __RequestOnStackAbort(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName); + } + else if (rt->rtReplyFits) { + fprintf(file, "\tif (sizeof(Request) < %d)\n", MaxMessSizeOnStack); + fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName); + } + } + if (rt->rtReplyUsedLimit) { + if (rt->rtReplyFits) { + fprintf(file, "\tif ((sizeof(Reply) - %d) > %d)\n", rt->rtReplySizeKnown, UserTypeLimit); + fprintf(file, "\t __ReplyOnStackAbort(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName); + } + else if (rt->rtRequestFits) { + fprintf(file, "\tif (sizeof(Reply) < %d)\n", MaxMessSizeOnStack); + fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName); + } + } + if (rt->rtRequestUsedLimit && rt->rtReplyUsedLimit && + ! (rt->rtRequestFits || rt->rtReplyFits)) { + fprintf(file, "\tif (sizeof(Request) < %d \n", MaxMessSizeOnStack); + fprintf(file, "&& sizeof(Reply) < %d)\n", MaxMessSizeOnStack); + fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName); + } + fprintf(file, "#endif /* LimitCheck */\n"); +} + +static void +WriteOOLSizeCheck(FILE *file, routine_t *rt) +{ + /* Emit code to validate the actual size of ool data vs. the reported size */ + argument_t *argPtr; + boolean_t openedTypeCheckConditional = FALSE; + + // scan through arguments to see if there are any ool data blocks + for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { + if (akCheck(argPtr->argKind, akbReturnKPD)) { + ipc_type_t *it = argPtr->argType; + boolean_t multiple_kpd = IS_MULTIPLE_KPD(it); + char string[MAX_STR_LEN]; + boolean_t test; + argument_t *argCountPtr; + char *tab; + + if (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { + + if (multiple_kpd) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + WriteKPD_Iterator(file, FALSE, FALSE, FALSE, argPtr, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + test = !it->itVarArray && !it->itElement->itVarArray; + it = it->itElement; // point to element descriptor, so size calculation is correct + argCountPtr = argPtr->argSubCount; + } else { + tab = ""; + sprintf(string, "Out%dP->%s.", argPtr->argReplyPos, argPtr->argMsgField); + test = !it->itVarArray; + argCountPtr = argPtr->argCount; + } + + if (!test) { + int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1; + + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + fprintf(file, "\t%s" "if (%ssize ", tab, string); + if (multiplier > 1) + fprintf(file, "/ %d ", multiplier); + fprintf(file,"!= Out%dP->%s%s", argCountPtr->argReplyPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : ""); + if (it->itOOL_Number) { + fprintf(file," || Out%dP->%s%s > %d", argCountPtr->argReplyPos, + argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number); + } + fprintf(file,")\n"); + fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); + } + + if (multiple_kpd) + fprintf(file, "\t }\n\t}\n"); + } else if (argPtr->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR) { + if (multiple_kpd) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + WriteKPD_Iterator(file, FALSE, FALSE, FALSE, argPtr, TRUE); + tab = "\t"; + sprintf(string, "ptr->"); + test = !it->itVarArray && !it->itElement->itVarArray; + it = it->itElement; // point to element descriptor, so size calculation is correct + argCountPtr = argPtr->argSubCount; + } else { + tab = ""; + sprintf(string, "Out%dP->%s.", argPtr->argReplyPos, argPtr->argMsgField); + test = !it->itVarArray; + argCountPtr = argPtr->argCount; + } + + if (!test) { + if ( !openedTypeCheckConditional ) { + openedTypeCheckConditional = TRUE; + fputs("#if __MigTypeCheck\n", file); + } + + fprintf(file, "\t%s" "if (%scount ", tab, string); + fprintf(file,"!= Out%dP->%s%s", argCountPtr->argReplyPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : ""); + if (it->itOOL_Number) { + fprintf(file," || Out%dP->%s%s > %d", argCountPtr->argReplyPos, + argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number); + } + fprintf(file,")\n"); + fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); + } + + if (multiple_kpd) + fprintf(file, "\t }\n\t}\n"); + } + } + } + + if ( openedTypeCheckConditional ) + fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); +} + +static void +WriteCheckReply(FILE *file, routine_t *rt) +{ + int i; + + /* initialize the disciplines for the handling of KPDs */ + InitKPD_Disciplines(rt->rtArgs); + + if (rt->rtOneWay) + return; + + fprintf(file, "\n"); + fprintf(file, "#if ( __MigTypeCheck "); + if (CheckNDR) + fprintf(file, "|| __NDR_convert__ "); + fprintf(file, ")\n"); + fprintf(file, "#if __MIG_check__Reply__%s_subsystem__\n", SubsystemName); + fprintf(file, "#if !defined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName); + fprintf(file, "#define __MIG_check__Reply__%s_t__defined\n", rt->rtName); + if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) { + WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgDecl, akbReturnNdr, "\n", "\n"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgDecl, akbReturnNdr, "\n", "\n"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgDecl, akbReturnNdr, "\n", "\n"); + } + fprintf(file, "\n"); + fprintf(file, "mig_internal kern_return_t __MIG_check__Reply__%s_t(__Reply__%s_t *Out0P", rt->rtName, rt->rtName); + for (i = 1; i <= rt->rtMaxReplyPos; i++) + fprintf(file, ", __Reply__%s_t **Out%dPP", rt->rtName, i); + fprintf(file, ")\n{\n"); + + + fprintf(file, "\n\ttypedef __Reply__%s_t __Reply __attribute__((unused));\n", rt->rtName); + for (i = 1; i <= rt->rtMaxReplyPos; i++) + fprintf(file, "\t__Reply *Out%dP;\n", i); + if (!rt->rtSimpleReply) + fprintf(file, "\tboolean_t msgh_simple;\n"); + if (!rt->rtNoReplyArgs) { + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tunsigned int msgh_size;\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + } + if (rt->rtMaxReplyPos > 0) + fprintf(file, "\tunsigned int msgh_size_delta;\n"); + if (rt->rtNumReplyVar > 0 || rt->rtMaxReplyPos > 0) + fprintf(file, "\n"); + + /* Check the values that are returned in the reply message */ + + WriteCheckIdentity(file, rt); + + /* Check the remote port is NULL */ + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\tif (Out0P->Head.msgh_request_port != MACH_PORT_NULL) {\n"); + fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); + + /* If the reply message has no Out parameters or return values + other than the return code, we can type-check it and + return it directly. */ + + if (rt->rtNoReplyArgs && !rt->rtUserImpl) { + if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply) && rt->rtRetCode) + WriteReplyNDRConvertIntRepOneArgUse(file, rt->rtRetCode); + WriteReturn(file, rt, "\t", stRetCode, "\n", FALSE); + } + else { + if (UseEventLogger) + WriteLogMsg(file, rt, LOG_USER, LOG_REPLY); + + WriteRetCodeCheck(file, rt); + + /* Type Checking for the Out parameters which are typed */ + WriteList(file, rt->rtArgs, WriteTypeCheck, akbReturnKPD, "\n", "\n"); + + { + argument_t *arg, *lastVarArg; + + lastVarArg = argNULL; + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + /* + * Advance message pointer if the last reply argument was + * variable-length and the reply position will change. + */ + if (lastVarArg != argNULL && + lastVarArg->argReplyPos < arg->argReplyPos) { + WriteAdjustReplyMsgPtr(file, lastVarArg); + lastVarArg = argNULL; + } + + if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) { + if (akCheck(arg->argKind, akbVariable)) { + WriteCheckMsgSize(file, arg); + lastVarArg = arg; + } + } + } + } + + if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) { + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgCond, akbReturnNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep) {\n"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgUse, akbReturnNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n"); + + WriteOOLSizeCheck(file, rt); + + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgCond, akbReturnNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (Out0P->NDR.char_rep != NDR_record.char_rep) {\n"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgUse, akbReturnNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n"); + + fprintf(file, "#if\t"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgCond, akbReturnNdr, " || \\\n\t", "\n"); + fprintf(file, "\tif (Out0P->NDR.float_rep != NDR_record.float_rep) {\n"); + WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgUse, akbReturnNdr, "", ""); + fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n"); + } else { + WriteOOLSizeCheck(file, rt); + } + fprintf(file, "\treturn MACH_MSG_SUCCESS;\n"); + } + fprintf(file, "}\n"); + fprintf(file, "#endif /* !defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName); + fprintf(file, "#endif /* __MIG_check__Reply__%s_subsystem__ */\n", SubsystemName); + fprintf(file, "#endif /* ( __MigTypeCheck "); + if (CheckNDR) + fprintf(file, "|| __NDR_convert__ "); + fprintf(file, ") */\n\n"); +} + +static void +WriteCheckReplyCall(FILE *file, routine_t *rt) +{ + int i; + + fprintf(file, "\n"); + fprintf(file, "#if\tdefined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName); + fprintf(file, "\tcheck_result = __MIG_check__Reply__%s_t((__Reply__%s_t *)Out0P", rt->rtName, rt->rtName); + for (i = 1; i <= rt->rtMaxReplyPos; i++) + fprintf(file, ", (__Reply__%s_t **)&Out%dP", rt->rtName, i); + fprintf(file, ");\n"); + fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS) {\n"); + if (IsKernelUser) { + fprintf(file, "#if\t__MigKernelSpecificCode\n"); + fprintf(file, "\t\tmach_msg_destroy_from_kernel(&Out0P->Head);\n"); + fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n"); + } else { + fprintf(file, "\t\tmach_msg_destroy(&Out0P->Head);\n"); + } + WriteReturnMsgError(file, rt, TRUE, argNULL, "check_result"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif\t/* defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName); + fprintf(file, "\n"); +} + +void +WriteCheckReplies(FILE *file, statement_t *stats) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) + WriteCheckReply(file, stat->stRoutine); +} + +static void +WriteCheckReplyTrailerArgs(FILE *file, routine_t *rt) +{ + argument_t *arg; + + if (rt->rtUserImpl) + WriteCheckTrailerHead(file, rt, TRUE); + + for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { + if (akCheck(arg->argKind, akbUserImplicit)) + WriteCheckTrailerSize(file, TRUE, arg); + } + if (rt->rtUserImpl) + fprintf(file, "\n"); +} + + +/************************************************************* + * Writes all the code comprising a routine body. Called by + * WriteUser for each routine. + *************************************************************/ +static void +WriteRoutine(FILE *file, routine_t *rt) +{ + /* write the stub's declaration */ + WriteStubDecl(file, rt); + + /* Use the RPC trap for user-user and user-kernel RPC */ + if (UseRPCTrap) + WriteRPCRoutine(file, rt); + + /* write the code for doing a short-circuited RPC: */ + if (ShortCircuit) + WriteShortCircRPC(file, rt); + + /* typedef of structure for Request and Reply messages */ + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, FALSE, FALSE, FALSE); + if (!rt->rtOneWay) { + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply", rt->rtSimpleReply, TRUE, rt->rtUserImpl, FALSE); + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "__Reply", rt->rtSimpleReply, FALSE, FALSE, FALSE); + } + if (rt->rtOverwrite) + WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply|akbOverwrite, "OverwriteTemplate", FALSE, TRUE, FALSE, TRUE); + /* + * Define a Minimal Reply structure to be used in case of errors + */ + fprintf(file, "\t/*\n"); + fprintf(file, "\t * typedef struct {\n"); + fprintf(file, "\t * \tmach_msg_header_t Head;\n"); + fprintf(file, "\t * \tNDR_record_t NDR;\n"); + fprintf(file, "\t * \tkern_return_t RetCode;\n"); + fprintf(file, "\t * } mig_reply_error_t;\n"); + fprintf(file, "\t */\n"); + fprintf(file, "\n"); + + + /* declarations for local vars: Union of Request and Reply messages, + InP, OutP and return value */ + + WriteVarDecls(file, rt); + + /* declarations and initializations of the mach_msg_type_descriptor_t variables + for each argument that is a Kernel Processed Data */ + + WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbRequest | akbSendKPD, "\n", "\n"); + + WriteLimitCheck(file, rt); + WriteRetCodeArg(file, rt); + + /* fill in the fields that are non related to parameters */ + + if (!rt->rtSimpleRequest) + fprintf(file, "\tInP->msgh_body.msgh_descriptor_count = %d;\n", rt->rtRequestKPDs); + + /* fill in all the request message types and then arguments */ + + WriteRequestArgs(file, rt); + + /* fill in request message head */ + + WriteRequestHead(file, rt); + fprintf(file, "\n"); + + /* give the application a chance to do some stuff. */ + WriteApplMacro(file, "Send", "Before", rt); + + /* Write the send/receive or rpc call */ + + if (UseEventLogger) + WriteLogMsg(file, rt, LOG_USER, LOG_REQUEST); + + + if (rt->rtOneWay) { + WriteMsgSend(file, rt); + } + else { + if (UseMsgRPC +#if USE_IMMEDIATE_SEND_TIMEOUT + && (rt->rtWaitTime == argNULL) +#endif + ) { + /* overwrite mode meaningful only when UseMsgRPC is enabled */ + if (rt->rtOverwrite) + WriteOverwriteTemplate(file, rt); + WriteMsgRPC(file, rt); + } + else + WriteMsgSendReceive(file, rt); + + WriteCheckReplyCall(file, rt); + WriteCheckReplyTrailerArgs(file, rt); + + if (UseEventLogger) + WriteLogMsg(file, rt, LOG_USER, LOG_REPLY); + + WriteReplyArgs(file, rt); + } + /* return the return value, if any */ + if (!rt->rtOneWay) // WriteMsgSend() already wrote the 'return' + WriteReturnValue(file, rt); + fprintf(file, "}\n"); +} + +static void +WriteRPCClientFunctions(FILE *file, statement_t *stats) +{ + statement_t *stat; + char *fname; + char *argfmt = "(mach_port_t, char *, mach_msg_type_number_t)"; + + fprintf(file, "#ifdef AUTOTEST\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + fname = stat->stRoutine->rtName; + fprintf(file, "extern void client_%s%s;\n", fname, argfmt); + } + fprintf(file, "function_table_entry %s_client_functions[] =\n", SubsystemName); + fprintf(file, "{\n"); + for (stat = stats; stat != stNULL; stat = stat->stNext) + if (stat->stKind == skRoutine) { + fname = stat->stRoutine->rtName; + fprintf(file, " { \"%s\", client_%s },\n", fname, fname); + } + fprintf(file, " { (char *) 0, (function_ptr_t) 0 }\n"); + fprintf(file, "};\n"); + fprintf(file, "#endif /* AUTOTEST */\n"); +} + +/************************************************************* + * Writes out the xxxUser.c file. Called by mig.c + *************************************************************/ +void +WriteUser(FILE *file, statement_t *stats) +{ + statement_t *stat; + + WriteProlog(file, stats); + if (TestRPCTrap) + WriteRPCClientFunctions(file, stats); + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: + WriteCheckReply(file, stat->stRoutine); + WriteRoutine(file, stat->stRoutine); + break; + + case skImport: + case skUImport: + case skSImport: + case skDImport: + case skIImport: + break; + + default: + fatal("WriteUser(): bad statement_kind_t (%d)", (int) stat->stKind); + } + WriteEpilog(file); +} + +/************************************************************* + * Writes out individual .c user files for each routine. Called by mig.c + *************************************************************/ +void +WriteUserIndividual(statement_t *stats) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skRoutine: { + FILE *file; + char *filename; + + filename = strconcat(UserFilePrefix, strconcat(stat->stRoutine->rtName, ".c")); + file = fopen(filename, "w"); + if (file == NULL) + fatal("fopen(%s): %s", filename, strerror(errno)); + WriteProlog(file, stats); + WriteRoutine(file, stat->stRoutine); + WriteEpilog(file); + fclose(file); + strfree(filename); + } + break; + + case skImport: + case skUImport: + case skSImport: + case skDImport: + case skIImport: + break; + + default: + fatal("WriteUserIndividual(): bad statement_kind_t (%d)", (int) stat->stKind); + } +} diff --git a/bootstrap_cmds/migcom.tproj/utils.c b/bootstrap_cmds/migcom.tproj/utils.c new file mode 100644 index 0000000..7a609a4 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/utils.c @@ -0,0 +1,1043 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include "routine.h" +#include "write.h" +#include "global.h" +#include "utils.h" +#include "error.h" + +extern char *MessFreeRoutine; + +void +WriteIdentificationString(FILE *file) +{ + extern char * GenerationDate; + + fprintf(file, "/*\n"); + fprintf(file, " * IDENTIFICATION:\n"); + fprintf(file, " * stub generated %s", GenerationDate); + fprintf(file, " * with a MiG generated by " MIG_VERSION "\n"); + fprintf(file, " * OPTIONS: \n"); + if (IsKernelUser) + fprintf(file, " *\tKernelUser\n"); + if (IsKernelServer) + fprintf(file, " *\tKernelServer\n"); + if (!UseMsgRPC) + fprintf(file, " *\t-R (no RPC calls)\n"); + fprintf(file, " */\n"); +} + +void +WriteMigExternal(FILE *file) +{ + fprintf(file, "#ifdef\tmig_external\n"); + fprintf(file, "mig_external\n"); + fprintf(file, "#else\n"); + fprintf(file, "extern\n"); + fprintf(file, "#endif\t/* mig_external */\n"); +} + +void +WriteMigInternal(FILE *file) +{ + fprintf(file, "#ifdef\tmig_internal\n"); + fprintf(file, "mig_internal\n"); + fprintf(file, "#else\n"); + fprintf(file, "static\n"); + fprintf(file, "#endif\t/* mig_internal */\n"); +} + +void +WriteImport(FILE *file, string_t filename) +{ + fprintf(file, "#include %s\n", filename); +} + +void +WriteImplImports(FILE *file, statement_t *stats, boolean_t isuser) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skImport: + case skIImport: + WriteImport(file, stat->stFileName); + break; + + case skSImport: + if (!isuser) + WriteImport(file, stat->stFileName); + break; + + case skUImport: + if (isuser) + WriteImport(file, stat->stFileName); + break; + + case skRoutine: + case skDImport: + break; + + default: + fatal("WriteImplImport(): bad statement_kind_t (%d)", (int) stat->stKind); + } +} + +void +WriteRCSDecl(FILE *file, identifier_t name, string_t rcs) +{ + fprintf(file, "#ifndef\tlint\n"); + fprintf(file, "#if\tUseExternRCSId\n"); + fprintf(file, "%s char %s_rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", name, rcs); + fprintf(file, "#else\t/* UseExternRCSId */\n"); + fprintf(file, "static %s char rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", rcs); + fprintf(file, "#endif\t/* UseExternRCSId */\n"); + fprintf(file, "#endif\t/* lint */\n"); + fprintf(file, "\n"); +} + +static void +WriteOneApplDefault(FILE *file, char *word1, char *word2, char *word3) +{ + char buf[50]; + + sprintf(buf, "__%s%s%s", word1, word2, word3); + fprintf(file, "#ifndef\t%s\n", buf); + fprintf(file, "#define\t%s(_NUM_, _NAME_)\n", buf); + fprintf(file, "#endif\t/* %s */\n", buf); + fprintf(file, "\n"); +} + +void +WriteApplDefaults(FILE *file, char *dir) +{ + WriteOneApplDefault(file, "Declare", dir, "Rpc"); + WriteOneApplDefault(file, "Before", dir, "Rpc"); + WriteOneApplDefault(file, "After", dir, "Rpc"); + WriteOneApplDefault(file, "Declare", dir, "Simple"); + WriteOneApplDefault(file, "Before", dir, "Simple"); + WriteOneApplDefault(file, "After", dir, "Simple"); +} + +void +WriteApplMacro(FILE *file, char *dir, char *when, routine_t *rt) +{ + char *what = (rt->rtOneWay) ? "Simple" : "Rpc"; + + fprintf(file, "\t__%s%s%s(%d, \"%s\")\n", when, dir, what, SubsystemBase + rt->rtNumber, rt->rtName); +} + + +void +WriteBogusDefines(FILE *file) +{ + fprintf(file, "#ifndef\tmig_internal\n"); + fprintf(file, "#define\tmig_internal\tstatic __inline__\n"); + fprintf(file, "#endif\t/* mig_internal */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tmig_external\n"); + fprintf(file, "#define mig_external\n"); + fprintf(file, "#endif\t/* mig_external */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if\t!defined(__MigTypeCheck) && defined(TypeCheck)\n"); + fprintf(file, "#define\t__MigTypeCheck\t\tTypeCheck\t/* Legacy setting */\n"); + fprintf(file, "#endif\t/* !defined(__MigTypeCheck) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if\t!defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)\n"); + fprintf(file, "#define\t__MigKernelSpecificCode\t_MIG_KERNEL_SPECIFIC_CODE_\t/* Legacy setting */\n"); + fprintf(file, "#endif\t/* !defined(__MigKernelSpecificCode) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tLimitCheck\n"); + fprintf(file, "#define\tLimitCheck 0\n"); + fprintf(file, "#endif\t/* LimitCheck */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tmin\n"); + fprintf(file, "#define\tmin(a,b) ( ((a) < (b))? (a): (b) )\n"); + fprintf(file, "#endif\t/* min */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if !defined(_WALIGN_)\n"); + fprintf(file, "#define _WALIGN_(x) (((x) + %d) & ~%d)\n", (int)(itWordAlign - 1), (int)(itWordAlign - 1)); + fprintf(file, "#endif /* !defined(_WALIGN_) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if !defined(_WALIGNSZ_)\n"); + fprintf(file, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n"); + fprintf(file, "#endif /* !defined(_WALIGNSZ_) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tUseStaticTemplates\n"); + if (BeAnsiC) { + fprintf(file, "#define\tUseStaticTemplates\t0\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "#define\tUseStaticTemplates\t0\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\n"); + + WriteBogusServerRoutineAnnotationDefine(file); +} + +void +WriteList(FILE *file, argument_t *args, void (*func)(FILE *, argument_t *), u_int mask, char *between, char *after) +{ + argument_t *arg; + boolean_t sawone = FALSE; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) { + if (sawone) + fprintf(file, "%s", between); + sawone = TRUE; + + (*func)(file, arg); + } + + if (sawone) + fprintf(file, "%s", after); +} + + +static boolean_t +WriteReverseListPrim(FILE *file, argument_t *arg, void (*func)(FILE *, argument_t *), u_int mask, char *between) +{ + boolean_t sawone = FALSE; + + if (arg != argNULL) { + sawone = WriteReverseListPrim(file, arg->argNext, func, mask, between); + + if (akCheckAll(arg->argKind, mask)) { + if (sawone) + fprintf(file, "%s", between); + sawone = TRUE; + + (*func)(file, arg); + } + } + + return sawone; +} + +void +WriteReverseList(FILE *file, argument_t *args, void (*func)(FILE *file, argument_t *args), u_int mask, char *between, char *after) +{ + boolean_t sawone; + + sawone = WriteReverseListPrim(file, args, func, mask, between); + + if (sawone) + fprintf(file, "%s", after); +} + +void +WriteNameDecl(FILE *file, argument_t *arg) +{ + fprintf(file, "%s", arg->argVarName); +} + +void +WriteUserVarDecl(FILE *file, argument_t *arg) +{ + boolean_t pointer = (arg->argByReferenceUser ||arg->argType->itNativePointer); + char *ref = (pointer) ? "*" : ""; + char *cnst = ((arg->argFlags & flConst) && + (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || + arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; + + fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itUserType, ref, arg->argVarName); +} + +void +WriteServerVarDecl(FILE *file, argument_t *arg) +{ + char *ref = (arg->argByReferenceServer || + arg->argType->itNativePointer) ? "*" : ""; + char *cnst = ((arg->argFlags & flConst) && + (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || + arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; + + fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itTransType, ref, arg->argVarName); +} + +char * +ReturnTypeStr(routine_t *rt) +{ + return rt->rtRetCode->argType->itUserType; +} + +char * +FetchUserType(ipc_type_t *it) +{ + return it->itUserType; +} + +char * +FetchServerType(ipc_type_t *it) +{ + return it->itServerType; +} + +char * +FetchKPDType(ipc_type_t *it) +{ + return it->itKPDType; +} + +void +WriteTrailerDecl(FILE *file, boolean_t trailer) +{ + if (trailer) + fprintf(file, "\t\tmach_msg_max_trailer_t trailer;\n"); + else + fprintf(file, "\t\tmach_msg_trailer_t trailer;\n"); +} + +void +WriteFieldDeclPrim(FILE *file, argument_t *arg, char *(*tfunc)(ipc_type_t *it)) +{ + ipc_type_t *it = arg->argType; + + if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { + argument_t *count = arg->argCount; + ipc_type_t *btype = it->itElement; + + /* + * Build our own declaration for a varying array: + * use the element type and maximum size specified. + * Note arg->argCount->argMultiplier == btype->itNumber. + */ + /* + * NDR encoded VarStrings requires the offset field. + * Since it is not used, it wasn't worthwhile to create an extra + * parameter + */ + if (it->itString) + fprintf(file, "\t\t%s %sOffset; /* MiG doesn't use it */\n", (*tfunc)(count->argType), arg->argName); + + if (!(arg->argFlags & flSameCount) && !it->itNoOptArray) + /* in these cases we would have a count, which we don't want */ + fprintf(file, "\t\t%s %s;\n", (*tfunc)(count->argType), count->argMsgField); + fprintf(file, "\t\t%s %s[%d];", (*tfunc)(btype), arg->argMsgField, it->itNumber/btype->itNumber); + } + else if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t\t%s %s[%d];", (*tfunc)(it), arg->argMsgField, it->itKPD_Number); + else if (IS_OPTIONAL_NATIVE(it)) { + fprintf(file, "\t\tboolean_t __Present__%s;\n", arg->argMsgField); + fprintf(file, "\t\tunion {\n"); + fprintf(file, "\t\t %s __Real__%s;\n", (*tfunc)(it), arg->argMsgField); + fprintf(file, "\t\t char __Phony__%s[_WALIGNSZ_(%s)];\n", arg->argMsgField, (*tfunc)(it)); + fprintf(file, "\t\t} %s;", arg->argMsgField); + } + else { + /* either simple KPD or simple in-line */ + fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField); + } + + /* Kernel Processed Data has always PadSize = 0 */ + if (it->itPadSize != 0) + fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize); +} + +void +WriteKPDFieldDecl(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbSendKPD) || + akCheck(arg->argKind, akbReturnKPD)) + WriteFieldDeclPrim(file, arg, FetchKPDType); + else + WriteFieldDeclPrim(file, arg, FetchServerType); +} + +void +WriteStructDecl( + FILE *file, + argument_t *args, + void (*func)(FILE *, argument_t *), + u_int mask, + char *name, + boolean_t simple, + boolean_t trailer, + boolean_t trailer_t, + boolean_t template_only) +{ + fprintf(file, "\n#ifdef __MigPackStructs\n#pragma pack(push, %lu)\n#endif\n",sizeof(natural_t)); + fprintf(file, "\ttypedef struct {\n"); + fprintf(file, "\t\tmach_msg_header_t Head;\n"); + if (simple == FALSE) { + fprintf(file, "\t\t/* start of the kernel processed data */\n"); + fprintf(file, "\t\tmach_msg_body_t msgh_body;\n"); + if (mask == akbRequest) + WriteList(file, args, func, mask | akbSendKPD, "\n", "\n"); + else + WriteList(file, args, func, mask | akbReturnKPD, "\n", "\n"); + fprintf(file, "\t\t/* end of the kernel processed data */\n"); + } + if (!template_only) { + if (mask == akbRequest) + WriteList(file, args, func, mask | akbSendBody, "\n", "\n"); + + else + WriteList(file, args, func, mask | akbReturnBody, "\n", "\n"); + if (trailer) + WriteTrailerDecl(file, trailer_t); + } + fprintf(file, "\t} %s __attribute__((unused));\n", name); + fprintf(file, "#ifdef __MigPackStructs\n#pragma pack(pop)\n#endif\n"); +} + +void +WriteTemplateDeclIn(FILE *file, argument_t *arg) +{ + (*arg->argKPD_Template)(file, arg, TRUE); +} + +void +WriteTemplateDeclOut(FILE *file, argument_t *arg) +{ + (*arg->argKPD_Template)(file, arg, FALSE); +} + +void +WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + fprintf(file, "\t\t/* name = */\t\tMACH_PORT_NULL,\n"); + fprintf(file, "\t\t/* pad1 = */\t\t0,\n"); + fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); + fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_PORT_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + if (IS_MULTIPLE_KPD(it)) + it = it->itElement; + + fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); + if (it->itVarArray) + fprintf(file, "\t\t/* size = */\t\t0,\n"); + else + fprintf(file, "\t\t/* size = */\t\t%d,\n", (it->itNumber * it->itSize + 7)/8); + fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + /* the d_MAYBE case will be fixed runtime */ + fprintf(file, "\t\t/* copy = */\t\t%s,\n", (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); + /* the PHYSICAL COPY flag has not been established yet */ + fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + if (IS_MULTIPLE_KPD(it)) + it = it->itElement; + + fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); + if (!it->itVarArray) + fprintf(file, "\t\t/* coun = */\t\t%d,\n", it->itNumber); + else + fprintf(file, "\t\t/* coun = */\t\t0,\n"); + fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t\t/* copy is meaningful only in overwrite mode */\n"); + fprintf(file, "\t\t/* copy = */\t\tMACH_MSG_PHYSICAL_COPY,\n"); + fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_PORTS_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteReplyTypes(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* typedefs for all replies */\n\n"); + fprintf(file, "#ifndef __Reply__%s_subsystem__defined\n", SubsystemName); + fprintf(file, "#define __Reply__%s_subsystem__defined\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + char str[MAX_STR_LEN]; + + rt = stat->stRoutine; + sprintf(str, "__Reply__%s_t", rt->rtName); + WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbReply, str, rt->rtSimpleReply, FALSE, FALSE, FALSE); + } + } + fprintf(file, "#endif /* !__Reply__%s_subsystem__defined */\n", SubsystemName); + fprintf(file, "\n"); +} + +void +WriteRequestTypes(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* typedefs for all requests */\n\n"); + fprintf(file, "#ifndef __Request__%s_subsystem__defined\n", SubsystemName); + fprintf(file, "#define __Request__%s_subsystem__defined\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + char str[MAX_STR_LEN]; + + rt = stat->stRoutine; + sprintf(str, "__Request__%s_t", rt->rtName); + WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbRequest, str, rt->rtSimpleRequest, FALSE, FALSE, FALSE); + } + } + fprintf(file, "#endif /* !__Request__%s_subsystem__defined */\n", SubsystemName); + fprintf(file, "\n"); +} + +void +WriteNDRConvertArgDecl(FILE *file, argument_t *arg, char *convert, char *dir) +{ + argument_t *count = arg->argCount; + argument_t *parent = arg->argParent; + char *carg = (count) ? ", c" : ""; + routine_t *rt = arg->argRoutine; + ipc_type_t *ptype = arg->argType; + ipc_type_t *btype; + int multi, array; + char domain[MAX_STR_LEN]; + + fprintf(file, "#ifndef __NDR_convert__%s__%s__%s_t__%s__defined\n#", convert, dir, rt->rtName, arg->argMsgField); + + for (btype = ptype, multi = (!parent) ? arg->argMultiplier : 1, array = 0; + btype; + ptype = btype, array += ptype->itVarArray, btype = btype->itElement) { + char *bttype; + + if (btype->itNumber < ptype->itNumber && !ptype->itVarArray && !parent) { + multi *= ptype->itNumber / btype->itNumber; + if (!btype->itString) + continue; + } + else if (array && ptype->itVarArray) + continue; + if (btype != ptype) + fprintf(file, "#el"); + + bttype = (multi > 1 && btype->itString) ? "string" : FetchServerType(btype); + sprintf(domain, "__%s", SubsystemName); + do { + fprintf(file, "if\tdefined(__NDR_convert__%s%s__%s__defined)\n", convert, domain, bttype); + fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s__defined\n", convert, dir, rt->rtName, arg->argMsgField); + fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s(a, f%s) \\\n\t", convert, dir, rt->rtName, arg->argMsgField, carg); + if (multi > 1) { + if (array) { + if (btype->itString) + fprintf(file, "__NDR_convert__2DARRAY((%s *)(a), f, %d, c, ", bttype, multi); + else + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d * (c), ", bttype, multi); + } + else if (!btype->itString) + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d, ", bttype, multi); + } + else if (array) + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, c, ", bttype); + fprintf(file, "__NDR_convert__%s%s__%s", convert, domain, bttype); + if (multi > 1) { + if (!array && btype->itString) + fprintf(file, "(a, f, %d", multi); + } + else if (!array) + fprintf(file, "((%s *)(a), f%s", bttype, carg); + fprintf(file, ")\n"); + } while (strcmp(domain, "") && ((void)(domain[0] = '\0'), fprintf(file, "#el"))); + } + fprintf(file, "#endif /* defined(__NDR_convert__*__defined) */\n"); + fprintf(file, "#endif /* __NDR_convert__%s__%s__%s_t__%s__defined */\n\n", convert, dir, rt->rtName, arg->argMsgField); +} + +/* + * Like vfprintf, but omits a leading comment in the format string + * and skips the items that would be printed by it. Only %s, %d, + * and %f are recognized. + */ +void +SkipVFPrintf(FILE *file, char *fmt, va_list pvar) +{ + if (*fmt == 0) + return; /* degenerate case */ + + if (fmt[0] == '/' && fmt[1] == '*') { + /* Format string begins with C comment. Scan format + string until end-comment delimiter, skipping the + items in pvar that the enclosed format items would + print. */ + + int c; + + fmt += 2; + for (;;) { + c = *fmt++; + if (c == 0) + return; /* nothing to format */ + if (c == '*') { + if (*fmt == '/') { + break; + } + } + else if (c == '%') { + /* Field to skip */ + c = *fmt++; + switch (c) { + + case 's': + (void) va_arg(pvar, char *); + break; + + case 'd': + (void) va_arg(pvar, int); + break; + + case 'f': + (void) va_arg(pvar, double); + break; + + case '\0': + return; /* error - fmt ends with '%' */ + + default: + break; + } + } + } + /* End of comment. To be pretty, skip + the space that follows. */ + fmt++; + if (*fmt == ' ') + fmt++; + } + + /* Now format the string. */ + (void) vfprintf(file, fmt, pvar); +} + +static void +vWriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, va_list pvar) +{ + va_list pvar2; + va_copy(pvar2, pvar); + + if (it->itStruct) { + + fprintf(file, "\t"); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, " = "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ";\n"); + } + else if (it->itString) { + va_list pvar3, pvar4; + va_copy(pvar3, pvar); + va_copy(pvar4, pvar); + + if (mig_allocated_buf) { + /* + * zero-fill MIG allocated buffers: we control the size so there's + * no risk of buffer overrun, and we avoid leaking process/kernel + * memory on the copy-out + */ + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n"); + fprintf(file, "\t\t(void) mig_strncpy_zerofill("); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, ", "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ", %d);\n", it->itTypeSize); + fprintf(file, "\t} else {\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n\t"); + } + fprintf(file, "\t(void) mig_strncpy("); + + (void) SkipVFPrintf(file, left, pvar3); + fprintf(file, ", "); + (void) SkipVFPrintf(file, right, pvar4); + fprintf(file, ", %d);\n", it->itTypeSize); + + if (mig_allocated_buf) { + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + } + + va_end(pvar3); + va_end(pvar4); + } + else { + fprintf(file, "\t{ typedef struct { char data[%d]; } *sp;\n", it->itTypeSize); + fprintf(file, "\t * (sp) "); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, " = * (sp) "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ";\n\t}\n"); + } + + va_end(pvar2); +} + + +/*ARGSUSED*/ +/*VARARGS4*/ +void +WriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, ...) +{ + va_list pvar; + va_start(pvar, right); + + vWriteCopyType(file, it, mig_allocated_buf, left, right, pvar); + + va_end(pvar); +} + + +/*ARGSUSED*/ +/*VARARGS4*/ +void +WriteCopyArg(FILE *file, argument_t *arg, boolean_t mig_allocated_buf, char *left, char *right, ...) +{ + va_list pvar; + va_start(pvar, right); + + { + ipc_type_t *it = arg->argType; + if (it->itVarArray && !it->itString) { + fprintf(file, "\t (void)memcpy("); + (void) SkipVFPrintf(file, left, pvar); + va_end(pvar); + fprintf(file, ", "); + va_start(pvar, right); + (void) SkipVFPrintf(file, right, pvar); + fprintf(file, ", %s);\n", arg->argCount->argVarName); + } + else + vWriteCopyType(file, it, mig_allocated_buf, left, right, pvar); + } + + va_end(pvar); +} + + +/* + * Global KPD disciplines + */ +void +KPD_error(FILE *file, argument_t *arg) +{ + printf("MiG internal error: argument is %s\n", arg->argVarName); + exit(1); +} + +void +KPD_noop(FILE *file, argument_t *arg) +{ + /* Nothing to see here, people. Move it along... */ +} + +static void +WriteStringDynArgs(argument_t *args, u_int mask, string_t InPOutP, string_t *str_oolports, string_t *str_ool) +{ + argument_t *arg; + char loc[100], sub[20]; + string_t tmp_str1 = ""; + string_t tmp_str2 = ""; + int cnt, multiplier = 1; + boolean_t test, complex = FALSE; + + for (arg = args; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if (IS_MULTIPLE_KPD(it)) { + test = it->itVarArray || it->itElement->itVarArray; + if (test) { + multiplier = it->itKPD_Number; + it = it->itElement; + complex = TRUE; + } + } + else + test = it->itVarArray; + + cnt = multiplier; + while (cnt) { + if (complex) + sprintf(sub, "[%d]", multiplier - cnt); + if (akCheck(arg->argKind, mask) && + it->itPortType && !it->itInLine && test) { + sprintf(loc, " + %s->%s%s.count", InPOutP, arg->argMsgField, complex ? sub : ""); + tmp_str1 = strconcat(tmp_str1, loc); + } + if (akCheck(arg->argKind, mask) && + !it->itInLine && !it->itPortType && test) { + sprintf(loc, " + %s->%s%s.size", InPOutP, arg->argMsgField, complex ? sub : ""); + tmp_str2 = strconcat(tmp_str2, loc); + } + cnt--; + } + } + *str_oolports = tmp_str1; + *str_ool = tmp_str2; +} + +/* + * Utilities for Logging Events that happen at the stub level + */ +void +WriteLogMsg(FILE *file, routine_t *rt, int where, int what) +{ + string_t ptr_str; + string_t StringOolPorts = strNULL; + string_t StringOOL = strNULL; + u_int ports, oolports, ool; + string_t event; + + fprintf(file, "\n#if MIG_DEBUG\n"); + if (where == LOG_USER) + fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_USER,\n"); + else + fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_SERVER,\n"); + if (where == LOG_USER && what == LOG_REQUEST) { + ptr_str = "InP"; + event = "MACH_MSG_REQUEST_BEING_SENT"; + } + else if (where == LOG_USER && what == LOG_REPLY) { + ptr_str = "Out0P"; + event = "MACH_MSG_REPLY_BEING_RCVD"; + } + else if (where == LOG_SERVER && what == LOG_REQUEST) { + ptr_str = "In0P"; + event = "MACH_MSG_REQUEST_BEING_RCVD"; + } + else { + ptr_str = "OutP"; + event = "MACH_MSG_REPLY_BEING_SENT"; + } + WriteStringDynArgs(rt->rtArgs, (what == LOG_REQUEST) ? akbSendKPD : akbReturnKPD, ptr_str, &StringOolPorts, &StringOOL); + fprintf(file, "\t\t%s,\n", event); + fprintf(file, "\t\t%s->Head.msgh_id,\n", ptr_str); + if (where == LOG_USER && what == LOG_REQUEST) { + if (rt->rtNumRequestVar) + fprintf(file, "\t\tmsgh_size,\n"); + else + fprintf(file, "\t\t(mach_msg_size_t)sizeof(Request),\n"); + } + else + fprintf(file, "\t\t%s->Head.msgh_size,\n", ptr_str); + if ((what == LOG_REQUEST && rt->rtSimpleRequest == FALSE) || + (what == LOG_REPLY && rt->rtSimpleReply == FALSE)) + fprintf(file, "\t\t%s->msgh_body.msgh_descriptor_count,\n", ptr_str); + else + fprintf(file, "\t\t0, /* Kernel Proc. Data entries */\n"); + if (what == LOG_REQUEST) { + fprintf(file, "\t\t0, /* RetCode */\n"); + ports = rt->rtCountPortsIn; + oolports = rt->rtCountOolPortsIn; + ool = rt->rtCountOolIn; + } + else { + if (akCheck(rt->rtRetCode->argKind, akbReply)) + fprintf(file, "\t\t%s->RetCode,\n", ptr_str); + else + fprintf(file, "\t\t0, /* RetCode */\n"); + ports = rt->rtCountPortsOut; + oolports = rt->rtCountOolPortsOut; + ool = rt->rtCountOolOut; + } + fprintf(file, "\t\t/* Ports */\n"); + fprintf(file, "\t\t%d,\n", ports); + fprintf(file, "\t\t/* Out-of-Line Ports */\n"); + fprintf(file, "\t\t%d", oolports); + if (StringOolPorts != strNULL) + fprintf(file, "%s,\n", StringOolPorts); + else + fprintf(file, ",\n"); + fprintf(file, "\t\t/* Out-of-Line Bytes */\n"); + fprintf(file, "\t\t%d", ool); + if (StringOOL != strNULL) + fprintf(file, "%s,\n", StringOOL); + else + fprintf(file, ",\n"); + fprintf(file, "\t\t__FILE__, __LINE__);\n"); + fprintf(file, "#endif /* MIG_DEBUG */\n\n"); +} + +void +WriteLogDefines(FILE *file, string_t who) +{ + fprintf(file, "#if MIG_DEBUG\n"); + fprintf(file, "#define LOG_W_E(X)\tLOG_ERRORS(%s, \\\n", who); + fprintf(file, "\t\t\tMACH_MSG_ERROR_WHILE_PARSING, (void *)(X), __FILE__, __LINE__)\n"); + fprintf(file, "#else /* MIG_DEBUG */\n"); + fprintf(file, "#define LOG_W_E(X)\n"); + fprintf(file, "#endif /* MIG_DEBUG */\n"); + fprintf(file, "\n"); +} + +/* common utility to report errors */ +void +WriteReturnMsgError(FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error) +{ + char space[MAX_STR_LEN]; + string_t string = &space[0]; + + if (UseEventLogger && arg != argNULL) + sprintf(string, "LOG_W_E(\"%s\"); ", arg->argVarName); + else + string = ""; + + fprintf(file, "\t\t{ "); + + if (isuser) { + if (! rtMessOnStack(rt)) + fprintf(file, "%s((char *) Mess, (mach_msg_size_t)sizeof(*Mess)); ", MessFreeRoutine); + + fprintf(file, "%sreturn %s; }\n", string, error); + } + else + fprintf(file, "%sMIG_RETURN_ERROR(OutP, %s); }\n", string, error); +} + +/* executed iff elements are defined */ +void +WriteCheckTrailerHead(FILE *file, routine_t *rt, boolean_t isuser) +{ + string_t who = (isuser) ? "Out0P" : "In0P"; + + fprintf(file, "\tTrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)%s +\n", who); + fprintf(file, "\t\tround_msg(%s->Head.msgh_size));\n", who); + fprintf(file, "\tif (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, MIG_TRAILER_ERROR); }\n", who); + + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\ttrailer_size = TrailerP->msgh_trailer_size -\n"); + fprintf(file, "\t\t(mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t));\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + +/* executed iff elements are defined */ +void +WriteCheckTrailerSize(FILE *file, boolean_t isuser, argument_t *arg) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + if (akIdent(arg->argKind) == akeMsgSeqno) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_port_seqno_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_port_seqno_t);\n"); + } + else if (akIdent(arg->argKind) == akeSecToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(security_token_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(security_token_t);\n"); + } + else if (akIdent(arg->argKind) == akeAuditToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(audit_token_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(audit_token_t);\n"); + } + else if (akIdent(arg->argKind) == akeContextToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_vm_address_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_vm_address_t);\n"); + } + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + diff --git a/bootstrap_cmds/migcom.tproj/utils.h b/bootstrap_cmds/migcom.tproj/utils.h new file mode 100644 index 0000000..a804920 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/utils.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1999-2002, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University + * Created. + */ + +#ifndef _UTILS_H +#define _UTILS_H + +/* definitions used by the Event Logger */ + +#define LOG_USER 0 +#define LOG_SERVER 1 + +#define LOG_REQUEST 0 +#define LOG_REPLY 1 + +/* stuff used by more than one of header.c, user.c, server.c */ + +extern void WriteMigExternal(FILE *file); +extern void WriteMigInternal(FILE *file); + +extern void WriteImport(FILE *file, string_t filename); +extern void WriteRCSDecl( FILE *file, identifier_t name, string_t rcs ); +extern void WriteBogusDefines( FILE *file ); + +extern void WriteList( FILE *file, argument_t *args, + void (*func)(FILE *file, argument_t *arg), + u_int mask, char *between, char *after ); + +extern void WriteReverseList( FILE *file, argument_t *args, + void (*func)(FILE *file, argument_t *arg), + u_int mask, char *between, char *after ); + +/* good as arguments to WriteList */ +extern void WriteNameDecl( FILE *file, argument_t *arg ); +extern void WriteUserVarDecl( FILE *file, argument_t *arg ); +extern void WriteServerVarDecl( FILE *file, argument_t *arg ); +extern void WriteTemplateDeclIn( FILE *file, argument_t *arg ); +extern void WriteTemplateDeclOut( FILE *file, argument_t *arg ); +extern void WriteCheckDecl( FILE *file, argument_t *arg ); + +extern char *ReturnTypeStr( routine_t *rt ); + +extern char *FetchUserType( ipc_type_t *it ); +extern char *FetchServerType( ipc_type_t *it ); +extern char *FetchKPDType( ipc_type_t *it ); +extern void WriteKPDFieldDecl(FILE *file, argument_t *arg); + +extern void WriteFieldDeclPrim( FILE *file, argument_t *arg, char *(*tfunc)(ipc_type_t *it) ); + +extern void WriteStructDecl( FILE *file, argument_t *args, + void (*func)(FILE *file, argument_t *arg), + u_int mask, char *name, + boolean_t simple, boolean_t trailer, + boolean_t isuser, + boolean_t template_only ); + +extern void WriteStaticDecl( FILE *file, argument_t *arg ); + +extern void WriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, ...); + +extern void WriteCopyArg(FILE *file, argument_t *arg, boolean_t mig_allocated_buf, char *left, char *right, ...); + +extern void WriteLogMsg( FILE *file, routine_t *rt, int where, int what ); + +extern void WriteCheckTrailerHead( FILE *file, routine_t *rt, boolean_t isuser ); + +extern void WriteCheckTrailerSize( FILE *file, boolean_t isuser, argument_t *arg ); + +extern void WriteReturnMsgError( FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error ); + +extern void WriteRPCRoutineDescriptor( FILE *file, routine_t *rt, int arg_count, int descr_count, string_t stub_routine, string_t sig_array ); + +extern void WriteRPCRoutineArgDescriptor( FILE *file, routine_t *rt ); + +extern void WriteRequestTypes( FILE *file, statement_t *stats); +extern void WriteCheckRequests( FILE *file, statement_t *stats); +extern void WriteUserRequestUnion( FILE *file, statement_t *stats ); +extern void WriteServerRequestUnion( FILE *file, statement_t *stats ); + +extern void WriteReplyTypes( FILE *file, statement_t *stats); +extern void WriteCheckReplies( FILE *file, statement_t *stats); +extern void WriteUserReplyUnion( FILE *file, statement_t *stats ); +extern void WriteServerReplyUnion( FILE *file, statement_t *stats ); + +extern void WriteNDRConvertArgDecl( FILE *file, argument_t *arg, char *convert, char *dir); + +#endif /* _UTILS_H */ diff --git a/bootstrap_cmds/migcom.tproj/write.h b/bootstrap_cmds/migcom.tproj/write.h new file mode 100644 index 0000000..0e935aa --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/write.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University + * Extensive revamping. Added polymorphic arguments. + * Allow multiple variable-sized inline arguments in messages. + * + * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University + * Created. + */ + +#ifndef _WRITE_H +#define _WRITE_H + +#include +#include "statement.h" + +extern void WriteUserHeader( FILE *file, statement_t *stats ); +extern void WriteServerHeader( FILE *file, statement_t *stats ); +extern void WriteServerRoutine( FILE *file, routine_t *rt ); +extern void WriteInternalHeader( FILE *file, statement_t *stats ); +extern void WriteDefinesHeader( FILE *file, statement_t *stats ); +extern void WriteUser( FILE *file, statement_t *stats ); +extern void WriteUserIndividual( statement_t *stats ); +extern void WriteServer( FILE *file, statement_t *stats ); +extern void WriteIncludes( FILE *file, boolean_t isuser, boolean_t is_def ); +extern void WriteImplImports( FILE *file, statement_t *stats, boolean_t isuser ); +extern void WriteApplDefaults( FILE *file, char *dir ); +extern void WriteApplMacro( FILE *file, char *dir, char *when, routine_t *rt ); +extern void WriteBogusServerRoutineAnnotationDefine( FILE *file ); + +#endif /* _WRITE_H */ diff --git a/bootstrap_cmds/xcodescripts/install-mig.sh b/bootstrap_cmds/xcodescripts/install-mig.sh new file mode 100644 index 0000000..f0f742e --- /dev/null +++ b/bootstrap_cmds/xcodescripts/install-mig.sh @@ -0,0 +1,8 @@ +set -e -x + +BINDIR="$DSTROOT/$DT_TOOLCHAIN_DIR/usr/bin" + +install -d -o root -g wheel -m 0755 "$BINDIR" +install -c -o root -g wheel -m 0755 \ + "$PROJECT_DIR/migcom.tproj/mig.sh" \ + "$BINDIR"/mig diff --git a/developer_cmds/asa/asa.1 b/developer_cmds/asa/asa.1 new file mode 100644 index 0000000..4c388a0 --- /dev/null +++ b/developer_cmds/asa/asa.1 @@ -0,0 +1,85 @@ +.\" $NetBSD: asa.1,v 1.5 1997/09/20 14:55:00 lukem Exp $ +.\" +.\" 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. +.\" +.Dd September 23, 1993 +.Dt ASA 1 +.Os +.Sh NAME +.Nm asa +.Nd interpret carriage-control characters. +.Sh SYNOPSIS +.Nm +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility reads files sequentially, mapping +.Tn FORTRAN +carriage-control characters to line-printer control sequences, +and writes them to the standard output. +.Pp +The first character of each line is interpreted as a carriage-control +character. The following characters are interpreted as follows: +.Bl -tag -width "" +.It +Output the rest of the line without change. +.It 0 +Output a character before printing the rest of the line. +.It 1 +Output a character before printing the rest of the line. +.It + +The trailing of the previous line is replaced by a +before printing the rest of the line. +.El +.Pp +Lines beginning with characters other than the above are treated as if they +begin with . +.Sh EXAMPLES +To view a file containing the output of a +.Tn FORTRAN program: +.Dl asa file +.Pp +To format the output of a +.Tn FORTRAN +program and redirect it to a line-printer. +.Dl a.out | asa | lpr +.Sh DIAGNOSTICS +The +.Nm +utility exit 0 on success, and >0 if an error occurs. +.Sh SEE ALSO +.Xr f77 1 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.2-92 . +.Sh AUTHORS +J.T. Conklin, Winning Strategies, Inc. diff --git a/developer_cmds/asa/asa.c b/developer_cmds/asa/asa.c new file mode 100644 index 0000000..9516a45 --- /dev/null +++ b/developer_cmds/asa/asa.c @@ -0,0 +1,131 @@ +/* $NetBSD: asa.c,v 1.11 1997/09/20 14:55:00 lukem Exp $ */ + +/* + * Copyright (c) 1993,94 Winning Strategies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Winning Strategies, Inc. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: asa.c,v 1.11 1997/09/20 14:55:00 lukem Exp $"); +#endif + +#include +#include +#include +#include + +static void asa __P((FILE *)); +int main __P((int, char *[])); + +int main(int argc, char **argv) +{ + FILE *fp; + int exit_val = 0; + /* skip progname */ + argv++; + + if (*argv && !strcmp(*argv, "--")) { + argv++; + argc--; + } + + if (argc == 1) { + asa(stdin); + exit(exit_val); + } + + do { + if (*argv) { + if (!(fp = fopen(*argv, "r"))) { + warn ("%s", *argv); + exit_val = 1; + continue; + } else { + asa(fp); + (void)fclose(fp); + } + } + } while (*argv++); + + exit (exit_val); +} + +static void +asa(f) + FILE *f; +{ + char *buf; + size_t len; + + if ((buf = fgetln (f, &len)) != NULL) { + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + /* special case the first line */ + switch (buf[0]) { + case '0': + putchar ('\n'); + break; + case '1': + putchar ('\f'); + break; + } + + if (len > 1 && buf[0] && buf[1]) { + printf("%.*s", (int)(len - 1), buf + 1); + } + + while ((buf = fgetln(f, &len)) != NULL) { + if (buf[len - 1] == '\n') + buf[--len] = '\0'; + switch (buf[0]) { + default: + case ' ': + putchar ('\n'); + break; + case '0': + putchar ('\n'); + putchar ('\n'); + break; + case '1': + putchar ('\n'); + putchar ('\f'); + break; + case '+': + putchar ('\r'); + break; + } + + if (len > 1 && buf[0] && buf[1]) { + printf("%.*s", (int)(len - 1), buf + 1); + } + } + + putchar ('\n'); + } +} diff --git a/developer_cmds/ctags/C.c b/developer_cmds/ctags/C.c new file mode 100644 index 0000000..c99d617 --- /dev/null +++ b/developer_cmds/ctags/C.c @@ -0,0 +1,555 @@ +/* $NetBSD: C.c,v 1.5 1998/07/24 07:30:08 ross Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)C.c 8.4 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: C.c,v 1.5 1998/07/24 07:30:08 ross Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include + +#include "ctags.h" + +static int func_entry __P((void)); +static void hash_entry __P((void)); +static void skip_string __P((int)); +static int str_entry __P((int)); + +/* + * c_entries -- + * read .c and .h files and call appropriate routines + */ +void +c_entries() +{ + int c; /* current character */ + int level; /* brace level */ + int token; /* if reading a token */ + int t_def; /* if reading a typedef */ + int t_level; /* typedef's brace level */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* token buffer */ + + lineftell = ftell(inf); + sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1; + while (GETC(!=, EOF)) { + switch (c) { + /* + * Here's where it DOESN'T handle: { + * foo(a) + * { + * #ifdef notdef + * } + * #endif + * if (a) + * puts("hello, world"); + * } + */ + case '{': + ++level; + goto endtok; + case '}': + /* + * if level goes below zero, try and fix + * it, even though we've already messed up + */ + if (--level < 0) + level = 0; + goto endtok; + + case '\n': + SETLINE; + /* + * the above 3 cases are similar in that they + * are special characters that also end tokens. + */ + endtok: if (sp > tok) { + *sp = EOS; + token = YES; + sp = tok; + } + else + token = NO; + continue; + + /* + * We ignore quoted strings and character constants + * completely. + */ + case '"': + case '\'': + (void)skip_string(c); + break; + + /* + * comments can be fun; note the state is unchanged after + * return, in case we found: + * "foo() XX comment XX { int bar; }" + */ + case '/': + if (GETC(==, '*')) { + skip_comment(); + continue; + } + (void)ungetc(c, inf); + c = '/'; + goto storec; + + /* hash marks flag #define's. */ + case '#': + if (sp == tok) { + hash_entry(); + break; + } + goto storec; + + /* + * if we have a current token, parenthesis on + * level zero indicates a function. + */ + case '(': + if (!level && token) { + int curline; + + if (sp != tok) + *sp = EOS; + /* + * grab the line immediately, we may + * already be wrong, for example, + * foo\n + * (arg1, + */ + ct_getline(); + curline = lineno; + if (func_entry()) { + ++level; + pfnote(tok, curline); + } + break; + } + goto storec; + + /* + * semi-colons indicate the end of a typedef; if we find a + * typedef we search for the next semi-colon of the same + * level as the typedef. Ignoring "structs", they are + * tricky, since you can find: + * + * "typedef long time_t;" + * "typedef unsigned int u_int;" + * "typedef unsigned int u_int [10];" + * + * If looking at a typedef, we save a copy of the last token + * found. Then, when we find the ';' we take the current + * token if it starts with a valid token name, else we take + * the one we saved. There's probably some reasonable + * alternative to this... + */ + case ';': + if (t_def && level == t_level) { + t_def = NO; + ct_getline(); + if (sp != tok) + *sp = EOS; + pfnote(tok, lineno); + break; + } + goto storec; + + /* + * store characters until one that can't be part of a token + * comes along; check the current token against certain + * reserved words. + */ + default: + storec: if (!intoken(c)) { + if (sp == tok) + break; + *sp = EOS; + if (tflag) { + /* no typedefs inside typedefs */ + if (!t_def && + !memcmp(tok, "typedef",8)) { + t_def = YES; + t_level = level; + break; + } + /* catch "typedef struct" */ + if ((!t_def || t_level < level) + && (!memcmp(tok, "struct", 7) + || !memcmp(tok, "union", 6) + || !memcmp(tok, "enum", 5))) { + /* + * get line immediately; + * may change before '{' + */ + ct_getline(); + if (str_entry(c)) + ++level; + break; + /* } */ + } + } + sp = tok; + } + else if (sp != tok || begtoken(c)) { + *sp++ = c; + token = YES; + } + continue; + } + + sp = tok; + token = NO; + } +} + +/* + * func_entry -- + * handle a function reference + */ +static int +func_entry() +{ + int c; /* current character */ + int level = 0; /* for matching '()' */ + static char attribute[] = "__attribute__"; + char maybe_attribute[sizeof attribute + 1], + *anext; + + /* + * Find the end of the assumed function declaration. + * Note that ANSI C functions can have type definitions so keep + * track of the parentheses nesting level. + */ + while (GETC(!=, EOF)) { + switch (c) { + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) + skip_comment(); + break; + case '(': + level++; + break; + case ')': + if (level == 0) + goto fnd; + level--; + break; + case '\n': + SETLINE; + } + } + return (NO); +fnd: + /* + * we assume that the character after a function's right paren + * is a token character if it's a function and a non-token + * character if it's a declaration. Comments don't count... + */ + for (anext = maybe_attribute;;) { + while (GETC(!=, EOF) && iswhite(c)) + if (c == '\n') + SETLINE; + if (c == EOF) + return NO; + /* + * Recognize the gnu __attribute__ extension, which would + * otherwise make the heuristic test DTWT + */ + if (anext == maybe_attribute) { + if (intoken(c)) { + *anext++ = c; + continue; + } + } else { + if (intoken(c)) { + if (anext - maybe_attribute + < (int)(sizeof attribute - 1)) + *anext++ = c; + else break; + continue; + } else { + *anext++ = '\0'; + if (strcmp(maybe_attribute, attribute) == 0) { + (void)ungetc(c, inf); + return NO; + } + break; + } + } + if (intoken(c) || c == '{') + break; + if (c == '/' && GETC(==, '*')) + skip_comment(); + else { /* don't ever "read" '/' */ + (void)ungetc(c, inf); + return (NO); + } + } + if (c != '{') + (void)skip_key('{'); + return (YES); +} + +/* + * hash_entry -- + * handle a line starting with a '#' + */ +static void +hash_entry() +{ + int c; /* character read */ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* storage buffer */ + + curline = lineno; + for (sp = tok;;) { /* get next token */ + if (GETC(==, EOF)) + return; + if (iswhite(c)) + break; + *sp++ = c; + } + *sp = EOS; + if (memcmp(tok, "define", 6)) /* only interested in #define's */ + goto skip; + for (;;) { /* this doesn't handle "#define \n" */ + if (GETC(==, EOF)) + return; + if (!iswhite(c)) + break; + } + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return; + /* + * this is where it DOESN'T handle + * "#define \n" + */ + if (!intoken(c)) + break; + } + *sp = EOS; + if (dflag || c == '(') { /* only want macros */ + ct_getline(); + pfnote(tok, curline); + } +skip: if (c == '\n') { /* get rid of rest of define */ + SETLINE + if (*(sp - 1) != '\\') + return; + } + (void)skip_key('\n'); +} + +/* + * str_entry -- + * handle a struct, union or enum entry + */ +static int +str_entry(c) + int c; /* current character */ +{ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[LINE_MAX]; /* storage buffer */ + + curline = lineno; + while (iswhite(c)) + if (GETC(==, EOF)) + return (NO); + if (c == '{') /* it was "struct {" */ + return (YES); + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return (NO); + if (!intoken(c)) + break; + } + + switch (c) { + case '{': /* it was "struct foo{" */ + --sp; + break; + case '\n': /* it was "struct foo\n" */ + SETLINE; + if(GETC(!=, '/')) + { + while (GETC(!=, EOF)) + if (!iswhite(c)) + break; + if (c != '{') { + (void)ungetc(c, inf); + return (NO); + } + break; + } + case '/': + /* skip comments */ + if (GETC(==, '*')) { + skip_comment(); + } + /*FALLTHROUGH*/ + default: /* probably "struct foo " */ + while (GETC(!=, EOF)) + if (!iswhite(c)) + break; + if (c != '{') { + (void)ungetc(c, inf); + return (NO); + } + } + *sp = EOS; + pfnote(tok, curline); + return (YES); +} + +/* + * skip_comment -- + * skip over comment + */ +void +skip_comment() +{ + int c; /* character read */ + int star; /* '*' flag */ + + for (star = 0; GETC(!=, EOF);) + switch(c) { + /* comments don't nest, nor can they be escaped. */ + case '*': + star = YES; + break; + case '/': + if (star) + return; + break; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + star = NO; + break; + } +} + +/* + * skip_string -- + * skip to the end of a string or character constant. + */ +void +skip_string(key) + int key; +{ + int c, + skip; + + for (skip = NO; GETC(!=, EOF); ) + switch (c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + if (c == key && !skip) + return; + skip = NO; + } +} + +/* + * skip_key -- + * skip to next char "key" + */ +int +skip_key(key) + int key; +{ + int c, + skip, + retval; + + for (skip = retval = NO; GETC(!=, EOF);) + switch(c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; + case ';': /* special case for yacc; if one */ + case '|': /* of these chars occurs, we may */ + retval = YES; /* have moved out of the rule */ + break; /* not used by C */ + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) { + skip_comment(); + break; + } + (void)ungetc(c, inf); + c = '/'; + goto norm; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + norm: + if (c == key && !skip) + return (retval); + skip = NO; + } + return (retval); +} diff --git a/developer_cmds/ctags/ctags.1 b/developer_cmds/ctags/ctags.1 new file mode 100644 index 0000000..353c990 --- /dev/null +++ b/developer_cmds/ctags/ctags.1 @@ -0,0 +1,221 @@ +.\" $NetBSD: ctags.1,v 1.5 1997/10/18 13:18:24 lukem Exp $ +.\" +.\" Copyright (c) 1987, 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. +.\" +.\" @(#)ctags.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt CTAGS 1 +.Os BSD 4 +.Sh NAME +.Nm ctags +.Nd create a tags file +.Sh SYNOPSIS +.Nm +.Op Fl BFadtuwvx +.Op Fl f Ar tags_file +.Ar name ... +.Sh DESCRIPTION +.Nm +makes a tags file for +.Xr ex 1 +from the specified C, +Pascal, Fortran, +.Tn YACC , +lex, and lisp sources. +A tags file gives the locations of specified objects in a group of files. +Each line of the tags file contains the object name, the file in which it +is defined, and a search pattern for the object definition, separated by +white-space. +.Pp +Using the +.Ar tags +file, +.Xr ex 1 +can quickly locate these object definitions. +Depending upon the options provided to +.Nm , +objects will consist of subroutines, typedefs, defines, structs, +enums, and unions. +.Bl -tag -width Ds +.It Fl a +append to +.Ar tags +file. +.It Fl B +use backward searching patterns +.Pq Li ?...? . +.It Fl d +create tags for +.Li #defines +that don't take arguments; +.Li #defines +that take arguments are tagged automatically. +.It Fl F +use forward searching patterns +.Pq Li /.../ +(the default). +.It Fl f +Places the tag descriptions in a file called +.Ar tags_file . +The default behavior is to place them in a file called +.Ar tags . +.It Fl t +create tags for typedefs, structs, unions, and enums. +.It Fl u +update the specified files in the +.Ar tags +file, that is, all +references to them are deleted, and the new values are appended to the +file. (Beware: this option is implemented in a way which is rather +slow; it is usually faster to simply rebuild the +.Ar tags +file.) +.It Fl v +An index of the form expected by +.Xr vgrind 1 +is produced on the standard output. This listing +contains the object name, file name, and page number (assuming 64-line pages). +Because the output will be sorted into lexicographic order, +it may be desirable to run the output through +.Xr sort 1 . +Sample use: +.Bd -literal -offset indent +ctags \-v files \&| sort \-f > index +vgrind \-x index +.Ed +.It Fl w +suppress warning diagnostics. +.It Fl x +.Nm +produces a list of object +names, the line number and file name on which each is defined, as well +as the text of that line and prints this on the standard output. This +is a simple function index which can be printed out for reading off-line. +.El +.Pp +Files whose names end in +.Sq \&.c +or +.Sq \&.h +are assumed to be C +source files and are searched for C style routine and macro definitions. +Files whose names end in +.Sq \&.y +are assumed to be +.Tn YACC +source files. +Files whose names end in +.Sq \&.l +are assumed to be lisp files if their +first non-blank character is `;', `(', or `[', +otherwise, they are treated +as lex files. Other files are first examined to see if they +contain any Pascal or Fortran routine definitions; if not, they are +searched for C-style definitions. +.Pp +The tag +.Li main +is treated specially in C programs. The tag formed +is created by prepending +.Ar M +to the name of the file, with the +trailing +.Sq \&.c +and any leading pathname components removed. This +makes use of +.Nm +practical in directories with more than one +program. +.Pp +Yacc and lex files each have a special tag. +.Ar Yyparse +is the start +of the second section of the yacc file, and +.Ar yylex +is the start of +the second section of the lex file. +.Sh FILES +.Bl -tag -width tagsxxx -compact +.It Pa tags +default output tags file +.El +.Sh DIAGNOSTICS +.Nm +exits with a value of 1 if an error occurred, 0 otherwise. +Duplicate objects are not considered to be errors. +.Sh SEE ALSO +.Xr cc 1 , +.Xr ex 1 , +.Xr lex 1 , +.Xr sort 1 , +.\" .Xr vgrind 1 , +.Xr vi 1 , +.Xr yacc 1 +.Sh BUGS +Recognition of +.Em functions , +.Em subroutines , +and +.Em procedures +for +.Tn FORTRAN +and Pascal is done in a very simple-minded way. No attempt +is made to deal with block structure; if you have Pascal procedures +with the same name in different blocks, you lose. +.Nm +doesn't +understand about Pascal types. +.Pp +The method of deciding whether to look for C, Pascal, or +.Tn FORTRAN +functions is a hack. +.Pp +.Nm +relies on the input being well formed, so any syntactical +errors will completely confuse it. It also finds some legal syntax +to be confusing; for example, because it doesn't understand +.Li #ifdef Ns 's +(incidentally, that's a feature, not a bug), any code with unbalanced +braces inside +.Li #ifdef Ns 's +will cause it to become somewhat disoriented. +In a similar fashion, multiple line changes within a definition will +cause it to enter the last line of the object, rather than the first, as +the searching pattern. The last line of multiple line +.Li typedef Ns 's +will similarly be noted. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/developer_cmds/ctags/ctags.c b/developer_cmds/ctags/ctags.c new file mode 100644 index 0000000..490f91d --- /dev/null +++ b/developer_cmds/ctags/ctags.c @@ -0,0 +1,282 @@ +/* $NetBSD: ctags.c,v 1.6 1998/08/25 20:59:36 ross Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994, 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. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994, 1995\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ctags.c 8.4 (Berkeley) 2/7/95"; +#endif +__RCSID("$NetBSD: ctags.c,v 1.6 1998/08/25 20:59:36 ross Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include "ctags.h" + +/* + * ctags: create a tags file + */ + +NODE *head; /* head of the sorted binary tree */ + + /* boolean "func" (see init()) */ +bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256]; + +FILE *inf; /* ioptr for current input file */ +FILE *outf; /* ioptr for tags file */ + +long lineftell; /* ftell after getc( inf ) == '\n' */ + +int lineno; /* line number of current line */ +int dflag; /* -d: non-macro defines */ +int tflag=1; /* -t: create tags for typedefs */ +int vflag; /* -v: vgrind style index output */ +int wflag; /* -w: suppress warnings */ +int xflag; /* -x: cxref style output */ + +char *curfile; /* current input file name */ +char searchar = '/'; /* use /.../ searches by default */ +char lbuf[LINE_MAX]; + +void init __P((void)); +int main __P((int, char **)); +void find_entries __P((char *)); + +int +main(argc, argv) + int argc; + char **argv; +{ + static char *outfile = "tags"; /* output file */ + int aflag; /* -a: append to tags */ + int uflag; /* -u: update tags */ + int exit_val; /* exit value */ + int step; /* step through args */ + int ch; /* getopts char */ + char cmd[100]; /* too ugly to explain */ + + aflag = uflag = NO; + while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1) + switch(ch) { + case 'B': + searchar = '?'; + break; + case 'F': + searchar = '/'; + break; + case 'a': + aflag++; + break; + case 'd': + dflag++; + break; + case 'f': + outfile = optarg; + break; + case 't': + tflag++; + break; + case 'T': + tflag--; + break; + case 'u': + uflag++; + break; + case 'w': + wflag++; + break; + case 'v': + vflag++; + case 'x': + xflag++; + break; + case '?': + default: + goto usage; + } + argv += optind; + argc -= optind; + if (!argc) { +usage: (void)fprintf(stderr, + "usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n"); + exit(1); + } + + init(); + + for (exit_val = step = 0; step < argc; ++step) + if (!(inf = fopen(argv[step], "r"))) { + warn("%s", argv[step]); + exit_val = 1; + } + else { + curfile = argv[step]; + find_entries(argv[step]); + (void)fclose(inf); + } + + if (head) { + if (xflag) + put_entries(head); + else { + if (uflag) { + for (step = 0; step < argc; step++) { + (void)sprintf(cmd, + "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS", + outfile, argv[step], + outfile); + system(cmd); + } + ++aflag; + } + if (!(outf = fopen(outfile, aflag ? "a" : "w"))) + err(exit_val ? exit_val : 1, "%s", outfile); + put_entries(head); + (void)fclose(outf); + if (uflag) { + (void)sprintf(cmd, "sort -o %s %s", + outfile, outfile); + system(cmd); + } + } + } + exit(exit_val); +} + +/* + * init -- + * this routine sets up the boolean psuedo-functions which work by + * setting boolean flags dependent upon the corresponding character. + * Every char which is NOT in that string is false with respect to + * the pseudo-function. Therefore, all of the array "_wht" is NO + * by default and then the elements subscripted by the chars in + * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in + * the string CWHITE, else NO. + */ +void +init() +{ + int i; + unsigned char *sp; + + for (i = 0; i < 256; i++) { + _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO; + _gd[i] = YES; + } +#define CWHITE (unsigned char *)" \f\t\n" + for (sp = CWHITE; *sp; sp++) /* white space chars */ + _wht[*sp] = YES; +#define CTOKEN (unsigned char *)" \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?" + for (sp = CTOKEN; *sp; sp++) /* token ending chars */ + _etk[*sp] = YES; +#define CINTOK (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789" + for (sp = CINTOK; *sp; sp++) /* valid in-token chars */ + _itk[*sp] = YES; +#define CBEGIN (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" + for (sp = CBEGIN; *sp; sp++) /* token starting chars */ + _btk[*sp] = YES; +#define CNOTGD (unsigned char *)",;" + for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */ + _gd[*sp] = NO; +} + +/* + * find_entries -- + * this routine opens the specified file and calls the function + * which searches the file. + */ +void +find_entries(file) + char *file; +{ + char *cp; + + lineno = 0; /* should be 1 ?? KB */ + if ((cp = strrchr(file, '.')) != NULL) { + if (cp[1] == 'l' && !cp[2]) { + int c; + + for (;;) { + if (GETC(==, EOF)) + return; + if (!iswhite(c)) { + rewind(inf); + break; + } + } +#define LISPCHR ";([" +/* lisp */ if (strchr(LISPCHR, c)) { + l_entries(); + return; + } +/* lex */ else { + /* + * we search all 3 parts of a lex file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yylex", lineno); + rewind(inf); + } + } +/* yacc */ else if (cp[1] == 'y' && !cp[2]) { + /* + * we search only the 3rd part of a yacc file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yyparse", lineno); + y_entries(); + } +/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) { + if (PF_funcs()) + return; + rewind(inf); + } + } +/* C */ c_entries(); +} diff --git a/developer_cmds/ctags/ctags.h b/developer_cmds/ctags/ctags.h new file mode 100644 index 0000000..99ba934 --- /dev/null +++ b/developer_cmds/ctags/ctags.h @@ -0,0 +1,92 @@ +/* $NetBSD: ctags.h,v 1.3 1995/03/26 20:14:07 glass Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + * + * @(#)ctags.h 8.3 (Berkeley) 4/2/94 + */ + +#define bool char + +#define YES 1 +#define NO 0 +#define EOS '\0' + +#define ENDLINE 50 /* max length of pattern */ +#define MAXTOKEN 250 /* max size of single token */ + +#define SETLINE {++lineno;lineftell = ftell(inf);} +#define GETC(op,exp) ((c = getc(inf)) op (int)exp) + +#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */ +#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */ +#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */ +#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */ +#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */ + +typedef struct nd_st { /* sorting structure */ + struct nd_st *left, + *right; /* left and right sons */ + char *entry, /* function or type name */ + *file, /* file name */ + *pat; /* search pattern */ + int lno; /* for -x option */ + bool been_warned; /* set if noticed dup */ +} NODE; + +extern char *curfile; /* current input file name */ +extern NODE *head; /* head of the sorted binary tree */ +extern FILE *inf; /* ioptr for current input file */ +extern FILE *outf; /* ioptr for current output file */ +extern long lineftell; /* ftell after getc( inf ) == '\n' */ +extern int lineno; /* line number of current line */ +extern int dflag; /* -d: non-macro defines */ +extern int tflag; /* -t: create tags for typedefs */ +extern int vflag; /* -v: vgrind style index output */ +extern int wflag; /* -w: suppress warnings */ +extern int xflag; /* -x: cxref style output */ +extern bool _wht[], _etk[], _itk[], _btk[], _gd[]; +extern char lbuf[LINE_MAX]; +extern char *lbp; +extern char searchar; /* ex search character */ + +extern int cicmp __P((char *)); +extern void ct_getline __P((void)); +extern void pfnote __P((char *, int)); +extern int skip_key __P((int)); +extern void put_entries __P((NODE *)); +extern void toss_yysec __P((void)); +extern void l_entries __P((void)); +extern void y_entries __P((void)); +extern int PF_funcs __P((void)); +extern void c_entries __P((void)); +extern void skip_comment __P((void)); diff --git a/developer_cmds/ctags/fortran.c b/developer_cmds/ctags/fortran.c new file mode 100644 index 0000000..a4b4178 --- /dev/null +++ b/developer_cmds/ctags/fortran.c @@ -0,0 +1,175 @@ +/* $NetBSD: fortran.c,v 1.4 1997/10/18 13:18:37 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)fortran.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: fortran.c,v 1.4 1997/10/18 13:18:37 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +static void takeprec __P((void)); + +char *lbp; /* line buffer pointer */ + +int +PF_funcs() +{ + bool pfcnt; /* pascal/fortran functions found */ + char *cp; + char tok[MAXTOKEN]; + + for (pfcnt = NO;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return (pfcnt); + ++lineno; + lbp = lbuf; + if (*lbp == '%') /* Ratfor escape to fortran */ + ++lbp; + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { /* convert to lower-case */ + case 'c': + if (cicmp("complex") || cicmp("character")) + takeprec(); + break; + case 'd': + if (cicmp("double")) { + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + if (cicmp("precision")) + break; + continue; + } + break; + case 'i': + if (cicmp("integer")) + takeprec(); + break; + case 'l': + if (cicmp("logical")) + takeprec(); + break; + case 'r': + if (cicmp("real")) + takeprec(); + break; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { + case 'f': + if (cicmp("function")) + break; + continue; + case 'p': + if (cicmp("program") || cicmp("procedure")) + break; + continue; + case 's': + if (cicmp("subroutine")) + break; + default: + continue; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + for (cp = lbp + 1; *cp && intoken(*cp); ++cp) + continue; + if ((cp = lbp + 1) != NULL) + continue; + *cp = EOS; + (void)strcpy(tok, lbp); + ct_getline(); /* process line for ex(1) */ + pfnote(tok, lineno); + pfcnt = YES; + } + /*NOTREACHED*/ +} + +/* + * cicmp -- + * do case-independent strcmp + */ +int +cicmp(cp) + char *cp; +{ + int len; + char *bp; + + for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' '); + ++cp, ++len) + continue; + if (!*cp) { + lbp += len; + return (YES); + } + return (NO); +} + +static void +takeprec() +{ + for (; isspace(*lbp); ++lbp) + continue; + if (*lbp == '*') { + for (++lbp; isspace(*lbp); ++lbp) + continue; + if (!isdigit(*lbp)) + --lbp; /* force failure */ + else + while (isdigit(*++lbp)) + continue; + } +} diff --git a/developer_cmds/ctags/lisp.c b/developer_cmds/ctags/lisp.c new file mode 100644 index 0000000..e925c1b --- /dev/null +++ b/developer_cmds/ctags/lisp.c @@ -0,0 +1,112 @@ +/* $NetBSD: lisp.c,v 1.4 1997/10/18 13:18:45 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)lisp.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: lisp.c,v 1.4 1997/10/18 13:18:45 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +/* + * lisp tag functions + * just look for (def or (DEF + */ +void +l_entries() +{ + int special; + char *cp; + char savedc; + char tok[MAXTOKEN]; + + for (;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return; + ++lineno; + lbp = lbuf; + if (!cicmp("(def")) + continue; + special = NO; + switch(*lbp | ' ') { + case 'm': + if (cicmp("method")) + special = YES; + break; + case 'w': + if (cicmp("wrapper") || cicmp("whopper")) + special = YES; + } + for (; !isspace(*lbp); ++lbp) + continue; + for (; isspace(*lbp); ++lbp) + continue; + for (cp = lbp; *cp && *cp != '\n'; ++cp) + continue; + *cp = EOS; + if (special) { + if (!(cp = strchr(lbp, ')'))) + continue; + for (; cp >= lbp && *cp != ':'; --cp) + continue; + if (cp < lbp) + continue; + lbp = cp; + for (; *cp && *cp != ')' && *cp != ' '; ++cp) + continue; + } + else + for (cp = lbp + 1; + *cp && *cp != '(' && *cp != ' '; ++cp) + continue; + savedc = *cp; + *cp = EOS; + (void)strcpy(tok, lbp); + *cp = savedc; + ct_getline(); + pfnote(tok, lineno); + } + /*NOTREACHED*/ +} diff --git a/developer_cmds/ctags/print.c b/developer_cmds/ctags/print.c new file mode 100644 index 0000000..a6c4aaf --- /dev/null +++ b/developer_cmds/ctags/print.c @@ -0,0 +1,122 @@ +/* $NetBSD: print.c,v 1.5 1997/10/18 13:18:52 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)print.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: print.c,v 1.5 1997/10/18 13:18:52 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "ctags.h" + +/* + * ct_getline -- + * get the line the token of interest occurred on, + * prepare it for printing. + */ +void +ct_getline() +{ + long saveftell; + int c; + int cnt; + char *cp; + + saveftell = ftell(inf); + (void)fseek(inf, lineftell, SEEK_SET); + if (xflag) + for (cp = lbuf; GETC(!=, '\n'); *cp++ = c) + continue; + /* + * do all processing here, so we don't step through the + * line more than once; means you don't call this routine + * unless you're sure you've got a keeper. + */ + else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) { + if (c == '\\') { /* backslashes */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = '\\'; + ++cnt; + } + else if (c == (int)searchar) { /* search character */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = c; + ++cnt; + } + else if (c == '\n') { /* end of keep */ + *cp++ = '$'; /* can find whole line */ + break; + } + else + *cp++ = c; + } + *cp = EOS; + (void)fseek(inf, saveftell, SEEK_SET); +} + +/* + * put_entries -- + * write out the tags + */ +void +put_entries(node) + NODE *node; +{ + + if (node->left) + put_entries(node->left); + if (vflag) + printf("%s %s %d\n", + node->entry, node->file, (node->lno + 63) / 64); + else if (xflag) + printf("%-16s%4d %-16s %s\n", + node->entry, node->lno, node->file, node->pat); + else + fprintf(outf, "%s\t%s\t%c^%s%c\n", + node->entry, node->file, searchar, node->pat, searchar); + if (node->right) + put_entries(node->right); +} diff --git a/developer_cmds/ctags/test/ctags.test b/developer_cmds/ctags/test/ctags.test new file mode 100644 index 0000000..658a073 --- /dev/null +++ b/developer_cmds/ctags/test/ctags.test @@ -0,0 +1,69 @@ +/* $NetBSD: ctags.test,v 1.2 1995/03/26 20:14:14 glass Exp $ */ + +int bar = (1 + 5); + +FOO("here is a #define test: ) {"); +char sysent[20]; +int nsysent = sizeof (sysent) / sizeof (sysent[0]); +/* + * now is the time for a comment. + * four lines in length... + */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe; +#define FOO BAR +struct struct_three { + int list; +}; +#define SINGLE +int BAD(); +enum color {red, green, gold, brown}; +char qq[] = " quote(one,two) {int bar;} "; +typedef struct { + int bar; + struct struct_two { + int foo; + union union_3 { + struct struct_three entry; + char size[25]; + }; + struct last { + struct struct_three xentry; + char list[34]; + }; + }; +} struct_one; +#define TWOLINE ((MAXLIST + FUTURE + 15) \ + / (time_to_live ? 3 : 4)) +#if (defined(BAR)) +int bar; +#endif +#define MULTIPLE {\ + multiple(one,two); \ + lineno++; \ + callroute(one,two); \ +} +#if defined(BAR) +int bar; +#endif +union union_one { + struct struct_three s3; + char foo[25]; +}; +#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno) +routine1(one,two) /* comments here are fun... */ + struct { + int entry; + char bar[34]; + } *one; + char two[10]; +{ +typedef unsigned char u_char; + register struct buf *bp; + five(one,two); +} + routine2 (one,two) { puts("hello\n"); } + routine3 +(one, +two) { puts("world\n"); } +routine4(int one, char (*two)(void)) /* test ANSI arguments */ +{ +} diff --git a/developer_cmds/ctags/tree.c b/developer_cmds/ctags/tree.c new file mode 100644 index 0000000..c31975c --- /dev/null +++ b/developer_cmds/ctags/tree.c @@ -0,0 +1,142 @@ +/* $NetBSD: tree.c,v 1.5 1997/10/18 13:18:58 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: tree.c,v 1.5 1997/10/18 13:18:58 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "ctags.h" + +static void add_node __P((NODE *, NODE *)); +static void free_tree __P((NODE *)); + +/* + * pfnote -- + * enter a new node in the tree + */ +void +pfnote(name, ln) + char *name; + int ln; +{ + NODE *np; + char *fp; + char nbuf[MAXTOKEN]; + + /*NOSTRICT*/ + if (!(np = (NODE *)malloc(sizeof(NODE)))) { + warnx("too many entries to sort"); + put_entries(head); + free_tree(head); + /*NOSTRICT*/ + if (!(head = np = (NODE *)malloc(sizeof(NODE)))) + err(1, "out of space"); + } + if (!xflag && !strcmp(name, "main")) { + if (!(fp = strrchr(curfile, '/'))) + fp = curfile; + else + ++fp; + (void)sprintf(nbuf, "M%s", fp); + fp = strrchr(nbuf, '.'); + if (fp && !fp[2]) + *fp = EOS; + name = nbuf; + } + if (!(np->entry = strdup(name))) + err(1, "strdup"); + np->file = curfile; + np->lno = ln; + np->left = np->right = 0; + if (!(np->pat = strdup(lbuf))) + err(1, "strdup"); + if (!head) + head = np; + else + add_node(np, head); +} + +static void +add_node(node, cur_node) + NODE *node, + *cur_node; +{ + int dif; + + dif = strcmp(node->entry, cur_node->entry); + if (!dif) { + if (node->file == cur_node->file) { + if (!wflag) + fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry); + return; + } + if (!cur_node->been_warned) + if (!wflag) + fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry); + cur_node->been_warned = YES; + } + else if (dif < 0) + if (cur_node->left) + add_node(node, cur_node->left); + else + cur_node->left = node; + else if (cur_node->right) + add_node(node, cur_node->right); + else + cur_node->right = node; +} + +static void +free_tree(node) + NODE *node; +{ + while (node) { + if (node->right) + free_tree(node->right); + free(node); + node = node->left; + } +} diff --git a/developer_cmds/ctags/yacc.c b/developer_cmds/ctags/yacc.c new file mode 100644 index 0000000..17edfa6 --- /dev/null +++ b/developer_cmds/ctags/yacc.c @@ -0,0 +1,158 @@ +/* $NetBSD: yacc.c,v 1.4 1997/10/18 13:19:04 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 +#ifndef lint +#if 0 +static char sccsid[] = "@(#)yacc.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: yacc.c,v 1.4 1997/10/18 13:19:04 lukem Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include + +#include "ctags.h" + +/* + * y_entries: + * find the yacc tags and put them in. + */ +void +y_entries() +{ + int c; + char *sp; + bool in_rule; + char tok[MAXTOKEN]; + + in_rule = NO; + + while (GETC(!=, EOF)) + switch (c) { + case '\n': + SETLINE; + /* FALLTHROUGH */ + case ' ': + case '\f': + case '\r': + case '\t': + break; + case '{': + if (skip_key('}')) + in_rule = NO; + break; + case '\'': + case '"': + if (skip_key(c)) + in_rule = NO; + break; + case '%': + if (GETC(==, '%')) + return; + (void)ungetc(c, inf); + break; + case '/': + if (GETC(==, '*')) + skip_comment(); + else + (void)ungetc(c, inf); + break; + case '|': + case ';': + in_rule = NO; + break; + default: + if (in_rule || (!isalpha(c) && c != '.' && c != '_')) + break; + sp = tok; + *sp++ = c; + while (GETC(!=, EOF) && (intoken(c) || c == '.')) + *sp++ = c; + *sp = EOS; + ct_getline(); /* may change before ':' */ + while (iswhite(c)) { + if (c == '\n') + SETLINE; + if (GETC(==, EOF)) + return; + } + if (c == ':') { + pfnote(tok, lineno); + in_rule = YES; + } + else + (void)ungetc(c, inf); + } +} + +/* + * toss_yysec -- + * throw away lines up to the next "\n%%\n" + */ +void +toss_yysec() +{ + int c; /* read character */ + int state; + + /* + * state == 0 : waiting + * state == 1 : received a newline + * state == 2 : received first % + * state == 3 : recieved second % + */ + lineftell = ftell(inf); + for (state = 0; GETC(!=, EOF);) + switch (c) { + case '\n': + ++lineno; + lineftell = ftell(inf); + if (state == 3) /* done! */ + return; + state = 1; /* start over */ + break; + case '%': + if (state) /* if 1 or 2 */ + ++state; /* goto 3 */ + break; + default: + state = 0; /* reset */ + break; + } +} diff --git a/developer_cmds/developer_cmds.xcodeproj/project.pbxproj b/developer_cmds/developer_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e43393a --- /dev/null +++ b/developer_cmds/developer_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,787 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXAggregateTarget section */ + FDA9C8500FD5E85100A6EA6E /* default */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDA9C85E0FD5E86100A6EA6E /* Build configuration list for PBXAggregateTarget "default" */; + buildPhases = ( + ); + dependencies = ( + FDA9C8590FD5E85C00A6EA6E /* PBXTargetDependency */, + FDA9C85B0FD5E85E00A6EA6E /* PBXTargetDependency */, + FDA9C8B60FD5EAA500A6EA6E /* PBXTargetDependency */, + FDA9C9870FD5F06900A6EA6E /* PBXTargetDependency */, + FDA9C8DA0FD5EBB200A6EA6E /* PBXTargetDependency */, + FDA9C8FC0FD5EC3300A6EA6E /* PBXTargetDependency */, + ); + name = default; + productName = Default; + }; + FDA9C97F0FD5F05400A6EA6E /* lorder */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDA9C98B0FD5F08700A6EA6E /* Build configuration list for PBXAggregateTarget "lorder" */; + buildPhases = ( + FDA9C97E0FD5F05400A6EA6E /* ShellScript */, + FDA9C9A20FD5F12200A6EA6E /* Install man1 */, + ); + dependencies = ( + ); + name = lorder; + productName = lorder; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + FDA9C83F0FD5E7E300A6EA6E /* asa.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E40FD5D90F00A6EA6E /* asa.c */; }; + FDA9C84D0FD5E82800A6EA6E /* asa.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C7E30FD5D90F00A6EA6E /* asa.1 */; }; + FDA9C85F0FD5E87200A6EA6E /* C.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E70FD5D92800A6EA6E /* C.c */; }; + FDA9C8600FD5E87200A6EA6E /* ctags.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7E90FD5D92800A6EA6E /* ctags.c */; }; + FDA9C8610FD5E87200A6EA6E /* fortran.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EB0FD5D92800A6EA6E /* fortran.c */; }; + FDA9C8620FD5E87200A6EA6E /* lisp.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EC0FD5D92800A6EA6E /* lisp.c */; }; + FDA9C8630FD5E87200A6EA6E /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7EE0FD5D92800A6EA6E /* print.c */; }; + FDA9C8640FD5E87200A6EA6E /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7F10FD5D92800A6EA6E /* tree.c */; }; + FDA9C8650FD5E87200A6EA6E /* yacc.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7F20FD5D92800A6EA6E /* yacc.c */; }; + FDA9C86B0FD5E88900A6EA6E /* ctags.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C7E80FD5D92800A6EA6E /* ctags.1 */; }; + FDA9C8BA0FD5EAD700A6EA6E /* args.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C7FF0FD5D92800A6EA6E /* args.c */; }; + FDA9C8BB0FD5EAD700A6EA6E /* indent.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8010FD5D92800A6EA6E /* indent.c */; }; + FDA9C8BC0FD5EAD700A6EA6E /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8040FD5D92800A6EA6E /* io.c */; }; + FDA9C8BD0FD5EAD700A6EA6E /* lexi.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8050FD5D92800A6EA6E /* lexi.c */; }; + FDA9C8BE0FD5EAD700A6EA6E /* parse.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8070FD5D92800A6EA6E /* parse.c */; }; + FDA9C8BF0FD5EAD700A6EA6E /* pr_comment.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8080FD5D92800A6EA6E /* pr_comment.c */; }; + FDA9C8C10FD5EAEA00A6EA6E /* indent.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8000FD5D92800A6EA6E /* indent.1 */; }; + FDA9C8DF0FD5EBE600A6EA6E /* rpc_clntout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */; }; + FDA9C8E00FD5EBE600A6EA6E /* rpc_cout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */; }; + FDA9C8E10FD5EBE600A6EA6E /* rpc_hout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */; }; + FDA9C8E20FD5EBE600A6EA6E /* rpc_main.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */; }; + FDA9C8E30FD5EBE600A6EA6E /* rpc_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */; }; + FDA9C8E40FD5EBE600A6EA6E /* rpc_sample.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */; }; + FDA9C8E50FD5EBE600A6EA6E /* rpc_scan.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */; }; + FDA9C8E60FD5EBE600A6EA6E /* rpc_svcout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */; }; + FDA9C8E70FD5EBE600A6EA6E /* rpc_tblout.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */; }; + FDA9C8E80FD5EBE600A6EA6E /* rpc_util.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8230FD5D92800A6EA6E /* rpc_util.c */; }; + FDA9C8EA0FD5EBF600A6EA6E /* rpcgen.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */; }; + FDA9C9010FD5EC4800A6EA6E /* unifdef.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA9C8290FD5D92800A6EA6E /* unifdef.c */; }; + FDA9C9030FD5EC5F00A6EA6E /* unifdef.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C8280FD5D92800A6EA6E /* unifdef.1 */; }; + FDA9C9900FD5F10200A6EA6E /* lorder.1 in Install man1 */ = {isa = PBXBuildFile; fileRef = FDA9C80B0FD5D92800A6EA6E /* lorder.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FDA9C8580FD5E85C00A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8390FD5E7DB00A6EA6E; + remoteInfo = asa; + }; + FDA9C85A0FD5E85E00A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8540FD5E85900A6EA6E; + remoteInfo = ctags; + }; + FDA9C8B50FD5EAA500A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8B10FD5EAA100A6EA6E; + remoteInfo = indent; + }; + FDA9C8D90FD5EBB200A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8D50FD5EBA400A6EA6E; + remoteInfo = rpcgen; + }; + FDA9C8FB0FD5EC3300A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C8F70FD5EC2A00A6EA6E; + remoteInfo = unifdef; + }; + FDA9C9860FD5F06900A6EA6E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FDA9C7D70FD5D84000A6EA6E /* Project object */; + proxyType = 1; + remoteGlobalIDString = FDA9C97F0FD5F05400A6EA6E; + remoteInfo = lorder; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FDA9C84F0FD5E82D00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C84D0FD5E82800A6EA6E /* asa.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8730FD5E89700A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C86B0FD5E88900A6EA6E /* ctags.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8CA0FD5EAFC00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C8C10FD5EAEA00A6EA6E /* indent.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C8F40FD5EC0F00A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C8EA0FD5EBF600A6EA6E /* rpcgen.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C9040FD5EC6800A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C9030FD5EC5F00A6EA6E /* unifdef.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + FDA9C9A20FD5F12200A6EA6E /* Install man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(DT_TOOLCHAIN_DIR)/usr/share/man/man1"; + dstSubfolderSpec = 0; + files = ( + FDA9C9900FD5F10200A6EA6E /* lorder.1 in Install man1 */, + ); + name = "Install man1"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + FDA9C7E30FD5D90F00A6EA6E /* asa.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = asa.1; sourceTree = ""; }; + FDA9C7E40FD5D90F00A6EA6E /* asa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asa.c; sourceTree = ""; }; + FDA9C7E70FD5D92800A6EA6E /* C.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = C.c; sourceTree = ""; }; + FDA9C7E80FD5D92800A6EA6E /* ctags.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ctags.1; sourceTree = ""; }; + FDA9C7E90FD5D92800A6EA6E /* ctags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ctags.c; sourceTree = ""; }; + FDA9C7EA0FD5D92800A6EA6E /* ctags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ctags.h; sourceTree = ""; }; + FDA9C7EB0FD5D92800A6EA6E /* fortran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fortran.c; sourceTree = ""; }; + FDA9C7EC0FD5D92800A6EA6E /* lisp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lisp.c; sourceTree = ""; }; + FDA9C7EE0FD5D92800A6EA6E /* print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = ""; }; + FDA9C7F00FD5D92800A6EA6E /* ctags.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ctags.test; sourceTree = ""; }; + FDA9C7F10FD5D92800A6EA6E /* tree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = ""; }; + FDA9C7F20FD5D92800A6EA6E /* yacc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yacc.c; sourceTree = ""; }; + FDA9C7FF0FD5D92800A6EA6E /* args.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = args.c; sourceTree = ""; }; + FDA9C8000FD5D92800A6EA6E /* indent.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = indent.1; sourceTree = ""; }; + FDA9C8010FD5D92800A6EA6E /* indent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = indent.c; sourceTree = ""; }; + FDA9C8020FD5D92800A6EA6E /* indent_codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indent_codes.h; sourceTree = ""; }; + FDA9C8030FD5D92800A6EA6E /* indent_globs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indent_globs.h; sourceTree = ""; }; + FDA9C8040FD5D92800A6EA6E /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = ""; }; + FDA9C8050FD5D92800A6EA6E /* lexi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lexi.c; sourceTree = ""; }; + FDA9C8070FD5D92800A6EA6E /* parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parse.c; sourceTree = ""; }; + FDA9C8080FD5D92800A6EA6E /* pr_comment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pr_comment.c; sourceTree = ""; }; + FDA9C8090FD5D92800A6EA6E /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; + FDA9C80B0FD5D92800A6EA6E /* lorder.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = lorder.1; sourceTree = ""; }; + FDA9C80C0FD5D92800A6EA6E /* lorder.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = lorder.sh; sourceTree = ""; }; + FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_clntout.c; sourceTree = ""; }; + FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_cout.c; sourceTree = ""; }; + FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_hout.c; sourceTree = ""; }; + FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_main.c; sourceTree = ""; }; + FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_parse.c; sourceTree = ""; }; + FDA9C81D0FD5D92800A6EA6E /* rpc_parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_parse.h; sourceTree = ""; }; + FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_sample.c; sourceTree = ""; }; + FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_scan.c; sourceTree = ""; }; + FDA9C8200FD5D92800A6EA6E /* rpc_scan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_scan.h; sourceTree = ""; }; + FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_svcout.c; sourceTree = ""; }; + FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_tblout.c; sourceTree = ""; }; + FDA9C8230FD5D92800A6EA6E /* rpc_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_util.c; sourceTree = ""; }; + FDA9C8240FD5D92800A6EA6E /* rpc_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_util.h; sourceTree = ""; }; + FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = rpcgen.1; sourceTree = ""; }; + FDA9C8280FD5D92800A6EA6E /* unifdef.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = unifdef.1; sourceTree = ""; }; + FDA9C8290FD5D92800A6EA6E /* unifdef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unifdef.c; sourceTree = ""; }; + FDA9C82A0FD5D92800A6EA6E /* unifdefall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = unifdefall.sh; sourceTree = ""; }; + FDA9C83A0FD5E7DB00A6EA6E /* asa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = asa; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8550FD5E85900A6EA6E /* ctags */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ctags; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8B20FD5EAA100A6EA6E /* indent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = indent; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8D60FD5EBA400A6EA6E /* rpcgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rpcgen; sourceTree = BUILT_PRODUCTS_DIR; }; + FDA9C8F80FD5EC2A00A6EA6E /* unifdef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unifdef; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FDA9C8380FD5E7DB00A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8530FD5E85900A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8B00FD5EAA100A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8D40FD5EBA400A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8F60FD5EC2A00A6EA6E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FDA9C7D50FD5D84000A6EA6E = { + isa = PBXGroup; + children = ( + FDA9C9280FD5ED6700A6EA6E /* Source */, + FDA9C83B0FD5E7DB00A6EA6E /* Products */, + ); + sourceTree = ""; + }; + FDA9C7E20FD5D90F00A6EA6E /* asa */ = { + isa = PBXGroup; + children = ( + FDA9C7E30FD5D90F00A6EA6E /* asa.1 */, + FDA9C7E40FD5D90F00A6EA6E /* asa.c */, + ); + path = asa; + sourceTree = ""; + }; + FDA9C7E60FD5D92800A6EA6E /* ctags */ = { + isa = PBXGroup; + children = ( + FDA9C7E70FD5D92800A6EA6E /* C.c */, + FDA9C7E90FD5D92800A6EA6E /* ctags.c */, + FDA9C7EB0FD5D92800A6EA6E /* fortran.c */, + FDA9C7EC0FD5D92800A6EA6E /* lisp.c */, + FDA9C7EE0FD5D92800A6EA6E /* print.c */, + FDA9C7F10FD5D92800A6EA6E /* tree.c */, + FDA9C7F20FD5D92800A6EA6E /* yacc.c */, + FDA9C7EA0FD5D92800A6EA6E /* ctags.h */, + FDA9C7E80FD5D92800A6EA6E /* ctags.1 */, + FDA9C7EF0FD5D92800A6EA6E /* test */, + ); + path = ctags; + sourceTree = ""; + }; + FDA9C7EF0FD5D92800A6EA6E /* test */ = { + isa = PBXGroup; + children = ( + FDA9C7F00FD5D92800A6EA6E /* ctags.test */, + ); + path = test; + sourceTree = ""; + }; + FDA9C7FE0FD5D92800A6EA6E /* indent */ = { + isa = PBXGroup; + children = ( + FDA9C7FF0FD5D92800A6EA6E /* args.c */, + FDA9C8010FD5D92800A6EA6E /* indent.c */, + FDA9C8040FD5D92800A6EA6E /* io.c */, + FDA9C8050FD5D92800A6EA6E /* lexi.c */, + FDA9C8070FD5D92800A6EA6E /* parse.c */, + FDA9C8080FD5D92800A6EA6E /* pr_comment.c */, + FDA9C8020FD5D92800A6EA6E /* indent_codes.h */, + FDA9C8030FD5D92800A6EA6E /* indent_globs.h */, + FDA9C8000FD5D92800A6EA6E /* indent.1 */, + FDA9C8090FD5D92800A6EA6E /* README */, + ); + path = indent; + sourceTree = ""; + }; + FDA9C80A0FD5D92800A6EA6E /* lorder */ = { + isa = PBXGroup; + children = ( + FDA9C80C0FD5D92800A6EA6E /* lorder.sh */, + FDA9C80B0FD5D92800A6EA6E /* lorder.1 */, + ); + path = lorder; + sourceTree = ""; + }; + FDA9C8160FD5D92800A6EA6E /* rpcgen */ = { + isa = PBXGroup; + children = ( + FDA9C8180FD5D92800A6EA6E /* rpc_clntout.c */, + FDA9C8190FD5D92800A6EA6E /* rpc_cout.c */, + FDA9C81A0FD5D92800A6EA6E /* rpc_hout.c */, + FDA9C81B0FD5D92800A6EA6E /* rpc_main.c */, + FDA9C81C0FD5D92800A6EA6E /* rpc_parse.c */, + FDA9C81E0FD5D92800A6EA6E /* rpc_sample.c */, + FDA9C81F0FD5D92800A6EA6E /* rpc_scan.c */, + FDA9C8210FD5D92800A6EA6E /* rpc_svcout.c */, + FDA9C8220FD5D92800A6EA6E /* rpc_tblout.c */, + FDA9C8230FD5D92800A6EA6E /* rpc_util.c */, + FDA9C81D0FD5D92800A6EA6E /* rpc_parse.h */, + FDA9C8200FD5D92800A6EA6E /* rpc_scan.h */, + FDA9C8240FD5D92800A6EA6E /* rpc_util.h */, + FDA9C8250FD5D92800A6EA6E /* rpcgen.1 */, + ); + path = rpcgen; + sourceTree = ""; + }; + FDA9C8260FD5D92800A6EA6E /* unifdef */ = { + isa = PBXGroup; + children = ( + FDA9C8290FD5D92800A6EA6E /* unifdef.c */, + FDA9C8280FD5D92800A6EA6E /* unifdef.1 */, + FDA9C82A0FD5D92800A6EA6E /* unifdefall.sh */, + ); + path = unifdef; + sourceTree = ""; + }; + FDA9C83B0FD5E7DB00A6EA6E /* Products */ = { + isa = PBXGroup; + children = ( + FDA9C83A0FD5E7DB00A6EA6E /* asa */, + FDA9C8550FD5E85900A6EA6E /* ctags */, + FDA9C8B20FD5EAA100A6EA6E /* indent */, + FDA9C8D60FD5EBA400A6EA6E /* rpcgen */, + FDA9C8F80FD5EC2A00A6EA6E /* unifdef */, + ); + name = Products; + sourceTree = ""; + }; + FDA9C9280FD5ED6700A6EA6E /* Source */ = { + isa = PBXGroup; + children = ( + FDA9C7E20FD5D90F00A6EA6E /* asa */, + FDA9C7E60FD5D92800A6EA6E /* ctags */, + FDA9C7FE0FD5D92800A6EA6E /* indent */, + FDA9C80A0FD5D92800A6EA6E /* lorder */, + FDA9C8160FD5D92800A6EA6E /* rpcgen */, + FDA9C8260FD5D92800A6EA6E /* unifdef */, + ); + name = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FDA9C8390FD5E7DB00A6EA6E /* asa */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C83E0FD5E7DC00A6EA6E /* Build configuration list for PBXNativeTarget "asa" */; + buildPhases = ( + FDA9C8370FD5E7DB00A6EA6E /* Sources */, + FDA9C8380FD5E7DB00A6EA6E /* Frameworks */, + FDA9C84F0FD5E82D00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = asa; + productName = asa; + productReference = FDA9C83A0FD5E7DB00A6EA6E /* asa */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8540FD5E85900A6EA6E /* ctags */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C85D0FD5E86100A6EA6E /* Build configuration list for PBXNativeTarget "ctags" */; + buildPhases = ( + FDA9C8520FD5E85900A6EA6E /* Sources */, + FDA9C8530FD5E85900A6EA6E /* Frameworks */, + FDA9C8730FD5E89700A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ctags; + productName = ctags; + productReference = FDA9C8550FD5E85900A6EA6E /* ctags */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8B10FD5EAA100A6EA6E /* indent */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C8B90FD5EAAD00A6EA6E /* Build configuration list for PBXNativeTarget "indent" */; + buildPhases = ( + FDA9C8AF0FD5EAA100A6EA6E /* Sources */, + FDA9C8B00FD5EAA100A6EA6E /* Frameworks */, + FDA9C8CA0FD5EAFC00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = indent; + productName = indent; + productReference = FDA9C8B20FD5EAA100A6EA6E /* indent */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8D50FD5EBA400A6EA6E /* rpcgen */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C8DE0FD5EBB300A6EA6E /* Build configuration list for PBXNativeTarget "rpcgen" */; + buildPhases = ( + FDA9C8D30FD5EBA400A6EA6E /* Sources */, + FDA9C8D40FD5EBA400A6EA6E /* Frameworks */, + FDA9C8F40FD5EC0F00A6EA6E /* Install man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = rpcgen; + productName = rpcgen; + productReference = FDA9C8D60FD5EBA400A6EA6E /* rpcgen */; + productType = "com.apple.product-type.tool"; + }; + FDA9C8F70FD5EC2A00A6EA6E /* unifdef */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDA9C9000FD5EC3B00A6EA6E /* Build configuration list for PBXNativeTarget "unifdef" */; + buildPhases = ( + FDA9C8F50FD5EC2A00A6EA6E /* Sources */, + FDA9C8F60FD5EC2A00A6EA6E /* Frameworks */, + FDA9C9040FD5EC6800A6EA6E /* Install man1 */, + FDA9C9080FD5EC7500A6EA6E /* Install unifdefall */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = unifdef; + productName = unifdef; + productReference = FDA9C8F80FD5EC2A00A6EA6E /* unifdef */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FDA9C7D70FD5D84000A6EA6E /* Project object */ = { + isa = PBXProject; + attributes = { + }; + buildConfigurationList = FDA9C7DA0FD5D84000A6EA6E /* Build configuration list for PBXProject "developer_cmds" */; + compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FDA9C7D50FD5D84000A6EA6E; + productRefGroup = FDA9C83B0FD5E7DB00A6EA6E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FDA9C8500FD5E85100A6EA6E /* default */, + FDA9C8390FD5E7DB00A6EA6E /* asa */, + FDA9C8540FD5E85900A6EA6E /* ctags */, + FDA9C8B10FD5EAA100A6EA6E /* indent */, + FDA9C97F0FD5F05400A6EA6E /* lorder */, + FDA9C8D50FD5EBA400A6EA6E /* rpcgen */, + FDA9C8F70FD5EC2A00A6EA6E /* unifdef */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + FDA9C9080FD5EC7500A6EA6E /* Install unifdefall */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + name = "Install unifdefall"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-unifdefall.sh"; + showEnvVarsInLog = 0; + }; + FDA9C97E0FD5F05400A6EA6E /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-lorder.sh"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FDA9C8370FD5E7DB00A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C83F0FD5E7E300A6EA6E /* asa.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8520FD5E85900A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C85F0FD5E87200A6EA6E /* C.c in Sources */, + FDA9C8600FD5E87200A6EA6E /* ctags.c in Sources */, + FDA9C8610FD5E87200A6EA6E /* fortran.c in Sources */, + FDA9C8620FD5E87200A6EA6E /* lisp.c in Sources */, + FDA9C8630FD5E87200A6EA6E /* print.c in Sources */, + FDA9C8640FD5E87200A6EA6E /* tree.c in Sources */, + FDA9C8650FD5E87200A6EA6E /* yacc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8AF0FD5EAA100A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C8BA0FD5EAD700A6EA6E /* args.c in Sources */, + FDA9C8BB0FD5EAD700A6EA6E /* indent.c in Sources */, + FDA9C8BC0FD5EAD700A6EA6E /* io.c in Sources */, + FDA9C8BD0FD5EAD700A6EA6E /* lexi.c in Sources */, + FDA9C8BE0FD5EAD700A6EA6E /* parse.c in Sources */, + FDA9C8BF0FD5EAD700A6EA6E /* pr_comment.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8D30FD5EBA400A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C8DF0FD5EBE600A6EA6E /* rpc_clntout.c in Sources */, + FDA9C8E00FD5EBE600A6EA6E /* rpc_cout.c in Sources */, + FDA9C8E10FD5EBE600A6EA6E /* rpc_hout.c in Sources */, + FDA9C8E20FD5EBE600A6EA6E /* rpc_main.c in Sources */, + FDA9C8E30FD5EBE600A6EA6E /* rpc_parse.c in Sources */, + FDA9C8E40FD5EBE600A6EA6E /* rpc_sample.c in Sources */, + FDA9C8E50FD5EBE600A6EA6E /* rpc_scan.c in Sources */, + FDA9C8E60FD5EBE600A6EA6E /* rpc_svcout.c in Sources */, + FDA9C8E70FD5EBE600A6EA6E /* rpc_tblout.c in Sources */, + FDA9C8E80FD5EBE600A6EA6E /* rpc_util.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDA9C8F50FD5EC2A00A6EA6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDA9C9010FD5EC4800A6EA6E /* unifdef.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FDA9C8590FD5E85C00A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8390FD5E7DB00A6EA6E /* asa */; + targetProxy = FDA9C8580FD5E85C00A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C85B0FD5E85E00A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8540FD5E85900A6EA6E /* ctags */; + targetProxy = FDA9C85A0FD5E85E00A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8B60FD5EAA500A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8B10FD5EAA100A6EA6E /* indent */; + targetProxy = FDA9C8B50FD5EAA500A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8DA0FD5EBB200A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8D50FD5EBA400A6EA6E /* rpcgen */; + targetProxy = FDA9C8D90FD5EBB200A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C8FC0FD5EC3300A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C8F70FD5EC2A00A6EA6E /* unifdef */; + targetProxy = FDA9C8FB0FD5EC3300A6EA6E /* PBXContainerItemProxy */; + }; + FDA9C9870FD5F06900A6EA6E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FDA9C97F0FD5F05400A6EA6E /* lorder */; + targetProxy = FDA9C9860FD5F06900A6EA6E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + FDA9C7D90FD5D84000A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + INSTALL_MODE_FLAG = "ugo-w,a+rX"; + PREBINDING = NO; + USE_HEADERMAP = NO; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = NO; + }; + name = Release; + }; + FDA9C83D0FD5E7DB00A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = asa; + }; + name = Release; + }; + FDA9C8510FD5E85100A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = default; + }; + name = Release; + }; + FDA9C8570FD5E85900A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = ctags; + }; + name = Release; + }; + FDA9C8B40FD5EAA200A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = indent; + }; + name = Release; + }; + FDA9C8D80FD5EBA400A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = rpcgen; + }; + name = Release; + }; + FDA9C8FA0FD5EC2A00A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(DT_TOOLCHAIN_DIR)/usr/bin"; + PRODUCT_NAME = unifdef; + }; + name = Release; + }; + FDA9C9800FD5F05400A6EA6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = lorder; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FDA9C7DA0FD5D84000A6EA6E /* Build configuration list for PBXProject "developer_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C7D90FD5D84000A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C83E0FD5E7DC00A6EA6E /* Build configuration list for PBXNativeTarget "asa" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C83D0FD5E7DB00A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C85D0FD5E86100A6EA6E /* Build configuration list for PBXNativeTarget "ctags" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8570FD5E85900A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C85E0FD5E86100A6EA6E /* Build configuration list for PBXAggregateTarget "default" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8510FD5E85100A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C8B90FD5EAAD00A6EA6E /* Build configuration list for PBXNativeTarget "indent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8B40FD5EAA200A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C8DE0FD5EBB300A6EA6E /* Build configuration list for PBXNativeTarget "rpcgen" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8D80FD5EBA400A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C9000FD5EC3B00A6EA6E /* Build configuration list for PBXNativeTarget "unifdef" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C8FA0FD5EC2A00A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDA9C98B0FD5F08700A6EA6E /* Build configuration list for PBXAggregateTarget "lorder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDA9C9800FD5F05400A6EA6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FDA9C7D70FD5D84000A6EA6E /* Project object */; +} diff --git a/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/developer_cmds/developer_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/developer_cmds/indent/args.c b/developer_cmds/indent/args.c new file mode 100644 index 0000000..507be03 --- /dev/null +++ b/developer_cmds/indent/args.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/args.c,v 1.16 2010/03/31 17:05:30 avg Exp $"); + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ +#define PRO_FONT 4 /* troff font */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +const char *option_source = "?"; + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbc", PRO_FONT, 0, 0, (int *) &blkcomf}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fbx", PRO_FONT, 0, 0, (int *) &boxcomf}, + {"fb", PRO_FONT, 0, 0, (int *) &bodyf}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"fc", PRO_FONT, 0, 0, (int *) &scomf}, + {"fk", PRO_FONT, 0, 0, (int *) &keywordf}, + {"fs", PRO_FONT, 0, 0, (int *) &stringf}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nps", PRO_BOOL, false, OFF, &pointer_as_binop}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"ps", PRO_BOOL, false, ON, &pointer_as_binop}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"troff", PRO_BOOL, false, ON, &troff}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(void) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace(i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +const char *param_start; + +static int +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (false); + } + param_start = s2; + return (true); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && eqin(p->p_name, arg)) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == 0) + input = stdin; + if (output == 0) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + { + char *str = strdup(param_start); + if (str == NULL) + err(1, NULL); + addkey(str, 4); + } + break; + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit(*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, arg - 1); + } + *p->p_obj = atoi(param_start); + break; + + case PRO_FONT: + parsefont((struct fstate *) p->p_obj, param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} diff --git a/developer_cmds/indent/indent.1 b/developer_cmds/indent/indent.1 new file mode 100644 index 0000000..f35ea95 --- /dev/null +++ b/developer_cmds/indent/indent.1 @@ -0,0 +1,559 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with 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. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: src/usr.bin/indent/indent.1,v 1.28 2010/03/31 17:05:30 avg Exp $ +.\" +.Dd June 29, 2004 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input_file Op Ar output_file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl bap | Fl nbap +.Bk -words +.Op Fl bbb | Fl nbbb +.Ek +.Op Fl \&bc | Fl nbc +.Op Fl \&bl +.Op Fl \&br +.Op Fl c Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Bk -words +.Op Fl ei | Fl ei +.Op Fl eei | Fl eei +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl npro +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl troff +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Sh DESCRIPTION +.Nm +is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input_file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input_file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input_file +and a backup copy of +.Ar input_file +is written in the current directory. +If +.Ar input_file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output_file +is specified, +.Nm +checks to make sure that it is different from +.Ar input_file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +The default is +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +The default is +.Fl nbad . +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +The default is +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +The default is +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +The default is +.Fl \&nbc . +.It Fl \&br , \&bl +Specifying +.Fl \&bl +lines-up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.Pp +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines-up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of spaces for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines-up code surrounded by parenthesis in continuation lines. +If a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +The default is +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl troff +Causes +.Nm +to format the program for processing by +.Xr troff 1 . +.\" It will produce a fancy +.\" listing in much the same spirit as +.\" .Xr vgrind 1 . +If the output file is not specified, the default is standard output, +rather than formatting in place. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +Tabs are assumed to be aligned on columns divisible by 8. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +.Nm +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +.Nm +fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Pp +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Pp +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Pp +.Ss C syntax +.Nm +understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and misformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +.Nm +uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +.Nm +has even more switches than +.Xr ls 1 . +.Pp +A common mistake that often causes grief is typing: +.Pp +.Dl indent *.c +.Pp +to the shell in an attempt to indent all the +.Tn C +programs in a directory. +This is probably a bug, not a feature. diff --git a/developer_cmds/indent/indent.c b/developer_cmds/indent/indent.c new file mode 100644 index 0000000..b88118e --- /dev/null +++ b/developer_cmds/indent/indent.c @@ -0,0 +1,1234 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * 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. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ +@(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ +@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/indent.c,v 1.28 2011/12/30 11:02:40 uqs Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int flushed_nl; /* used when buffering up comments to remember + * that a newline was passed over */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a ?: + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = 0; + bp_save = 0; + be_save = 0; + + output = 0; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + set_defaults(); + if (i >= argc) + set_profile(); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (troff || input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (troff) { + if (bodyf.font[0] == 0) + parsefont(&bodyf, "R"); + if (scomf.font[0] == 0) + parsefont(&scomf, "I"); + if (blkcomf.font[0] == 0) + blkcomf = scomf, blkcomf.size += 2; + if (boxcomf.font[0] == 0) + boxcomf = blkcomf; + if (stringf.font[0] == 0) + parsefont(&stringf, "L"); + if (keywordf.font[0] == 0) + parsefont(&keywordf, "B"); + writefdef(&bodyf, 'B'); + writefdef(&scomf, 'C'); + writefdef(&blkcomf, 'L'); + writefdef(&boxcomf, 'X'); + writefdef(&stringf, 'S'); + writefdef(&keywordf, 'K'); + } + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = ((col - 1) & ~7) + 9; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + if (troff) { + const char *p = in_name, + *beg = in_name; + + while (*p) + if (*p++ == '/') + beg = p; + fprintf(output, ".Fn \"%s\"\n", beg); + } + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int is_procname; + + type_code = lexi(); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + is_procname = ps.procname[0]; + + /* + * The following code moves everything following an if (), while (), + * else, etc. up to the start of the following stmt to a buffer. This + * allows proper handling of both kinds of brace placement. + */ + + flushed_nl = false; + while (ps.search_brace) { /* if we scanned an if(), while(), + * etc., we might need to copy stuff + * into a buffer we must loop, copying + * stuff into save_com, until we find + * the start of the stmt which follows + * the if, or whatever */ + switch (type_code) { + case newline: + ++line_no; + flushed_nl = true; + case form_feed: + break; /* form feeds and newlines found here will be + * ignored */ + + case lbrace: /* this is a brace that starts the compound + * stmt */ + if (sc_end == 0) { /* ignore buffering if a comment wasn't + * stored up */ + ps.search_brace = false; + goto check_type; + } + if (btype_2) { + save_com[0] = '{'; /* we either want to put the brace + * right after the if */ + goto sw_buffer; /* go to common code to get out of + * this loop */ + } + case comment: /* we have a comment, so we must copy it into + * the buffer */ + if (!flushed_nl || sc_end != 0) { + if (sc_end == 0) { /* if this is the first comment, we + * must set up the buffer */ + save_com[0] = save_com[1] = ' '; + sc_end = &(save_com[2]); + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + + if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + } + default: /* it is the start of a normal statement */ + if (flushed_nl) /* if we flushed a newline, make sure it is + * put back */ + force_nl = true; + if ((type_code == sp_paren && *token == 'i' + && last_else && ps.else_if) + || (type_code == sp_nparen && *token == 'e' + && e_code != s_code && e_code[-1] == '}')) + force_nl = false; + + if (sc_end == 0) { /* ignore buffering if comment wasn't + * saved up */ + ps.search_brace = false; + goto check_type; + } + if (force_nl) { /* if we should insert a nl here, put it into + * the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the nl is + * read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose && !flushed_nl) /* print error msg if the line + * was not already broken */ + diag2(0, "Line broken"); + flushed_nl = false; + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; /* copy token into temp buffer */ + ps.procname[0] = 0; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + break; + } /* end of switch */ + if (type_code != 0) /* we must make this check, just in case there + * was an unexpected EOF */ + type_code = lexi(); /* read another token */ + /* if (ps.search_brace) ps.procname[0] = 0; */ + if ((is_procname = ps.procname[0]) && flushed_nl + && !procnames_start_line && ps.in_decl + && type_code == ident) + flushed_nl = 0; + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose && !flushed_nl) + diag2(0, "Line broken"); + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + *e_code++ = ' '; + for (t_ptr = s_com; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE; + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + ++ps.p_l_follow; /* count parens to make Healy happy */ + if (ps.want_blank && *token != '[' && + (ps.last_token != ident || proc_calls_space + || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) + *e_code++ = ' '; + if (ps.in_decl && !ps.block_init) + if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) { + ps.dumped_decl_indent = 1; + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + e_code += strlen(e_code); + } + else { + while ((e_code - s_code) < dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + *e_code++ = token[0]; + } + else + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + ps.want_blank = false; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + if (ps.sizeof_keyword) + ps.sizeof_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + rparen_count--; + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = false; + } else + ps.want_blank = true; + ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (ps.want_blank) + *e_code++ = ' '; + + if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) { + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } + else { + const char *res = token; + + if (ps.in_decl && !ps.block_init) { /* if this is a unary op + * in a declaration, we + * should indent this + * token */ + for (i = 0; token[i]; ++i); /* find length of token */ + while ((e_code - s_code) < (dec_ind - i)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; /* pad it */ + } + } + if (troff && token[0] == '-' && token[1] == '>') + res = "\\(->"; + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + if (ps.want_blank) + *e_code++ = ' '; + { + const char *res = token; + + if (troff) + switch (token[0]) { + case '<': + if (token[1] == '=') + res = "\\(<="; + break; + case '>': + if (token[1] == '=') + res = "\\(>="; + break; + case '!': + if (token[1] == '=') + res = "\\(!="; + break; + case '|': + if (token[1] == '|') + res = "\\(br\\(br"; + else if (token[1] == 0) + res = "\\(br"; + break; + } + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; /* move the operator */ + } + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * ?: construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the ?: construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + for (t_ptr = s_code; *t_ptr; ++t_ptr) + *e_lab++ = *t_ptr; /* turn everything so far into a label */ + e_code = s_code; + *e_lab++ = ':'; + *e_lab++ = ' '; + *e_lab = '\0'; + + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen && rparen_count == 0) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.sizeof_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest++] = dec_ind; + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case decl: /* we have a declaration type (int, register, + * etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + ps.in_parameter_declaration = 1; + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case ident: /* got an identifier or constant */ + if (ps.in_decl) { /* if we are in a declaration, we must indent + * identifier */ + if (is_procname == 0 || !procnames_start_line) { + if (!ps.block_init) { + if (troff && !ps.dumped_decl_indent) { + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } else { + int cur_dec_ind; + int pos, startpos; + + /* + * in order to get the tab math right for + * indentations that are not multiples of 8 we + * need to modify both startpos and dec_ind + * (cur_dec_ind) here by eight minus the + * remainder of the current starting column + * divided by eight. This seems to be a + * properly working fix + */ + startpos = e_code - s_code; + cur_dec_ind = dec_ind; + pos = startpos; + if ((ps.ind_level * ps.ind_size) % 8 != 0) { + pos += (ps.ind_level * ps.ind_size) % 8; + cur_dec_ind += (ps.ind_level * ps.ind_size) % 8; + } + + if (tabs_to_var) { + while ((pos & ~7) + 8 <= cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = '\t'; + pos = (pos & ~7) + 8; + } + } + while (pos < cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + pos++; + } + if (ps.want_blank && e_code - s_code == startpos) + *e_code++ = ' '; + ps.want_blank = false; + } + } + } else { + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + if (dec_ind && s_code != e_code) + dump_line(); + dec_ind = 0; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + if (ps.want_blank) + *e_code++ = ' '; + if (troff && ps.its_a_keyword) { + e_code = chfont(&bodyf, &keywordf, e_code); + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = keywordf.allcaps && islower(*t_ptr) + ? toupper(*t_ptr) : *t_ptr; + } + e_code = chfont(&keywordf, &bodyf, e_code); + } + else + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + ps.want_blank = true; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && is_procname == 0 && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB; + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (troff) + *e_lab++ = BACKSLASH; + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == 0) { /* comment on + * preprocessor line */ + if (sc_end == 0) /* if this is the first comment, we + * must set up the buffer */ + sc_end = &(save_com[0]); + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + bcopy(s_lab + com_start, sc_end, com_end - com_start); + sc_end += com_end - com_start; + if (sc_end >= &save_com[sc_size]) + abort(); + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + } + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { + if (blanklines_around_conditional_compilation) { + int c; + prefix_blankline_requested++; + while ((c = getc(input)) == '\n'); + ungetc(c, input); + } + if ((size_t)ifdef_level < sizeof(state_stack)/sizeof(state_stack[0])) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#else", 5) == 0) + if (ifdef_level <= 0) + diag2(1, "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else { + ifdef_level--; + +#ifdef undef + /* + * This match needs to be more intelligent before the + * message is useful + */ + if (match_state[ifdef_level].tos >= 0 + && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) + diag2(0, "Syntactically inconsistent #ifdef alternatives"); +#endif + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + if (flushed_nl) { /* we should force a broken line here */ + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof buff)) != 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} diff --git a/developer_cmds/indent/indent.h b/developer_cmds/indent/indent.h new file mode 100644 index 0000000..ac40f01 --- /dev/null +++ b/developer_cmds/indent/indent.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list 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. + */ + +#if 0 +__FBSDID("$FreeBSD: src/usr.bin/indent/indent.h,v 1.2 2002/03/30 17:10:20 dwmalone Exp $"); +#endif + +void addkey(char *, int); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int lexi(void); +void diag2(int, const char *); +void diag3(int, const char *, int); +void diag4(int, const char *, int, int); +void dump_line(void); +void fill_buffer(void); +void parse(int); +void parsefont(struct fstate *, const char *); +void pr_comment(void); +void set_defaults(void); +void set_option(char *); +void set_profile(void); +void writefdef(struct fstate *f, int); diff --git a/developer_cmds/indent/indent_codes.h b/developer_cmds/indent/indent_codes.h new file mode 100644 index 0000000..008bf2b --- /dev/null +++ b/developer_cmds/indent/indent_codes.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/indent/indent_codes.h,v 1.2 2000/12/09 09:52:51 obrien Exp $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 diff --git a/developer_cmds/indent/indent_globs.h b/developer_cmds/indent/indent_globs.h new file mode 100644 index 0000000..3ff82fa --- /dev/null +++ b/developer_cmds/indent/indent_globs.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/indent/indent_globs.h,v 1.12 2010/03/31 17:05:30 avg Exp $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + +#define tabsize 8 /* the size of a tab */ +#define tabmask 0177770 /* mask used when figuring length of lines + * with tabs */ + + +#define false 0 +#define true 1 + + +FILE *input; /* the fid for the input file */ +FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE \ + if (e_code >= l_code) { \ + int nsize = l_code-s_code+400; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + (e_code-s_code) + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM \ + if (e_com >= l_com) { \ + int nsize = l_com-s_com+400; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + (e_com-s_com) + 1; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB \ + if (e_lab >= l_lab) { \ + int nsize = l_lab-s_lab+400; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + (e_lab-s_lab) + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN \ + if (e_token >= l_token) { \ + int nsize = l_token-s_token+400; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + (e_token-s_token) + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +char *labbuf; /* buffer for label */ +char *s_lab; /* start ... */ +char *e_lab; /* .. and end of stored label */ +char *l_lab; /* limit of label buffer */ + +char *codebuf; /* buffer for code section */ +char *s_code; /* start ... */ +char *e_code; /* .. and end of stored code */ +char *l_code; /* limit of code section */ + +char *combuf; /* buffer for comments */ +char *s_com; /* start ... */ +char *e_com; /* ... and end of stored comments */ +char *l_com; /* limit of comment buffer */ + +#define token s_token +char *tokenbuf; /* the last token scanned */ +char *s_token; +char *e_token; +char *l_token; + +char *in_buffer; /* input buffer */ +char *in_buffer_limit; /* the end of the input buffer */ +char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +char *buf_end; /* ptr to first after last char in in_buffer */ + +char save_com[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +char *sc_end; /* pointer into save_com buffer */ + +char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +char *be_save; /* similarly saved value of buf_end */ + + +int found_err; +int pointer_as_binop; +int blanklines_after_declarations; +int blanklines_before_blockcomments; +int blanklines_after_procs; +int blanklines_around_conditional_compilation; +int swallow_optional_blanklines; +int n_real_blanklines; +int prefix_blankline_requested; +int postfix_blankline_requested; +int break_comma; /* when true and not in parens, break after a + * comma */ +int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +float case_ind; /* indentation level to be used for a "case + * n:" */ +int code_lines; /* count of lines with code */ +int had_eof; /* set to true when input is exhausted */ +int line_no; /* the current line number. */ +int max_col; /* the maximum allowable line length */ +int verbose; /* when true, non-essential error messages are + * printed */ +int cuddle_else; /* true if else should cuddle up to '}' */ +int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +int comment_delimiter_on_blankline; +int troff; /* true iff were generating troff input */ +int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +int inhibit_formatting; /* true if INDENT OFF is in effect */ +int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +int block_comment_max_col; +int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +int function_brace_split; /* split function declaration and + * brace onto separate lines */ +int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ + +/* -troff font state information */ + +struct fstate { + char font[4]; + char size; + int allcaps:1; +}; +char *chfont(struct fstate *, struct fstate *, char *); + +struct fstate + keywordf, /* keyword font */ + stringf, /* string font */ + boxcomf, /* Box comment font */ + blkcomf, /* Block comment font */ + scomf, /* Same line comment font */ + bodyf; /* major body font */ + + +#define STACKSIZE 150 + +struct parser_state { + int last_token; + struct fstate cfont; /* Current font */ + int p_stack[STACKSIZE]; /* this is the parsers stack */ + int il[STACKSIZE]; /* this stack stores indentation levels */ + float cstk[STACKSIZE];/* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta, + n_comment_delta; + int cast_mask; /* indicates which close parens close off + * casts */ + int sizeof_mask; /* indicates which close parens close off + * sizeof''s */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int its_a_keyword; + int sizeof_keyword; + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +} ps; + +int ifdef_level; +int rparen_count; +struct parser_state state_stack[5]; +struct parser_state match_state[5]; diff --git a/developer_cmds/indent/io.c b/developer_cmds/indent/io.c new file mode 100644 index 0000000..d6fd5ef --- /dev/null +++ b/developer_cmds/indent/io.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/io.c,v 1.17 2011/12/30 11:02:40 uqs Exp $"); + +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" + +int comment_open; +static int paren_target; +static int pad_output(int current, int target); + +void +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + if (troff) { + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + fprintf(output, ".Pr \"%s\"\n", ps.procname); + } + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { + if (troff) { + int all_here = 0; + char *p; + + if (e_com[-1] == '/' && e_com[-2] == '*') + e_com -= 2, all_here++; + while (e_com > s_com && e_com[-1] == ' ') + e_com--; + *e_com = 0; + p = s_com; + while (*p == ' ') + p++; + if (p[0] == '/' && p[1] == '*') + p += 2, all_here++; + else if (p[0] == '*') + p += p[1] == '/' ? 2 : 1; + while (*p == ' ') + p++; + if (*p == 0) + goto inhibit_newline; + if (comment_open < 2 && ps.box_com) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + if (comment_open == 0) { + if ('a' <= *p && *p <= 'z') + *p = *p + 'A' - 'a'; + if (e_com - p < 50 && all_here == 2) { + char *follow = p; + fprintf(output, "\n.nr C! \\w\1"); + while (follow < e_com) { + switch (*follow) { + case '\n': + putc(' ', output); + case 1: + break; + case '\\': + putc('\\', output); + default: + putc(*follow, output); + } + follow++; + } + putc(1, output); + } + fprintf(output, "\n./* %dp %d %dp\n", + ps.com_col * 7, + (s_code != e_code || s_lab != e_lab) - ps.box_com, + target_col * 7); + } + comment_open = 1 + ps.box_com; + while (*p) { + if (*p == BACKSLASH) + putc(BACKSLASH, output); + putc(*p++, output); + } + } + else { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') + com_st++, target += 8; /* ? */ + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = ((target - 1) & ~7) + 9, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace(e_com[-1])) + e_com--; + cur_col = pad_output(cur_col, target); + if (!ps.box_com) { + if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) { + if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) + com_st[1] = '*'; + else + fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); + } + } + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + cur_col = count_spaces(cur_col, com_st); + ++ps.com_lines; /* count lines with comments */ + } + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); +inhibit_newline: + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : ps.ind_size * (ps.ind_level - label_offset) + 1; +} + + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: fill_buffer + * + * FUNCTION: Reads one block of input into input_buffer + * + * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A + * Willcox of CAC Added check for switch back to partly full input + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != 0) { /* there is a partly filled input buffer left */ + buf_ptr = bp_save; /* dont read anything, just switch buffers */ + buf_end = be_save; + bp_save = be_save = 0; + if (buf_ptr < buf_end) + return; /* only return if there is really something in + * this buffer */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + if ((i = getc(f)) == EOF) { + *p++ = ' '; + *p++ = '\n'; + had_eof = true; + break; + } + *p++ = i; + if (i == '\n') + break; + } + buf_ptr = in_buffer; + buf_end = p; + if (p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column target + * nteger The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + int tcur; + + if (troff) + fprintf(output, "\\h'|%dp'", (target - 1) * 7); + else { + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { + putc('\t', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + } + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces(int current, char *buffer) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + int cur; /* current character counter */ + + cur = current; + + for (buf = buffer; *buf != '\0'; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = ((cur - 1) & tabmask) + tabsize + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + +void +writefdef(struct fstate *f, int nm) +{ + fprintf(output, ".ds f%c %s\n.nr s%c %d\n", + nm, f->font, nm, f->size); +} + +char * +chfont(struct fstate *of, struct fstate *nf, char *s) +{ + if (of->font[0] != nf->font[0] + || of->font[1] != nf->font[1]) { + *s++ = '\\'; + *s++ = 'f'; + if (nf->font[1]) { + *s++ = '('; + *s++ = nf->font[0]; + *s++ = nf->font[1]; + } + else + *s++ = nf->font[0]; + } + if (nf->size != of->size) { + *s++ = '\\'; + *s++ = 's'; + if (nf->size < of->size) { + *s++ = '-'; + *s++ = '0' + of->size - nf->size; + } + else { + *s++ = '+'; + *s++ = '0' + nf->size - of->size; + } + } + return s; +} + +void +parsefont(struct fstate *f, const char *s0) +{ + const char *s = s0; + int sizedelta = 0; + + bzero(f, sizeof *f); + while (*s) { + if (isdigit(*s)) + f->size = f->size * 10 + *s - '0'; + else if (isupper(*s)) + if (f->font[0]) + f->font[1] = *s; + else + f->font[0] = *s; + else if (*s == 'c') + f->allcaps = 1; + else if (*s == '+') + sizedelta++; + else if (*s == '-') + sizedelta--; + else { + errx(1, "bad font specification: %s", s0); + } + s++; + } + if (f->font[0] == 0) + f->font[0] = 'R'; + if (bodyf.size == 0) + bodyf.size = 11; + if (f->size == 0) + f->size = bodyf.size + sizedelta; + else if (sizedelta > 0) + f->size += bodyf.size; + else + f->size = bodyf.size - f->size; +} diff --git a/developer_cmds/indent/lexi.c b/developer_cmds/indent/lexi.c new file mode 100644 index 0000000..fbee368 --- /dev/null +++ b/developer_cmds/indent/lexi.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/lexi.c,v 1.21 2010/04/15 21:41:07 avg Exp $"); + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#define opchar 3 + +struct templ { + const char *rwd; + int rwcode; +}; + +struct templ specials[1000] = +{ + {"switch", 1}, + {"case", 2}, + {"break", 0}, + {"struct", 3}, + {"union", 3}, + {"enum", 3}, + {"default", 2}, + {"int", 4}, + {"char", 4}, + {"float", 4}, + {"double", 4}, + {"long", 4}, + {"short", 4}, + {"typdef", 4}, + {"unsigned", 4}, + {"register", 4}, + {"static", 4}, + {"global", 4}, + {"extern", 4}, + {"void", 4}, + {"const", 4}, + {"volatile", 4}, + {"goto", 0}, + {"return", 0}, + {"if", 5}, + {"while", 5}, + {"for", 5}, + {"else", 6}, + {"do", 6}, + {"sizeof", 7}, + {0, 0} +}; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +int +lexi(void) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + static int last_code; /* the last token type returned */ + static int l_struct; /* set to 1 if the last token was 'struct' */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + ps.col_1 = ps.last_nl; /* tell world that this token started in + * column 1 iff the last thing scanned was nl */ + ps.last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + ps.col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[(int)*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { + /* + * we have a character or number + */ + const char *j; /* used for searching thru list of + * + * reserved words */ + struct templ *p; + + if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + if (*buf_ptr == '0' && + (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) { + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + while (isxdigit(*buf_ptr)) { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + } + } + else + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (!isdigit(*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + while (1) { + if (!(seensfx & 1) && + (*buf_ptr == 'U' || *buf_ptr == 'u')) { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && + (*buf_ptr == 'L' || *buf_ptr == 'l')) { + CHECK_SIZE_TOKEN; + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[(int)*buf_ptr] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN; + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token++ = '\0'; + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + ps.its_a_keyword = false; + ps.sizeof_keyword = false; + if (l_struct && !ps.p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + l_struct = false; + last_code = ident; + ps.last_u_d = true; + return (decl); + } + ps.last_u_d = l_struct; /* Operator after identifier is binary + * unless last token was 'struct' */ + l_struct = false; + last_code = ident; /* Remember that this is the code we will + * return */ + + if (auto_typedefs) { + const char *q = s_token; + size_t q_len = strlen(q); + /* Check if we have an "_t" in the end */ + if (q_len > 2 && + (strcmp(q + q_len - 2, "_t") == 0)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + goto found_auto_typedef; + } + } + + /* + * This loop will check if the token is a keyword. + */ + for (p = specials; (j = p->rwd) != 0; p++) { + const char *q = s_token; /* point at scanned token */ + if (*j++ != *q++ || *j++ != *q++) + continue; /* This test depends on the fact that + * identifiers are always at least 1 character + * long (ie. the first two bytes of the + * identifier are always meaningful) */ + if (q[-1] == 0) + break; /* If its a one-character identifier */ + while (*q++ == *j) + if (*j++ == 0) + goto found_keyword; /* I wish that C had a multi-level + * break... */ + } + if (p->rwd) { /* we have a keyword */ + found_keyword: + ps.its_a_keyword = true; + ps.last_u_d = true; + switch (p->rwcode) { + case 1: /* it is a switch */ + return (swstmt); + case 2: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* + * Next time around, we will want to know that we have had a + * 'struct' + */ + l_struct = true; + /* FALLTHROUGH */ + + case 4: /* one of the declaration keywords */ + found_auto_typedef: + if (ps.p_l_follow) { + ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.sizeof_mask; + break; /* inside parens: cast, param list or sizeof */ + } + last_code = decl; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 7: + ps.sizeof_keyword = true; + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) { + char *tp = buf_ptr; + while (tp < buf_end) + if (*tp++ == ')' && (*tp == ';' || *tp == ',')) + goto not_proc; + strncpy(ps.procname, token, sizeof ps.procname - 1); + ps.in_parameter_declaration = 1; + rparen_count = 1; + not_proc:; + } + /* + * The following hack attempts to guess whether or not the current + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') + && !ps.p_l_follow + && !ps.block_init + && (ps.last_token == rparen || ps.last_token == semicolon || + ps.last_token == decl || + ps.last_token == lbrace || ps.last_token == rbrace)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + last_code = decl; + return decl; + } + if (last_code == decl) /* if this is a declared variable, then + * following sign is unary */ + ps.last_u_d = true; /* will make "int a -1" work */ + last_code = ident; + return (ident); /* the ident is not in the list */ + } /* end of procesing for alpanum character */ + + /* Scan a non-alphanumeric token */ + + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + if (troff) { + e_token[-1] = '`'; + if (qchar == '"') + *e_token++ = '`'; + e_token = chfont(&bodyf, &stringf, e_token); + } + do { /* copy the string */ + while (1) { /* move one character or [/] */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN; /* Only have to do this once in this loop, + * since CHECK_SIZE guarantees that there + * are at least 5 entries left */ + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + if (troff) { + *++e_token = BACKSLASH; + if (*buf_ptr == BACKSLASH) + *++e_token = BACKSLASH; + } + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); + if (troff) { + e_token = chfont(&stringf, &bodyf, e_token - 1); + if (qchar == '"') + *e_token++ = '\''; + } +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = ps.last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (ps.in_or_st) ps.block_init = 1; + */ + /* ? code = ps.block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = ps.block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember this so we can set 'ps.col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (last_code == ident || last_code == rparen) { + code = (ps.last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + if (!pointer_as_binop) { + unary_delim = false; + code = unary_op; + ps.want_blank = false; + } + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (ps.in_or_st) + ps.block_init = 1; +#ifdef undef + if (chartype[*buf_ptr] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = ps.last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (code != newline) { + l_struct = false; + last_code = code; + } + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + ps.last_u_d = unary_delim; + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +/* + * Add the given keyword to the keyword table, using val as the keyword type + */ +void +addkey(char *key, int val) +{ + struct templ *p = specials; + while (p->rwd) + if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) + return; + else + p++; + if (p >= specials + sizeof specials / sizeof specials[0]) + return; /* For now, table overflows are silently + * ignored */ + p->rwd = key; + p->rwcode = val; + p[1].rwd = 0; + p[1].rwcode = 0; +} diff --git a/developer_cmds/indent/parse.c b/developer_cmds/indent/parse.c new file mode 100644 index 0000000..7720ff1 --- /dev/null +++ b/developer_cmds/indent/parse.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/parse.c,v 1.10 2003/06/15 09:28:17 charnier Exp $"); + +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + ps.i_l_follow = ps.il[ps.tos]; + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have or */ + if (ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * + * + * do "dostmt" + * if "ifstmt" + * switch + * decl + * "ifelse" + * for + * while + * "dostmt" while + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* */ + case_ind = ps.cstk[ps.tos - 1]; + + case decl: /* finish of a declaration */ + case elsehead: + /* < else> */ + case forstmt: + /* */ + case whilestmt: + /* */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* */ + return; + + } /* end of section for on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/developer_cmds/indent/pr_comment.c b/developer_cmds/indent/pr_comment.c new file mode 100644 index 0000000..ad7fe2e --- /dev/null +++ b/developer_cmds/indent/pr_comment.c @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/indent/pr_comment.c,v 1.8 2003/06/15 09:28:17 charnier Exp $"); + +#include +#include +#include +#include "indent_globs.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int unix_comment; /* tri-state variable used to decide if it is + * a unix-style comment. 0 means only blanks + * since /+*, 1 means regular style comment, 2 + * means unix style comment */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + /* + * int ps.last_nl = 0; true iff the last significant thing + * weve seen is a newline + */ + int one_liner = 1; /* true iff this comment is a one-liner */ + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = 0; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + unix_comment = 1; /* set flag to let us figure out if there is a + * unix-style comment ** DISABLED: use 0 to + * reenable this hack! */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = 0; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = 0; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col < target_col) + ps.com_col = ((target_col + 7) & ~7) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + buf_ptr[-2] = 0; + ps.n_comment_delta = 1 - count_spaces(1, in_buffer); + buf_ptr[-2] = '/'; + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + *e_com = '\0'; + if (troff) { + now_col = 1; + adj_max_col = 80; + } + else + now_col = count_spaces(ps.com_col, s_com); /* figure what column we + * would be in if we + * printed the comment + * now */ + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + if (*buf_ptr > 040 && *buf_ptr != '*') + ps.last_nl = 0; + CHECK_SIZE_COM; + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = 0; + *e_com++ = ' '; + *e_com++ = '*'; + *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + *e_com = '\0'; + dump_line(); + return; + } + one_liner = 0; + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) { + *e_com++ = ' '; + *e_com++ = ' '; + } + *e_com = '\0'; + if (!ps.box_com && e_com - s_com > 3) { + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + dump_line(); + CHECK_SIZE_COM; + *e_com++ = ' '; + *e_com++ = ' '; + } + dump_line(); + now_col = ps.com_col; + } + else { + ps.last_nl = 1; + if (unix_comment != 1) { /* we not are in unix_style + * comment */ + if (unix_comment == 0 && s_code == e_code) { + /* + * if it is a UNIX-style comment, ignore the + * requirement that previous line be blank for + * unindention + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + if (ps.com_col <= 1) + ps.com_col = 2; + } + unix_comment = 2; /* permanently remember that we are in + * this type of comment */ + dump_line(); + ++line_no; + now_col = ps.com_col; + *e_com++ = ' '; + /* + * fix so that the star at the start of the line will line + * up + */ + do /* flush leading white space */ + if (++buf_ptr >= buf_end) + fill_buffer(); + while (*buf_ptr == ' ' || *buf_ptr == '\t'); + break; + } + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + CHECK_SIZE_COM; + *e_com++ = ' '; + ++now_col; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + + if (unix_comment == 0) /* set flag to show we are not in + * unix-style comment */ + unix_comment = 1; + + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + + if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before + * end */ + *e_com++ = ' '; + ++now_col; + } + if (break_delim == 1 && !one_liner && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (break_delim == 2 && e_com > s_com + 3 + /* now_col > adj_max_col - 2 && !ps.box_com */ ) { + *e_com = '\0'; + dump_line(); + now_col = ps.com_col; + } + CHECK_SIZE_COM; + *e_com++ = '*'; + *e_com++ = '/'; + *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else { /* handle isolated '*' */ + *e_com++ = '*'; + ++now_col; + } + break; + default: /* we have a random char */ + if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') + unix_comment = 1; /* we are not in unix-style comment */ + + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*e_com == '\t') /* keep track of column */ + now_col = ((now_col - 1) & tabmask) + tabsize + 1; + else if (*e_com == '\b') /* this is a backspace */ + --now_col; + else + ++now_col; + + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; + /* remember we saw a blank */ + + ++e_com; + if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (last_bl == 0) { /* we have seen no blanks */ + last_bl = e_com; /* fake it */ + *e_com++ = ' '; + } + *e_com = '\0'; /* print what we have */ + *last_bl = '\0'; + while (last_bl > s_com && last_bl[-1] < 040) + *--last_bl = 0; + e_com = last_bl; + dump_line(); + + *e_com++ = ' '; /* add blanks for continuation */ + *e_com++ = ' '; + *e_com++ = ' '; + + t_ptr = last_bl + 1; + last_bl = 0; + if (t_ptr >= e_com) { + while (*t_ptr == ' ' || *t_ptr == '\t') + t_ptr++; + while (*t_ptr != '\0') { /* move unprinted part of + * comment down in buffer */ + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + *e_com = '\0'; + now_col = count_spaces(ps.com_col, s_com); /* recompute current + * position */ + } + break; + } + } +} diff --git a/developer_cmds/lorder/lorder.1 b/developer_cmds/lorder/lorder.1 new file mode 100644 index 0000000..45fe0e6 --- /dev/null +++ b/developer_cmds/lorder/lorder.1 @@ -0,0 +1,75 @@ +.\" $NetBSD: lorder.1,v 1.6 1997/10/19 04:21:49 lukem Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. 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. +.\" +.\" @(#)lorder.1 8.2 (Berkeley) 4/28/95 +.\" +.Dd April 28, 1995 +.Dt LORDER 1 +.Os +.Sh NAME +.Nm lorder +.Nd list dependencies for object files +.Sh SYNOPSIS +.Nm +.Ar +.Sh DESCRIPTION +The +.Nm +utility uses +.Xr nm 1 +to determine interdependencies in the list of object files +specified on the command line. +.Nm +outputs a list of file names where the first file contains a symbol +which is defined by the second file. +.Pp +The output is normally used with +.Xr tsort 1 +when a library is created to determine the optimum ordering of the +object modules so that all references may be resolved in a single +pass of the loader. +.Sh EXAMPLES +.Bd -literal -offset indent +ar cr library.a `lorder ${OBJS} | tsort` +.Ed +.Sh SEE ALSO +.Xr ar 1 , +.Xr ld 1 , +.Xr nm 1 , +.Xr ranlib 1 , +.Xr tsort 1 +.Sh HISTORY +An +.Nm +utility appeared in +.At v7 . diff --git a/developer_cmds/lorder/lorder.sh b/developer_cmds/lorder/lorder.sh new file mode 100644 index 0000000..b6ed479 --- /dev/null +++ b/developer_cmds/lorder/lorder.sh @@ -0,0 +1,104 @@ +#!/bin/sh - +# $NetBSD: lorder.sh,v 1.7 1998/04/09 05:28:07 fair Exp $ +# +# Copyright (c) 1990, 1993 +# The Regents of the University of California. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. 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. +# +# @(#)lorder.sh 8.1 (Berkeley) 6/6/93 +# + +# If the user has set ${NM} then we use it, otherwise we use 'nm'. +# We try to find the compiler in the user's path, and if that fails we +# try to find it in the default path. If we can't find it, we punt. +# Once we find it, we canonicalize its name and set the path to the +# default path so that other commands we use are picked properly. + +if ! type "${NM:=nm}" > /dev/null 2>&1; then + PATH=/bin:/usr/bin + export PATH + if ! type "${NM}" > /dev/null 2>&1; then + echo "lorder: ${NM}: not found" + exit 1 + fi +fi +cmd='set `type "${NM}"` ; eval echo \$$#' +NM=`eval $cmd` + +# only one argument is a special case, just output the name twice +case $# in + 0) + echo "usage: lorder file ..."; + exit ;; + 1) + echo $1 $1; + exit ;; +esac + +# temporary files +R=/tmp/_reference_$$ +S=/tmp/_symbol_$$ + +# remove temporary files on HUP, INT, QUIT, PIPE, TERM +trap "rm -f $R $S; exit 1" 1 2 3 13 15 + +# if the line ends in a colon, assume it's the first occurrence of a new +# object file. Echo it twice, just to make sure it gets into the output. +# +# if the line has " T " or " D " it's a globally defined symbol, put it +# into the symbol file. +# +# if the line has " U " it's a globally undefined symbol, put it into +# the reference file. +(for file in $* ; do echo $file":" ; done ; $NM -go $*) | sed " + /:$/ { + s/:// + s/.*/& &/ + p + d + } + / [TDGR] / { + s/:.* [TDGR] / / + w $S + d + } + / U / { + s/:.* U / / + w $R + } + d +" + +# sort symbols and references on the first field (the symbol) +# join on that field, and print out the file names. +sort -k 2 $R -o $R +sort -k 2 $S -o $S +join -j 2 -o "1.1 2.1" $R $S +rm -f $R $S diff --git a/developer_cmds/rpcgen/rpc_clntout.c b/developer_cmds/rpcgen/rpc_clntout.c new file mode 100644 index 0000000..e0d2263 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_clntout.c @@ -0,0 +1,230 @@ +/* $NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_clntout.c,v 1.8 1997/10/18 10:53:37 lukem Exp $"); +#endif +#endif + +/* + * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsytsems, Inc. + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static void write_program __P((definition *)); +static char *ampr __P((char *)); +static void printbody __P((proc_list *)); + +#define DEFAULT_TIMEOUT 25 /* in seconds */ +static char RESULT[] = "clnt_res"; + + +void +write_stubs() +{ + list *l; + definition *def; + + f_print(fout, + "\n/* Default timeout can be changed using clnt_control() */\n"); + f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n", + DEFAULT_TIMEOUT); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_program(def); + } + } +} + +static void +write_program(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*\n"); + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, "clnt", "CLIENT *"); + f_print(fout, "{\n"); + printbody(proc); + f_print(fout, "}\n"); + } + } +} +/* Writes out declarations of procedure's argument list. + In either ANSI C style, in one of old rpcgen style (pass by reference), + or new rpcgen style (multiple arguments, pass by value); + */ + +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ + +void +printarglist(proc, addargname, addargtype) + proc_list *proc; + char *addargname, *addargtype; +{ + + decl_list *l; + + if (!newstyle) { /* old style: always pass argument by + * reference */ + if (Cflag) { /* C++ style heading */ + f_print(fout, "("); + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + f_print(fout, "*argp, %s%s)\n", addargtype, addargname); + } else { + f_print(fout, "(argp, %s)\n", addargname); + f_print(fout, "\t"); + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + f_print(fout, "*argp;\n"); + } + } else + if (streq(proc->args.decls->decl.type, "void")) { + /* newstyle, 0 argument */ + if (Cflag) + f_print(fout, "(%s%s)\n", addargtype, addargname); + else + f_print(fout, "(%s)\n", addargname); + } else { + /* new style, 1 or multiple arguments */ + if (!Cflag) { + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + f_print(fout, "%s, ", l->decl.name); + f_print(fout, "%s)\n", addargname); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 1, ";\n"); + } + } else {/* C++ style header */ + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pdeclaration(proc->args.argname, &l->decl, 0, ", "); + } + f_print(fout, " %s%s)\n", addargtype, addargname); + } + } + + if (!Cflag) + f_print(fout, "\t%s%s;\n", addargtype, addargname); +} + + + +static char * +ampr(type) + char *type; +{ + if (isvectordef(type, REL_ALIAS)) { + return (""); + } else { + return ("&"); + } +} + +static void +printbody(proc) + proc_list *proc; +{ + decl_list *l; + bool_t args2 = (proc->arg_num > 1); + + /* For new style with multiple arguments, need a structure in which to + * stuff the arguments. */ + if (newstyle && args2) { + f_print(fout, "\t%s", proc->args.argname); + f_print(fout, " arg;\n"); + } + f_print(fout, "\tstatic "); + if (streq(proc->res_type, "void")) { + f_print(fout, "char "); + } else { + ptype(proc->res_prefix, proc->res_type, 0); + } + f_print(fout, "%s;\n", RESULT); + f_print(fout, "\n"); + f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n", + ampr(proc->res_type), RESULT, RESULT); + if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) { + /* newstyle, 0 arguments */ + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_void", proc->proc_name); + f_print(fout, + ", NULL, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS) {\n", + stringfix(proc->res_type), ampr(proc->res_type), RESULT); + + } else + if (newstyle && args2) { + /* newstyle, multiple arguments: stuff arguments into + * structure */ + for (l = proc->args.decls; l != NULL; l = l->next) { + f_print(fout, "\targ.%s = %s;\n", + l->decl.name, l->decl.name); + } + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_%s, &arg, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n", + proc->proc_name, + proc->args.argname, + stringfix(proc->res_type), + ampr(proc->res_type), RESULT); + } else { /* single argument, new or old style */ + f_print(fout, + "\tif (clnt_call(clnt, %s, xdr_%s, %s%s, xdr_%s, %s%s, TIMEOUT) != RPC_SUCCESS)\n", + proc->proc_name, + stringfix(proc->args.decls->decl.type), + (newstyle ? "&" : ""), + (newstyle ? proc->args.decls->decl.name : "argp"), + stringfix(proc->res_type), + ampr(proc->res_type), RESULT); + } + f_print(fout, "\t\treturn (NULL);\n"); + if (streq(proc->res_type, "void")) { + f_print(fout, "\treturn ((void *)%s%s);\n", + ampr(proc->res_type), RESULT); + } else { + f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT); + } +} diff --git a/developer_cmds/rpcgen/rpc_cout.c b/developer_cmds/rpcgen/rpc_cout.c new file mode 100644 index 0000000..ca4eb7b --- /dev/null +++ b/developer_cmds/rpcgen/rpc_cout.c @@ -0,0 +1,741 @@ +/* $NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_cout.c,v 1.14 1998/08/25 20:59:40 ross Exp $"); +#endif +#endif + +/* + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler + */ +#include +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static int findtype __P((definition *, char *)); +static int undefined __P((char *)); +static void print_generic_header __P((char *, int)); +static void print_header __P((definition *)); +static void print_prog_header __P((proc_list *)); +static void print_trailer __P((void)); +static void print_ifopen __P((int, char *)); +static void print_ifarg __P((char *)); +static void print_ifsizeof __P((char *, char *)); +static void print_ifclose __P((int)); +static void print_ifstat __P((int, char *, char *, relation, char *, char *, char *)); +static void emit_enum __P((definition *)); +static void emit_program __P((definition *)); +static void emit_union __P((definition *)); +static void emit_struct __P((definition *)); +static void emit_typedef __P((definition *)); +static void print_stat __P((int, declaration *)); + +/* + * Emit the C-routine for the given definition + */ +void +emit(def) + definition *def; +{ + if (def->def_kind == DEF_CONST) { + return; + } + if (def->def_kind == DEF_PROGRAM) { + emit_program(def); + return; + } + if (def->def_kind == DEF_TYPEDEF) { + /* now we need to handle declarations like struct typedef foo + * foo; since we dont want this to be expanded into 2 calls to + * xdr_foo */ + + if (strcmp(def->def.ty.old_type, def->def_name) == 0) + return; + }; + + print_header(def); + + switch (def->def_kind) { + case DEF_UNION: + emit_union(def); + break; + case DEF_ENUM: + emit_enum(def); + break; + case DEF_STRUCT: + emit_struct(def); + break; + case DEF_TYPEDEF: + emit_typedef(def); + break; + case DEF_PROGRAM: + case DEF_CONST: + errx(1, "Internal error %s, %d: Case %d not handled\n", + __FILE__, __LINE__, def->def_kind); + break; + } + print_trailer(); +} + +static int +findtype(def, type) + definition *def; + char *type; +{ + + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) { + return (0); + } else { + return (streq(def->def_name, type)); + } +} + +static int +undefined(type) + char *type; +{ + definition *def; + + def = (definition *) FINDVAL(defined, type, findtype); + + + return (def == NULL); +} + +static void +print_generic_header(procname, pointerp) + char *procname; + int pointerp; +{ + f_print(fout, "\n"); + f_print(fout, "bool_t\n"); + if (Cflag) { + f_print(fout, "xdr_%s(", procname); + f_print(fout, "XDR *xdrs, "); + f_print(fout, "%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp)\n{\n"); + } else { + f_print(fout, "xdr_%s(xdrs, objp)\n", procname); + f_print(fout, "\tXDR *xdrs;\n"); + f_print(fout, "\t%s ", procname); + if (pointerp) + f_print(fout, "*"); + f_print(fout, "objp;\n{\n"); + } +} + +static void +print_header(def) + definition *def; +{ + print_generic_header(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); +} + +static void +print_prog_header(plist) + proc_list *plist; +{ + print_generic_header(plist->args.argname, 1); +} + +static void +print_trailer() +{ + f_print(fout, "\treturn (TRUE);\n"); + f_print(fout, "}\n"); +} + + +static void +print_ifopen(indent, name) + int indent; + char *name; +{ + tabify(fout, indent); + f_print(fout, "if (!xdr_%s(xdrs", name); +} + +static void +print_ifarg(arg) + char *arg; +{ + f_print(fout, ", %s", arg); +} + +static void +print_ifsizeof(prefix, type) + char *prefix; + char *type; +{ + if (streq(type, "bool")) { + f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool"); + } else { + f_print(fout, ", sizeof("); + if (undefined(type) && prefix) { + f_print(fout, "%s ", prefix); + } + f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type); + } +} + +static void +print_ifclose(indent) + int indent; +{ + f_print(fout, "))\n"); + tabify(fout, indent); + f_print(fout, "\treturn (FALSE);\n"); +} + +static void +print_ifstat(indent, prefix, type, rel, amax, objname, name) + int indent; + char *prefix; + char *type; + relation rel; + char *amax; + char *objname; + char *name; +{ + char *alt = NULL; + + switch (rel) { + case REL_POINTER: + print_ifopen(indent, "pointer"); + print_ifarg("(char **)"); + f_print(fout, "%s", objname); + print_ifsizeof(prefix, type); + break; + case REL_VECTOR: + if (streq(type, "string")) { + alt = "string"; + } else + if (streq(type, "opaque")) { + alt = "opaque"; + } + if (alt) { + print_ifopen(indent, alt); + print_ifarg(objname); + } else { + print_ifopen(indent, "vector"); + print_ifarg("(char *)"); + f_print(fout, "%s", objname); + } + print_ifarg(amax); + if (!alt) { + print_ifsizeof(prefix, type); + } + break; + case REL_ARRAY: + if (streq(type, "string")) { + alt = "string"; + } else + if (streq(type, "opaque")) { + alt = "bytes"; + } + if (streq(type, "string")) { + print_ifopen(indent, alt); + print_ifarg(objname); + } else { + if (alt) { + print_ifopen(indent, alt); + } else { + print_ifopen(indent, "array"); + } + print_ifarg("(char **)"); + if (*objname == '&') { + f_print(fout, "%s.%s_val, (u_int *)%s.%s_len", + objname, name, objname, name); + } else { + f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len", + objname, name, objname, name); + } + } + print_ifarg(amax); + if (!alt) { + print_ifsizeof(prefix, type); + } + break; + case REL_ALIAS: + print_ifopen(indent, type); + print_ifarg(objname); + break; + } + print_ifclose(indent); +} +/* ARGSUSED */ +static void +emit_enum(def) + definition *def; +{ + fprintf(fout, "\n"); + print_ifopen(1, "enum"); + print_ifarg("(enum_t *)objp"); + print_ifclose(1); +} + +static void +emit_program(def) + definition *def; +{ + decl_list *dl; + version_list *vlist; + proc_list *plist; + + for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) + for (plist = vlist->procs; plist != NULL; plist = plist->next) { + if (!newstyle || plist->arg_num < 2) + continue; /* old style, or single + * argument */ + print_prog_header(plist); + for (dl = plist->args.decls; dl != NULL; + dl = dl->next) + print_stat(1, &dl->decl); + print_trailer(); + } +} + + +static void +emit_union(def) + definition *def; +{ + declaration *dflt; + case_list *cl; + declaration *cs; + char *object; + char *vecformat = "objp->%s_u.%s"; + char *format = "&objp->%s_u.%s"; + + f_print(fout, "\n"); + print_stat(1, &def->def.un.enum_decl); + f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); + for (cl = def->def.un.cases; cl != NULL; cl = cl->next) { + f_print(fout, "\tcase %s:\n", cl->case_name); + if (cl->contflag == 1) /* a continued case statement */ + continue; + cs = &cl->case_decl; + if (!streq(cs->type, "void")) { + object = alloc(strlen(def->def_name) + strlen(format) + + strlen(cs->name) + 1); + if (isvectordef(cs->type, cs->rel)) { + s_print(object, vecformat, def->def_name, + cs->name); + } else { + s_print(object, format, def->def_name, + cs->name); + } + print_ifstat(2, cs->prefix, cs->type, cs->rel, + cs->array_max, object, cs->name); + free(object); + } + f_print(fout, "\t\tbreak;\n"); + } + dflt = def->def.un.default_decl; + f_print(fout, "\tdefault:\n"); + if (dflt != NULL) { + if (!streq(dflt->type, "void")) { + object = alloc(strlen(def->def_name) + strlen(format) + + strlen(dflt->name) + 1); + if (isvectordef(dflt->type, dflt->rel)) { + s_print(object, vecformat, def->def_name, + dflt->name); + } else { + s_print(object, format, def->def_name, + dflt->name); + } + print_ifstat(2, dflt->prefix, dflt->type, dflt->rel, + dflt->array_max, object, dflt->name); + free(object); + } + f_print(fout, "\t\tbreak;\n"); + } else { + f_print(fout, "\t\treturn (FALSE);\n"); + } + + f_print(fout, "\t}\n"); +} + +static void +emit_struct(def) + definition *def; +{ + decl_list *dl; + int i, j, size, flag; + decl_list *cur = NULL, *psav; + bas_type *ptr; + char *sizestr, *plus; + char ptemp[256]; + int can_inline; + + + if (doinline == 0) { + fprintf(fout, "\n"); + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; + } + size = 0; + can_inline = 0; + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if ((dl->decl.prefix == NULL) && + ((ptr = find_type(dl->decl.type)) != NULL) && + ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { + + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else { + can_inline = 1; + break; /* can be inlined */ + }; + } else { + if (size >= doinline) { + can_inline = 1; + break; /* can be inlined */ + } + size = 0; + } + if (size > doinline) + can_inline = 1; + + if (can_inline == 0) { /* can not inline, drop back to old mode */ + fprintf(fout, "\n"); + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(1, &dl->decl); + return; + }; + + /* May cause lint to complain. but ... */ + f_print(fout, "\tint32_t *buf;\n"); + + flag = PUT; + f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); + + for (j = 0; j < 2; j++) { + i = 0; + size = 0; + sizestr = NULL; + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */ + + /* now walk down the list and check for basic types */ + if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) { + if (i == 0) + cur = dl; + i++; + + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else { + /* this is required to handle arrays */ + + if (sizestr == NULL) + plus = ""; + else + plus = " + "; + + if (ptr->length != 1) + s_print(ptemp, "%s%s * %d", plus, dl->decl.array_max, ptr->length); + else + s_print(ptemp, "%s%s", plus, dl->decl.array_max); + + /* now concatenate to sizestr !!!! */ + if (sizestr == NULL) + sizestr = strdup(ptemp); + else { + sizestr = (char *) realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1); + if (sizestr == NULL) { + + f_print(stderr, "Fatal error : no memory\n"); + crash(); + }; + sizestr = strcat(sizestr, ptemp); /* build up length of + * array */ + + } + } + + } else { + if (i > 0) { + if (sizestr == NULL && size < doinline) { + /* don't expand into inline + * code if size < doinline */ + while (cur != dl) { + print_stat(2, &cur->decl); + cur = cur->next; + } + } else { + + + + /* were already looking at a + * xdr_inlineable structure */ + if (sizestr == NULL) + f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", + size); + else + if (size == 0) + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", + sizestr); + else + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", + size, sizestr); + + f_print(fout, "\t\tif (buf == NULL) {\n"); + + psav = cur; + while (cur != dl) { + print_stat(3, &cur->decl); + cur = cur->next; + } + + f_print(fout, "\t\t} else {\n"); + + cur = psav; + while (cur != dl) { + emit_inline(&cur->decl, flag); + cur = cur->next; + } + + f_print(fout, "\t\t}\n"); + } + } + size = 0; + i = 0; + sizestr = NULL; + print_stat(2, &dl->decl); + } + + } + if (i > 0) { + if (sizestr == NULL && size < doinline) { + /* don't expand into inline code if size < + * doinline */ + while (cur != dl) { + print_stat(2, &cur->decl); + cur = cur->next; + } + } else { + + /* were already looking at a xdr_inlineable + * structure */ + if (sizestr == NULL) + f_print(fout, "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);\n", + size); + else + if (size == 0) + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, %s * BYTES_PER_XDR_UNIT);\n", + sizestr); + else + f_print(fout, + "\t\tbuf = (int32_t *)XDR_INLINE(xdrs, (%d + %s) * BYTES_PER_XDR_UNIT);\n", + size, sizestr); + + f_print(fout, "\t\tif (buf == NULL) {\n"); + + psav = cur; + while (cur != NULL) { + print_stat(3, &cur->decl); + cur = cur->next; + } + f_print(fout, "\t\t} else {\n"); + + cur = psav; + while (cur != dl) { + emit_inline(&cur->decl, flag); + cur = cur->next; + } + + f_print(fout, "\t\t}\n"); + + } + } + if (flag == PUT) { + flag = GET; + f_print(fout, "\t} else if (xdrs->x_op == XDR_DECODE) {\n"); + } + } + + f_print(fout, "\t} else {\n"); + + /* now take care of XDR_FREE case */ + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat(2, &dl->decl); + + f_print(fout, "\t}\n"); +} + +static void +emit_typedef(def) + definition *def; +{ + char *prefix = def->def.ty.old_prefix; + char *type = def->def.ty.old_type; + char *amax = def->def.ty.array_max; + relation rel = def->def.ty.rel; + + fprintf(fout, "\n"); + print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name); +} + +static void +print_stat(indent, dec) + declaration *dec; + int indent; +{ + char *prefix = dec->prefix; + char *type = dec->type; + char *amax = dec->array_max; + relation rel = dec->rel; + char name[256]; + + if (isvectordef(type, rel)) { + s_print(name, "objp->%s", dec->name); + } else { + s_print(name, "&objp->%s", dec->name); + } + print_ifstat(indent, prefix, type, rel, amax, name, dec->name); +} + + +void +emit_inline(decl, flag) + declaration *decl; + int flag; +{ + +/*check whether an array or not */ + + switch (decl->rel) { + case REL_ALIAS: + emit_single_in_line(decl, flag, REL_ALIAS); + break; + case REL_VECTOR: + f_print(fout, "\t\t\t{\n"); + f_print(fout, "\t\t\t\tint i;\n"); + f_print(fout, "\t\t\t\t%s *genp;\n", decl->type); + f_print(fout, "\n"); + f_print(fout, "\t\t\t\tfor (i = 0, genp = objp->%s;\n", + decl->name); + f_print(fout, "\t\t\t\t i < %s; i++) {\n\t\t", + decl->array_max); + emit_single_in_line(decl, flag, REL_VECTOR); + f_print(fout, "\t\t\t\t}\n\t\t\t}\n"); + break; + case REL_ARRAY: + case REL_POINTER: + errx(1, "Internal error %s, %d: Case %d not handled\n", + __FILE__, __LINE__, decl->rel); + } +} + +void +emit_single_in_line(decl, flag, rel) + declaration *decl; + int flag; + relation rel; +{ + char *upp_case; + int freed = 0; + + if (flag == PUT) + f_print(fout, "\t\t\tIXDR_PUT_"); + else + if (rel == REL_ALIAS) + f_print(fout, "\t\t\tobjp->%s = IXDR_GET_", decl->name); + else + f_print(fout, "\t\t\t*genp++ = IXDR_GET_"); + + upp_case = upcase(decl->type); + + /* hack - XX */ + if (strcmp(upp_case, "INT") == 0) { + free(upp_case); + freed = 1; + upp_case = "LONG"; + } + if (strcmp(upp_case, "U_INT") == 0) { + free(upp_case); + freed = 1; + upp_case = "U_LONG"; + } + if (flag == PUT) + if (rel == REL_ALIAS) + f_print(fout, "%s(buf, objp->%s);\n", upp_case, decl->name); + else + f_print(fout, "%s(buf, *genp++);\n", upp_case); + + else + f_print(fout, "%s(buf);\n", upp_case); + if (!freed) + free(upp_case); + +} + + +char * +upcase(str) + char *str; +{ + char *ptr, *hptr; + + + ptr = (char *) malloc(strlen(str) + 1); + if (ptr == (char *) NULL) { + f_print(stderr, "malloc failed\n"); + exit(1); + }; + + hptr = ptr; + while (*str != '\0') + *ptr++ = toupper(*str++); + + *ptr = '\0'; + return (hptr); + +} diff --git a/developer_cmds/rpcgen/rpc_hout.c b/developer_cmds/rpcgen/rpc_hout.c new file mode 100644 index 0000000..3b8811f --- /dev/null +++ b/developer_cmds/rpcgen/rpc_hout.c @@ -0,0 +1,534 @@ +/* $NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_hout.c,v 1.9 1998/02/11 23:11:17 lukem Exp $"); +#endif +#endif + +/* + * rpc_hout.c, Header file outputter for the RPC protocol compiler + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static void pconstdef __P((definition *)); +static void pargdef __P((definition *)); +static void pstructdef __P((definition *)); +static void puniondef __P((definition *)); +static void pdefine __P((char *, char *)); +static void puldefine __P((char *, char *)); +static int define_printed __P((proc_list *, version_list *)); +static void pprogramdef __P((definition *)); +static void parglist __P((proc_list *, char *)); +static void penumdef __P((definition *)); +static void ptypedef __P((definition *)); +static int undefined2 __P((char *, char *)); + +/* + * Print the C-version of an xdr definition + */ +void +print_datadef(def) + definition *def; +{ + + if (def->def_kind == DEF_PROGRAM) /* handle data only */ + return; + + if (def->def_kind != DEF_CONST) { + f_print(fout, "\n"); + } + switch (def->def_kind) { + case DEF_STRUCT: + pstructdef(def); + break; + case DEF_UNION: + puniondef(def); + break; + case DEF_ENUM: + penumdef(def); + break; + case DEF_TYPEDEF: + ptypedef(def); + break; + case DEF_PROGRAM: + pprogramdef(def); + break; + case DEF_CONST: + pconstdef(def); + break; + } + if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) { + pxdrfuncdecl(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, def->def.ty.rel)); + + } +} + + +void +print_funcdef(def) + definition *def; +{ + switch (def->def_kind) { + case DEF_PROGRAM: + f_print(fout, "\n"); + pprogramdef(def); + break; + case DEF_CONST: + case DEF_TYPEDEF: + case DEF_ENUM: + case DEF_UNION: + case DEF_STRUCT: + break; + } +} + +void +pxdrfuncdecl(name, pointerp) + char *name; + int pointerp; +{ + + f_print(fout, "#ifdef __cplusplus\n"); + f_print(fout, "extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n", + name, + name, pointerp ? ("*") : ""); + f_print(fout, "#elif __STDC__\n"); + f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", + name, + name, pointerp ? ("*") : ""); + f_print(fout, "#else /* Old Style C */\n"); + f_print(fout, "bool_t xdr_%s();\n", name); + f_print(fout, "#endif /* Old Style C */\n\n"); +} + + +static void +pconstdef(def) + definition *def; +{ + pdefine(def->def_name, def->def.co); +} +/* print out the definitions for the arguments of functions in the + header file +*/ +static void +pargdef(def) + definition *def; +{ + decl_list *l; + version_list *vers; + char *name; + proc_list *plist; + + + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { + for (plist = vers->procs; plist != NULL; + plist = plist->next) { + + if (!newstyle || plist->arg_num < 2) { + continue; /* old style or single args */ + } + name = plist->args.argname; + f_print(fout, "struct %s {\n", name); + for (l = plist->args.decls; + l != NULL; l = l->next) { + pdeclaration(name, &l->decl, 1, ";\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); + pxdrfuncdecl(name, 0); + f_print(fout, "\n"); + } + } + +} + + +static void +pstructdef(def) + definition *def; +{ + decl_list *l; + char *name = def->def_name; + + f_print(fout, "struct %s {\n", name); + for (l = def->def.st.decls; l != NULL; l = l->next) { + pdeclaration(name, &l->decl, 1, ";\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); +} + +static void +puniondef(def) + definition *def; +{ + case_list *l; + char *name = def->def_name; + declaration *decl; + + f_print(fout, "struct %s {\n", name); + decl = &def->def.un.enum_decl; + if (streq(decl->type, "bool")) { + f_print(fout, "\tbool_t %s;\n", decl->name); + } else { + f_print(fout, "\t%s %s;\n", decl->type, decl->name); + } + f_print(fout, "\tunion {\n"); + for (l = def->def.un.cases; l != NULL; l = l->next) { + if (l->contflag == 0) + pdeclaration(name, &l->case_decl, 2, ";\n"); + } + decl = def->def.un.default_decl; + if (decl && !streq(decl->type, "void")) { + pdeclaration(name, decl, 2, ";\n"); + } + f_print(fout, "\t} %s_u;\n", name); + f_print(fout, "};\n"); + f_print(fout, "typedef struct %s %s;\n", name, name); +} + +static void +pdefine(name, num) + char *name; + char *num; +{ + f_print(fout, "#define %s %s\n", name, num); +} + +static void +puldefine(name, num) + char *name; + char *num; +{ + f_print(fout, "#define %s ((rpc_uint)%s)\n", name, num); +} + +static int +define_printed(stop, start) + proc_list *stop; + version_list *start; +{ + version_list *vers; + proc_list *proc; + + for (vers = start; vers != NULL; vers = vers->next) { + for (proc = vers->procs; proc != NULL; proc = proc->next) { + if (proc == stop) { + return (0); + } else + if (streq(proc->proc_name, stop->proc_name)) { + return (1); + } + } + } + errx(1, "Internal error %s, %d: procedure not found\n", + __FILE__, __LINE__); + /* NOTREACHED */ +} + +static void +pprogramdef(def) + definition *def; +{ + version_list *vers; + proc_list *proc; + int i; + char *ext; + + pargdef(def); + + puldefine(def->def_name, def->def.pr.prog_num); + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { + if (tblflag) { + f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n", + locase(def->def_name), vers->vers_num); + f_print(fout, "extern %s_%s_nproc;\n", + locase(def->def_name), vers->vers_num); + } + puldefine(vers->vers_name, vers->vers_num); + + /* Print out 3 definitions, one for ANSI-C, another for C++, a + * third for old style C */ + + for (i = 0; i < 3; i++) { + if (i == 0) { + f_print(fout, "\n#ifdef __cplusplus\n"); + ext = "extern \"C\" "; + } else + if (i == 1) { + f_print(fout, "\n#elif __STDC__\n"); + ext = "extern "; + } else { + f_print(fout, "\n#else /* Old Style C */\n"); + ext = "extern "; + } + + + for (proc = vers->procs; proc != NULL; proc = proc->next) { + if (!define_printed(proc, def->def.pr.versions)) { + puldefine(proc->proc_name, proc->proc_num); + } + f_print(fout, "%s", ext); + pprocdef(proc, vers, "CLIENT *", 0, i); + f_print(fout, "%s", ext); + pprocdef(proc, vers, "struct svc_req *", 1, i); + + } + + } + f_print(fout, "#endif /* Old Style C */\n"); + } +} + +void +pprocdef(proc, vp, addargtype, server_p, mode) + proc_list *proc; + version_list *vp; + char *addargtype; + int server_p; + int mode; +{ + + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "* "); + if (server_p) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + + /* + * mode 0 == cplusplus, mode 1 = ANSI-C, mode 2 = old style C + */ + if (mode == 0 || mode == 1) + parglist(proc, addargtype); + else + f_print(fout, "();\n"); +} + + +/* print out argument list of procedure */ +static void +parglist(proc, addargtype) + proc_list *proc; + char *addargtype; +{ + decl_list *dl; + + f_print(fout, "("); + + if (proc->arg_num < 2 && newstyle && + streq(proc->args.decls->decl.type, "void")) { + /* 0 argument in new style: do nothing */ + } else { + for (dl = proc->args.decls; dl != NULL; dl = dl->next) { + ptype(dl->decl.prefix, dl->decl.type, 1); + if (!newstyle) + f_print(fout, "*"); /* old style passes by + * reference */ + + f_print(fout, ", "); + } + } + + f_print(fout, "%s);\n", addargtype); +} + +static void +penumdef(def) + definition *def; +{ + char *name = def->def_name; + enumval_list *l; + char *last = NULL; + int count = 0; + + f_print(fout, "enum %s {\n", name); + for (l = def->def.en.vals; l != NULL; l = l->next) { + f_print(fout, "\t%s", l->name); + if (l->assignment) { + f_print(fout, " = %s", l->assignment); + last = l->assignment; + count = 1; + } else { + if (last == NULL) { + f_print(fout, " = %d", count++); + } else { + f_print(fout, " = %s + %d", last, count++); + } + } + f_print(fout, ",\n"); + } + f_print(fout, "};\n"); + f_print(fout, "typedef enum %s %s;\n", name, name); +} + +static void +ptypedef(def) + definition *def; +{ + char *name = def->def_name; + char *old = def->def.ty.old_type; + char prefix[8]; /* enough to contain "struct ", including NUL */ + relation rel = def->def.ty.rel; + + + if (!streq(name, old)) { + if (streq(old, "string")) { + old = "char"; + rel = REL_POINTER; + } else + if (streq(old, "opaque")) { + old = "char"; + } else + if (streq(old, "bool")) { + old = "bool_t"; + } + if (undefined2(old, name) && def->def.ty.old_prefix) { + s_print(prefix, "%s ", def->def.ty.old_prefix); + } else { + prefix[0] = 0; + } + f_print(fout, "typedef "); + switch (rel) { + case REL_ARRAY: + f_print(fout, "struct {\n"); + f_print(fout, "\tu_int %s_len;\n", name); + f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name); + f_print(fout, "} %s", name); + break; + case REL_POINTER: + f_print(fout, "%s%s *%s", prefix, old, name); + break; + case REL_VECTOR: + f_print(fout, "%s%s %s[%s]", prefix, old, name, + def->def.ty.array_max); + break; + case REL_ALIAS: + f_print(fout, "%s%s %s", prefix, old, name); + break; + } + f_print(fout, ";\n"); + } +} + +void +pdeclaration(name, dec, tab, separator) + char *name; + declaration *dec; + int tab; + char *separator; +{ + char buf[8]; /* enough to hold "struct ", include NUL */ + char *prefix; + char *type; + + if (streq(dec->type, "void")) { + return; + } + tabify(fout, tab); + if (streq(dec->type, name) && !dec->prefix) { + f_print(fout, "struct "); + } + if (streq(dec->type, "string")) { + f_print(fout, "char *%s", dec->name); + } else { + prefix = ""; + if (streq(dec->type, "bool")) { + type = "bool_t"; + } else + if (streq(dec->type, "opaque")) { + type = "char"; + } else { + if (dec->prefix) { + s_print(buf, "%s ", dec->prefix); + prefix = buf; + } + type = dec->type; + } + switch (dec->rel) { + case REL_ALIAS: + f_print(fout, "%s%s %s", prefix, type, dec->name); + break; + case REL_VECTOR: + f_print(fout, "%s%s %s[%s]", prefix, type, dec->name, + dec->array_max); + break; + case REL_POINTER: + f_print(fout, "%s%s *%s", prefix, type, dec->name); + break; + case REL_ARRAY: + f_print(fout, "struct {\n"); + tabify(fout, tab); + f_print(fout, "\tu_int %s_len;\n", dec->name); + tabify(fout, tab); + f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name); + tabify(fout, tab); + f_print(fout, "} %s", dec->name); + break; + } + } + f_print(fout, "%s", separator); +} + +static int +undefined2(type, stop) + char *type; + char *stop; +{ + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + if (streq(def->def_name, stop)) { + return (1); + } else + if (streq(def->def_name, type)) { + return (0); + } + } + } + return (1); +} diff --git a/developer_cmds/rpcgen/rpc_main.c b/developer_cmds/rpcgen/rpc_main.c new file mode 100644 index 0000000..a7a15a8 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_main.c @@ -0,0 +1,1170 @@ +/* $NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_main.c,v 1.14 1997/10/18 10:53:53 lukem Exp $"); +#endif +#endif + +/* + * rpc_main.c, Top level of the RPC protocol compiler. + */ + +#define RPCGEN_VERSION "199506"/* This program's version (year & month) */ + +#include +#include +#include +#include +#include +#include +#ifdef __TURBOC__ +#define MAXPATHLEN 80 +#include +#include +#else +#include +#include +#include +#endif +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define EXTEND 1 /* alias for TRUE */ +#define DONT_EXTEND 0 /* alias for FALSE */ + +#define SVR4_CPP "/usr/ccs/lib/cpp" +#define SUNOS_CPP "/lib/cpp" +static int cppDefined = 0; /* explicit path for C preprocessor */ + +struct commandline { + int cflag; /* xdr C routines */ + int hflag; /* header file */ + int lflag; /* client side stubs */ + int mflag; /* server side stubs */ + int nflag; /* netid flag */ + int sflag; /* server stubs for the given transport */ + int tflag; /* dispatch Table file */ + int Ssflag; /* produce server sample code */ + int Scflag; /* produce client sample code */ + char *infile; /* input module name */ + char *outfile; /* output module name */ +}; + + +static char *cmdname; + +static char *svcclosetime = "120"; +static char *CPP = "/usr/bin/cpp"; +static char CPPFLAGS[] = "-C"; +static char pathbuf[MAXPATHLEN + 1]; +static char *allv[] = { + "rpcgen", "-s", "udp", "-s", "tcp", +}; +static int allc = sizeof(allv) / sizeof(allv[0]); +static char *allnv[] = { + "rpcgen", "-s", "netpath", +}; +static int allnc = sizeof(allnv) / sizeof(allnv[0]); + +#define ARGLISTLEN 20 +#define FIXEDARGS 2 + +static char *arglist[ARGLISTLEN]; +static int argcount = FIXEDARGS; + + +int nonfatalerrors; /* errors */ +int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the default */ +int pmflag; /* Support for port monitors */ +int logflag; /* Use syslog instead of fprintf for errors */ +int tblflag; /* Support for dispatch table file */ +int callerflag; /* Generate svc_caller() function */ + +#define INLINE 3 +/*length at which to start doing an inline */ + +int doinline = INLINE; /* length at which to start doing an inline. 3 + * = default if 0, no xdr_inline code */ + +int indefinitewait; /* If started by port monitors, hang till it + * wants */ +int exitnow; /* If started by port monitors, exit after the + * call */ +int timerflag; /* TRUE if !indefinite && !exitnow */ +int newstyle; /* newstyle of passing arguments (by value) */ +int Cflag = 0; /* ANSI C syntax */ +static int allfiles; /* generate all files */ +int tirpcflag = 0; /* generating code for tirpc, by default */ + +#ifdef __MSDOS__ +static char *dos_cppfile = NULL; +#endif + +int main __P((int, char *[])); + +static char *extendfile __P((char *, char *)); +static void open_output __P((char *, char *)); +static void add_warning __P((void)); +static void clear_args __P((void)); +static void find_cpp __P((void)); +static void open_input __P((char *, char *)); +static int check_nettype __P((char *, char *[])); +static void c_output __P((char *, char *, int, char *)); +static void c_initialize __P((void)); +static char *generate_guard __P((char *)); +static void h_output __P((char *, char *, int, char *)); +static void s_output __P((int, char *[], char *, char *, int, char *, int, int)); +static void l_output __P((char *, char *, int, char *)); +static void t_output __P((char *, char *, int, char *)); +static void svc_output __P((char *, char *, int, char *)); +static void clnt_output __P((char *, char *, int, char *)); +static int do_registers __P((int, char *[])); +static void addarg __P((char *)); +static void putarg __P((int, char *)); +static void checkfiles __P((char *, char *)); +static int parseargs __P((int, char *[], struct commandline *)); +static void usage __P((void)); +static void options_usage __P((void)); + +pid_t childpid; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct commandline cmd; + + (void) memset((char *) &cmd, 0, sizeof(struct commandline)); + clear_args(); + if (!parseargs(argc, argv, &cmd)) + usage(); + + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) { + checkfiles(cmd.infile, cmd.outfile); + } else + checkfiles(cmd.infile, NULL); + + if (cmd.cflag) { + c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); + } else + if (cmd.hflag) { + h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); + } else + if (cmd.lflag) { + l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); + } else + if (cmd.sflag || cmd.mflag || (cmd.nflag)) { + s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, + cmd.outfile, cmd.mflag, cmd.nflag); + } else + if (cmd.tflag) { + t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); + } else + if (cmd.Ssflag) { + svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); + } else + if (cmd.Scflag) { + clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); + } else { + /* the rescans + * are + * required, + * since cpp + * may effect + * input */ + c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); + reinitialize(); + h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h"); + reinitialize(); + l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); + reinitialize(); + if (inetdflag || !tirpcflag) + s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, + "_svc.c", cmd.mflag, cmd.nflag); + else + s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", + EXTEND, "_svc.c", cmd.mflag, cmd.nflag); + if (tblflag) { + reinitialize(); + t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); + } + if (allfiles) { + reinitialize(); + svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); + } + if (allfiles) { + reinitialize(); + clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); + } + } +#ifdef __MSDOS__ + if (dos_cppfile != NULL) { + (void) fclose(fin); + (void) unlink(dos_cppfile); + } +#endif + exit(nonfatalerrors); + /* NOTREACHED */ +} +/* + * add extension to filename + */ +static char * +extendfile(path, ext) + char *path; + char *ext; +{ + char *file; + char *res; + char *p; + + if ((file = strrchr(path, '/')) == NULL) + file = path; + else + file++; + + res = alloc(strlen(file) + strlen(ext) + 1); + if (res == NULL) { + errx(1, "Out of memory"); + } + p = strrchr(file, '.'); + if (p == NULL) { + p = file + strlen(file); + } + (void) strcpy(res, file); + (void) strcpy(res + (p - file), ext); + return (res); +} +/* + * Open output file with given extension + */ +static void +open_output(infile, outfile) + char *infile; + char *outfile; +{ + + if (outfile == NULL) { + fout = stdout; + return; + } + if (infile != NULL && streq(outfile, infile)) { + f_print(stderr, "%s: output would overwrite %s\n", cmdname, + infile); + crash(); + } + fout = fopen(outfile, "w"); + if (fout == NULL) { + f_print(stderr, "%s: unable to open ", cmdname); + perror(outfile); + crash(); + } + record_open(outfile); + +} + +static void +add_warning() +{ + f_print(fout, "/*\n"); + f_print(fout, " * Please do not edit this file.\n"); + f_print(fout, " * It was generated using rpcgen.\n"); + f_print(fout, " */\n\n"); +} +/* clear list of arguments */ +static void +clear_args() +{ + int i; + for (i = FIXEDARGS; i < ARGLISTLEN; i++) + arglist[i] = NULL; + argcount = FIXEDARGS; +} +/* make sure that a CPP exists */ +static void +find_cpp() +{ + struct stat buf; + + if (stat(CPP, &buf) < 0) { /* SVR4 or explicit cpp does not exist */ + if (cppDefined) { + fprintf(stderr, "cannot find C preprocessor: %s\n", CPP); + crash(); + } else { /* try the other one */ + CPP = SUNOS_CPP; + if (stat(CPP, &buf) < 0) { /* can't find any cpp */ + fprintf(stderr, "cannot find any C preprocessor (cpp)\n"); + crash(); + } + } + } +} +/* + * Open input file with given define for C-preprocessor + */ +static void +open_input(infile, define) + char *infile; + char *define; +{ + int pd[2]; + + infilename = (infile == NULL) ? "" : infile; +#ifdef __MSDOS__ +#define DOSCPP "\\prog\\bc31\\bin\\cpp.exe" + { + int retval; + char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT]; + char cppfile[MAXPATH]; + char *cpp; + + if ((cpp = searchpath("cpp.exe")) == NULL + && (cpp = getenv("RPCGENCPP")) == NULL) + cpp = DOSCPP; + + putarg(0, cpp); + putarg(1, "-P-"); + putarg(2, CPPFLAGS); + addarg(define); + addarg(infile); + addarg(NULL); + + retval = spawnvp(P_WAIT, arglist[0], arglist); + if (retval != 0) { + fprintf(stderr, "%s: C PreProcessor failed\n", cmdname); + crash(); + } + fnsplit(infile, drive, dir, name, ext); + fnmerge(cppfile, drive, dir, name, ".i"); + + fin = fopen(cppfile, "r"); + if (fin == NULL) { + f_print(stderr, "%s: ", cmdname); + perror(cppfile); + crash(); + } + dos_cppfile = strdup(cppfile); + if (dos_cppfile == NULL) { + fprintf(stderr, "%s: out of memory\n", cmdname); + crash(); + } + } +#else + (void) pipe(pd); + switch (childpid = fork()) { + case 0: + find_cpp(); + putarg(0, CPP); + putarg(1, CPPFLAGS); + addarg(define); + addarg(infile); + addarg((char *) NULL); + (void) close(1); + (void) dup2(pd[1], 1); + (void) close(pd[0]); + execv(arglist[0], arglist); + perror("execv"); + exit(1); + case -1: + perror("fork"); + exit(1); + } + (void) close(pd[1]); + fin = fdopen(pd[0], "r"); +#endif + if (fin == NULL) { + f_print(stderr, "%s: ", cmdname); + perror(infilename); + crash(); + } +} +/* valid tirpc nettypes */ +static char *valid_ti_nettypes[] = +{ + "netpath", + "visible", + "circuit_v", + "datagram_v", + "circuit_n", + "datagram_n", + "udp", + "tcp", + "raw", + NULL +}; +/* valid inetd nettypes */ +static char *valid_i_nettypes[] = +{ + "udp", + "tcp", + NULL +}; + +static int +check_nettype(name, list_to_check) + char *name; + char *list_to_check[]; +{ + int i; + for (i = 0; list_to_check[i] != NULL; i++) { + if (strcmp(name, list_to_check[i]) == 0) { + return 1; + } + } + f_print(stderr, "illegal nettype :\'%s\'\n", name); + return 0; +} +/* + * Compile into an XDR routine output file + */ + +static void +c_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + + c_initialize(); + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + /* .h file already contains rpc/rpc.h */ + } else + f_print(fout, "#include \n"); + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + emit(def); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + + +static void +c_initialize() +{ + + /* add all the starting basic types */ + + add_type(1, "int"); + add_type(1, "long"); + add_type(1, "short"); + add_type(1, "bool"); + + add_type(1, "u_int"); + add_type(1, "u_long"); + add_type(1, "u_short"); + +} + +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ + char *(*proc)();\n\ + xdrproc_t xdr_arg;\n\ + unsigned len_arg;\n\ + xdrproc_t xdr_res;\n\ + unsigned len_res;\n\ +};\n"; + + +static char * +generate_guard(pathname) + char *pathname; +{ + char *filename, *guard, *tmp; + + filename = strrchr(pathname, '/'); /* find last component */ + filename = ((filename == 0) ? pathname : filename + 1); + guard = strdup(filename); + /* convert to upper case */ + tmp = guard; + while (*tmp) { + if (islower(*tmp)) + *tmp = toupper(*tmp); + tmp++; + } + + guard = extendfile(guard, "_H_RPCGEN"); + return (guard); +} +/* + * Compile into an XDR header file + */ + +static void +h_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *outfilename; + long tell; + char *guard; + list *l; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + guard = generate_guard(outfilename ? outfilename : infile); + + f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard, + guard); + + f_print(fout, "#define RPCGEN_VERSION\t%s\n\n", RPCGEN_VERSION); + f_print(fout, "#include \n\n"); + + tell = ftell(fout); + /* print data definitions */ + while ((def = get_definition()) != NULL) { + print_datadef(def); + } + + /* print function declarations. Do this after data definitions + * because they might be used as arguments for functions */ + for (l = defined; l != NULL; l = l->next) { + print_funcdef(l->val); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } else + if (tblflag) { + f_print(fout, "%s", rpcgen_table_dcl); + } + f_print(fout, "\n#endif /* !_%s */\n", guard); +} +/* + * Compile into an RPC service + */ +static void +s_output(argc, argv, infile, define, extend, outfile, nomain, netflag) + int argc; + char *argv[]; + char *infile; + char *define; + int extend; + char *outfile; + int nomain; + int netflag; +{ + char *include; + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + if (Cflag) { + f_print(fout, "#include \n"); + f_print(fout, + "#include \n"); + f_print(fout, "#include \n"); + } + f_print(fout, "#include \n"); + if (strcmp(svcclosetime, "-1") == 0) + indefinitewait = 1; + else + if (strcmp(svcclosetime, "0") == 0) + exitnow = 1; + else + if (inetdflag || pmflag) { + f_print(fout, "#include \n"); + timerflag = 1; + } + if (!tirpcflag && inetdflag) + f_print(fout, "#include \n"); + if (Cflag && (inetdflag || pmflag)) { + f_print(fout, "#ifdef __cplusplus\n"); + f_print(fout, "#include \n"); + f_print(fout, "#endif /* __cplusplus */\n"); + } + if (tirpcflag) + f_print(fout, "#include \n"); + + f_print(fout, "#include \n"); + if (tirpcflag) + f_print(fout, "#include \n"); + + if (inetdflag || !tirpcflag) { + f_print(fout, "#include \n"); + f_print(fout, "#include \n"); + } + if ((netflag || pmflag) && tirpcflag) { + f_print(fout, "#include \n"); + } + if ( /* timerflag && */ tirpcflag) + f_print(fout, "#include \n"); + if (logflag || inetdflag || pmflag) + f_print(fout, "#include \n"); + + /* for ANSI-C */ + f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n"); + + f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); + if (timerflag) + f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + if (callerflag) /* EVAS */ + f_print(fout, "\nstatic SVCXPRT *caller;\n"); /* EVAS */ + write_most(infile, netflag, nomain); + if (!nomain) { + if (!do_registers(argc, argv)) { + if (outfilename) + (void) unlink(outfilename); + usage(); + } + write_rest(); + } +} +/* + * generate client side stubs + */ +static void +l_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + char *include; + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + if (Cflag) + f_print(fout, "#include \n"); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + write_stubs(); +} +/* + * generate the dispatch table + */ +static void +t_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + int foundprogram = 0; + char *outfilename; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + open_output(infile, outfilename); + add_warning(); + while ((def = get_definition()) != NULL) { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) { + (void) unlink(outfilename); + return; + } + write_tables(); +} +/* sample routine for the server template */ +static void +svc_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + checkfiles(infile, outfilename); /* check if outfile already + * exists. if so, print an + * error message and exit */ + open_output(infile, outfilename); + add_sample_msg(); + + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + write_sample_svc(def); + } + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} + + +/* sample main routine for client */ +static void +clnt_output(infile, define, extend, outfile) + char *infile; + char *define; + int extend; + char *outfile; +{ + definition *def; + char *include; + char *outfilename; + long tell; + int has_program = 0; + + open_input(infile, define); + outfilename = extend ? extendfile(infile, outfile) : outfile; + checkfiles(infile, outfilename); /* check if outfile already + * exists. if so, print an + * error message and exit */ + + open_output(infile, outfilename); + add_sample_msg(); + if (infile && (include = extendfile(infile, ".h"))) { + f_print(fout, "#include \"%s\"\n", include); + free(include); + } else + f_print(fout, "#include \n"); + tell = ftell(fout); + while ((def = get_definition()) != NULL) { + has_program += write_sample_clnt(def); + } + + if (has_program) + write_sample_clnt_main(); + + if (extend && tell == ftell(fout)) { + (void) unlink(outfilename); + } +} +/* + * Perform registrations for service output + * Return 0 if failed; 1 otherwise. + */ +static int +do_registers(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (inetdflag || !tirpcflag) { + for (i = 1; i < argc; i++) { + if (streq(argv[i], "-s")) { + if (!check_nettype(argv[i + 1], valid_i_nettypes)) + return 0; + write_inetd_register(argv[i + 1]); + i++; + } + } + } else { + for (i = 1; i < argc; i++) + if (streq(argv[i], "-s")) { + if (!check_nettype(argv[i + 1], valid_ti_nettypes)) + return 0; + write_nettype_register(argv[i + 1]); + i++; + } else + if (streq(argv[i], "-n")) { + write_netid_register(argv[i + 1]); + i++; + } + } + return 1; +} +/* + * Add another argument to the arg list + */ +static void +addarg(cp) + char *cp; +{ + if (argcount >= ARGLISTLEN) { + f_print(stderr, "rpcgen: too many defines\n"); + crash(); + /* NOTREACHED */ + } + arglist[argcount++] = cp; + +} + +static void +putarg(where, cp) + char *cp; + int where; +{ + if (where >= ARGLISTLEN) { + f_print(stderr, "rpcgen: arglist coding error\n"); + crash(); + /* NOTREACHED */ + } + arglist[where] = cp; + +} +/* + * if input file is stdin and an output file is specified then complain + * if the file already exists. Otherwise the file may get overwritten + * If input file does not exist, exit with an error + */ + +static void +checkfiles(infile, outfile) + char *infile; + char *outfile; +{ + + struct stat buf; + + if (infile) /* infile ! = NULL */ + if (stat(infile, &buf) < 0) { + perror(infile); + crash(); + }; +#if 0 + if (outfile) { + if (stat(outfile, &buf) < 0) + return; /* file does not exist */ + else { + f_print(stderr, + "file '%s' already exists and may be overwritten\n", outfile); + crash(); + } + } +#endif +} +/* + * Parse command line arguments + */ +static int +parseargs(argc, argv, cmd) + int argc; + char *argv[]; + struct commandline *cmd; +{ + int i; + int j; + int c; + char flag[(1 << 8 * sizeof(char))]; + int nflags; + + cmdname = argv[0]; + cmd->infile = cmd->outfile = NULL; + if (argc < 2) { + return (0); + } + allfiles = 0; + flag['c'] = 0; + flag['h'] = 0; + flag['l'] = 0; + flag['m'] = 0; + flag['o'] = 0; + flag['s'] = 0; + flag['n'] = 0; + flag['t'] = 0; + flag['S'] = 0; + flag['C'] = 0; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + if (cmd->infile) { + f_print(stderr, "Cannot specify more than one input file!\n"); + + return (0); + } + cmd->infile = argv[i]; + } else { + for (j = 1; argv[i][j] != 0; j++) { + c = argv[i][j]; + switch (c) { + case 'A': + callerflag = 1; + break; + case 'a': + allfiles = 1; + break; + case 'c': + case 'h': + case 'l': + case 'm': + case 't': + if (flag[c]) { + return (0); + } + flag[c] = 1; + break; + case 'S': + /* sample flag: Ss or Sc. Ss means set + * flag['S']; Sc means set flag['C']; */ + c = argv[i][++j]; /* get next char */ + if (c == 's') + c = 'S'; + else + if (c == 'c') + c = 'C'; + else + return (0); + + if (flag[c]) { + return (0); + } + flag[c] = 1; + break; + case 'C': /* ANSI C syntax */ + Cflag = 1; + break; + + case 'b': /* turn TIRPC flag off for + * generating backward + * compatible */ + tirpcflag = 0; + break; + + case 'I': + inetdflag = 1; + break; + case 'N': + newstyle = 1; + break; + case 'L': + logflag = 1; + break; + case 'K': + if (++i == argc) { + return (0); + } + svcclosetime = argv[i]; + goto nextarg; + case 'T': + tblflag = 1; + break; + case 'i': + if (++i == argc) { + return (0); + } + doinline = atoi(argv[i]); + goto nextarg; + case 'n': + case 'o': + case 's': + if (argv[i][j - 1] != '-' || + argv[i][j + 1] != 0) { + return (0); + } + flag[c] = 1; + if (++i == argc) { + return (0); + } + if (c == 's') { + if (!streq(argv[i], "udp") && + !streq(argv[i], "tcp")) { + return (0); + } + } else + if (c == 'o') { + if (cmd->outfile) { + return (0); + } + cmd->outfile = argv[i]; + } + goto nextarg; + case 'D': + if (argv[i][j - 1] != '-') { + return (0); + } + (void) addarg(argv[i]); + goto nextarg; + case 'Y': + if (++i == argc) { + return (0); + } + (void) strcpy(pathbuf, argv[i]); + (void) strcat(pathbuf, "/cpp"); + CPP = pathbuf; + cppDefined = 1; + goto nextarg; + + + + default: + return (0); + } + } + nextarg: + ; + } + } + + cmd->cflag = flag['c']; + cmd->hflag = flag['h']; + cmd->lflag = flag['l']; + cmd->mflag = flag['m']; + cmd->nflag = flag['n']; + cmd->sflag = flag['s']; + cmd->tflag = flag['t']; + cmd->Ssflag = flag['S']; + cmd->Scflag = flag['C']; + + if (tirpcflag) { + pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is + * always TRUE */ + if ((inetdflag && cmd->nflag)) { /* netid not allowed + * with inetdflag */ + f_print(stderr, "Cannot use netid flag with inetd flag!\n"); + return (0); + } + } else { /* 4.1 mode */ + pmflag = 0; /* set pmflag only in tirpcmode */ + inetdflag = 1; /* inetdflag is TRUE by default */ + if (cmd->nflag) { /* netid needs TIRPC */ + f_print(stderr, "Cannot use netid flag without TIRPC!\n"); + return (0); + } + } + + if (newstyle && (tblflag || cmd->tflag)) { + f_print(stderr, "Cannot use table flags with newstyle!\n"); + return (0); + } + /* check no conflicts with file generation flags */ + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; + + if (nflags == 0) { + if (cmd->outfile != NULL || cmd->infile == NULL) { + return (0); + } + } else + if (nflags > 1) { + f_print(stderr, "Cannot have more than one file generation flag!\n"); + return (0); + } + return (1); +} + +static void +usage() +{ + f_print(stderr, "usage: %s infile\n", cmdname); + f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size [-I [-K seconds]] [-A][-L][-M toolkit][-N][-T] infile\n", + cmdname); + f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n", + cmdname); + f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname); + f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname); + options_usage(); + exit(1); +} + +static void +options_usage() +{ + f_print(stderr, "options:\n"); + f_print(stderr, "-A\t\tgenerate svc_caller() function\n"); + f_print(stderr, "-a\t\tgenerate all files, including samples\n"); + f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n"); + f_print(stderr, "-c\t\tgenerate XDR routines\n"); + f_print(stderr, "-C\t\tANSI C mode\n"); + f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n"); + f_print(stderr, "-h\t\tgenerate header file\n"); + f_print(stderr, "-i size\t\tsize at which to start generating inline code\n"); + f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n"); + f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n"); + f_print(stderr, "-l\t\tgenerate client side stubs\n"); + f_print(stderr, "-L\t\tserver errors will be printed to syslog\n"); + f_print(stderr, "-m\t\tgenerate server side stubs\n"); + f_print(stderr, "-n netid\tgenerate server code that supports named netid\n"); + f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n"); + f_print(stderr, "-o outfile\tname of the output file\n"); + f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n"); + f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n"); + f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n"); + f_print(stderr, "-t\t\tgenerate RPC dispatch table\n"); + f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n"); + f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n"); + + exit(1); +} diff --git a/developer_cmds/rpcgen/rpc_parse.c b/developer_cmds/rpcgen/rpc_parse.c new file mode 100644 index 0000000..db0c1f1 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_parse.c @@ -0,0 +1,643 @@ +/* $NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_parse.c,v 1.9 1998/02/11 23:11:18 lukem Exp $"); +#endif +#endif + +/* + * rpc_parse.c, Parser for the RPC protocol compiler + * Copyright (C) 1987 Sun Microsystems, Inc. + */ +#include +#include +#include +#include "rpc/types.h" +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define ARGNAME "arg" + +static void isdefined __P((definition *)); +static void def_struct __P((definition *)); +static void def_program __P((definition *)); +static void def_enum __P((definition *)); +static void def_const __P((definition *)); +static void def_union __P((definition *)); +static void check_type_name __P((char *, int)); +static void def_typedef __P((definition *)); +static void get_declaration __P((declaration *, defkind)); +static void get_prog_declaration __P((declaration *, defkind, int)); +static void get_type __P((char **, char **, defkind)); +static void unsigned_dec __P((char **)); + +/* + * return the next definition you see + */ +definition * +get_definition() +{ + definition *defp; + token tok; + + defp = ALLOC(definition); + get_token(&tok); + switch (tok.kind) { + case TOK_STRUCT: + def_struct(defp); + break; + case TOK_UNION: + def_union(defp); + break; + case TOK_TYPEDEF: + def_typedef(defp); + break; + case TOK_ENUM: + def_enum(defp); + break; + case TOK_PROGRAM: + def_program(defp); + break; + case TOK_CONST: + def_const(defp); + break; + case TOK_EOF: + return (NULL); + default: + error("definition keyword expected"); + } + scan(TOK_SEMICOLON, &tok); + isdefined(defp); + return (defp); +} + +static void +isdefined(defp) + definition *defp; +{ + STOREVAL(&defined, defp); +} + +static void +def_struct(defp) + definition *defp; +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + + defp->def_kind = DEF_STRUCT; + + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + tailp = &defp->def.st.decls; + do { + get_declaration(&dec, DEF_STRUCT); + decls = ALLOC(decl_list); + decls->decl = dec; + *tailp = decls; + tailp = &decls->next; + scan(TOK_SEMICOLON, &tok); + peek(&tok); + } while (tok.kind != TOK_RBRACE); + get_token(&tok); + *tailp = NULL; +} + +static void +def_program(defp) + definition *defp; +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + version_list *vlist; + version_list **vtailp; + proc_list *plist; + proc_list **ptailp; + int num_args; + bool_t isvoid = FALSE; /* whether first argument is void */ + defp->def_kind = DEF_PROGRAM; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + vtailp = &defp->def.pr.versions; + tailp = &defp->def.st.decls; + scan(TOK_VERSION, &tok); + do { + scan(TOK_IDENT, &tok); + vlist = ALLOC(version_list); + vlist->vers_name = tok.str; + scan(TOK_LBRACE, &tok); + ptailp = &vlist->procs; + do { + /* get result type */ + plist = ALLOC(proc_list); + get_type(&plist->res_prefix, &plist->res_type, + DEF_PROGRAM); + if (streq(plist->res_type, "opaque")) { + error("illegal result type"); + } + scan(TOK_IDENT, &tok); + plist->proc_name = tok.str; + scan(TOK_LPAREN, &tok); + /* get args - first one */ + num_args = 1; + isvoid = FALSE; + /* type of DEF_PROGRAM in the first + * get_prog_declaration and DEF_STURCT in the next + * allows void as argument if it is the only argument */ + get_prog_declaration(&dec, DEF_PROGRAM, num_args); + if (streq(dec.type, "void")) + isvoid = TRUE; + decls = ALLOC(decl_list); + plist->args.decls = decls; + decls->decl = dec; + tailp = &decls->next; + /* get args */ + while (peekscan(TOK_COMMA, &tok)) { + num_args++; + get_prog_declaration(&dec, DEF_STRUCT, + num_args); + decls = ALLOC(decl_list); + decls->decl = dec; + *tailp = decls; + if (streq(dec.type, "void")) + isvoid = TRUE; + tailp = &decls->next; + } + /* multiple arguments are only allowed in newstyle */ + if (!newstyle && num_args > 1) { + error("only one argument is allowed"); + } + if (isvoid && num_args > 1) { + error("illegal use of void in program definition"); + } + *tailp = NULL; + scan(TOK_RPAREN, &tok); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + scan(TOK_SEMICOLON, &tok); + plist->proc_num = tok.str; + plist->arg_num = num_args; + *ptailp = plist; + ptailp = &plist->next; + peek(&tok); + } while (tok.kind != TOK_RBRACE); + *ptailp = NULL; + *vtailp = vlist; + vtailp = &vlist->next; + scan(TOK_RBRACE, &tok); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + vlist->vers_num = tok.str; + /* make the argument structure name for each arg */ + for (plist = vlist->procs; plist != NULL; + plist = plist->next) { + plist->args.argname = make_argname(plist->proc_name, + vlist->vers_num); + /* free the memory ?? */ + } + scan(TOK_SEMICOLON, &tok); + scan2(TOK_VERSION, TOK_RBRACE, &tok); + } while (tok.kind == TOK_VERSION); + scan(TOK_EQUAL, &tok); + scan_num(&tok); + defp->def.pr.prog_num = tok.str; + *vtailp = NULL; +} + + +static void +def_enum(defp) + definition *defp; +{ + token tok; + enumval_list *elist; + enumval_list **tailp; + + defp->def_kind = DEF_ENUM; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_LBRACE, &tok); + tailp = &defp->def.en.vals; + do { + scan(TOK_IDENT, &tok); + elist = ALLOC(enumval_list); + elist->name = tok.str; + elist->assignment = NULL; + scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); + if (tok.kind == TOK_EQUAL) { + scan_num(&tok); + elist->assignment = tok.str; + scan2(TOK_COMMA, TOK_RBRACE, &tok); + } + *tailp = elist; + tailp = &elist->next; + } while (tok.kind != TOK_RBRACE); + *tailp = NULL; +} + +static void +def_const(defp) + definition *defp; +{ + token tok; + + defp->def_kind = DEF_CONST; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_EQUAL, &tok); + scan2(TOK_IDENT, TOK_STRCONST, &tok); + defp->def.co = tok.str; +} + +static void +def_union(defp) + definition *defp; +{ + token tok; + declaration dec; + case_list *cases; + case_list **tailp; + int flag; + + defp->def_kind = DEF_UNION; + scan(TOK_IDENT, &tok); + defp->def_name = tok.str; + scan(TOK_SWITCH, &tok); + scan(TOK_LPAREN, &tok); + get_declaration(&dec, DEF_UNION); + defp->def.un.enum_decl = dec; + tailp = &defp->def.un.cases; + scan(TOK_RPAREN, &tok); + scan(TOK_LBRACE, &tok); + scan(TOK_CASE, &tok); + while (tok.kind == TOK_CASE) { + scan2(TOK_IDENT, TOK_CHARCONST, &tok); + cases = ALLOC(case_list); + cases->case_name = tok.str; + scan(TOK_COLON, &tok); + /* now peek at next token */ + flag = 0; + if (peekscan(TOK_CASE, &tok)) { + + do { + scan2(TOK_IDENT, TOK_CHARCONST, &tok); + cases->contflag = 1; /* continued case + * statement */ + *tailp = cases; + tailp = &cases->next; + cases = ALLOC(case_list); + cases->case_name = tok.str; + scan(TOK_COLON, &tok); + + } while (peekscan(TOK_CASE, &tok)); + } else + if (flag) { + + *tailp = cases; + tailp = &cases->next; + cases = ALLOC(case_list); + }; + + get_declaration(&dec, DEF_UNION); + cases->case_decl = dec; + cases->contflag = 0; /* no continued case statement */ + *tailp = cases; + tailp = &cases->next; + scan(TOK_SEMICOLON, &tok); + + scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); + } + *tailp = NULL; + if (tok.kind == TOK_DEFAULT) { + scan(TOK_COLON, &tok); + get_declaration(&dec, DEF_UNION); + defp->def.un.default_decl = ALLOC(declaration); + *defp->def.un.default_decl = dec; + scan(TOK_SEMICOLON, &tok); + scan(TOK_RBRACE, &tok); + } else { + defp->def.un.default_decl = NULL; + } +} + +static char *reserved_words[] = { + "array", + "bytes", + "destroy", + "free", + "getpos", + "inline", + "pointer", + "reference", + "setpos", + "sizeof", + "union", + "vector", + NULL +}; + +static char *reserved_types[] = { + "opaque", + "string", + NULL +}; +/* check that the given name is not one that would eventually result in + xdr routines that would conflict with internal XDR routines. */ +static void +check_type_name(name, new_type) + int new_type; + char *name; +{ + int i; + char tmp[100]; + + for (i = 0; reserved_words[i] != NULL; i++) { + if (strcmp(name, reserved_words[i]) == 0) { + sprintf(tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error(tmp); + } + } + if (new_type) { + for (i = 0; reserved_types[i] != NULL; i++) { + if (strcmp(name, reserved_types[i]) == 0) { + sprintf(tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error(tmp); + } + } + } +} + +static void +def_typedef(defp) + definition *defp; +{ + declaration dec; + + defp->def_kind = DEF_TYPEDEF; + get_declaration(&dec, DEF_TYPEDEF); + defp->def_name = dec.name; + check_type_name(dec.name, 1); + defp->def.ty.old_prefix = dec.prefix; + defp->def.ty.old_type = dec.type; + defp->def.ty.rel = dec.rel; + defp->def.ty.array_max = dec.array_max; +} + +static void +get_declaration(dec, dkind) + declaration *dec; + defkind dkind; +{ + token tok; + + get_type(&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (streq(dec->type, "void")) { + return; + } + check_type_name(dec->type, 0); + + scan2(TOK_STAR, TOK_IDENT, &tok); + if (tok.kind == TOK_STAR) { + dec->rel = REL_POINTER; + scan(TOK_IDENT, &tok); + } + dec->name = tok.str; + if (peekscan(TOK_LBRACKET, &tok)) { + if (dec->rel == REL_POINTER) { + error("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_VECTOR; + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RBRACKET, &tok); + } else + if (peekscan(TOK_LANGLE, &tok)) { + if (dec->rel == REL_POINTER) { + error("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan(TOK_RANGLE, &tok)) { + dec->array_max = "~0"; /* unspecified size, use + * max */ + } else { + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RANGLE, &tok); + } + } + if (streq(dec->type, "opaque")) { + if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { + error("array declaration expected"); + } + } else + if (streq(dec->type, "string")) { + if (dec->rel != REL_ARRAY) { + error("variable-length array declaration expected"); + } + } +} + +static void +get_prog_declaration(dec, dkind, num) + declaration *dec; + defkind dkind; + int num; /* arg number */ +{ + token tok; + char name[10]; /* argument name */ + + if (dkind == DEF_PROGRAM) { + peek(&tok); + if (tok.kind == TOK_RPAREN) { /* no arguments */ + dec->rel = REL_ALIAS; + dec->type = "void"; + dec->prefix = NULL; + dec->name = NULL; + return; + } + } + get_type(&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ + strcpy(name, tok.str); + else + sprintf(name, "%s%d", ARGNAME, num); /* default name of + * argument */ + + dec->name = (char *) strdup(name); + + if (streq(dec->type, "void")) { + return; + } + if (streq(dec->type, "opaque")) { + error("opaque -- illegal argument type"); + } + if (peekscan(TOK_STAR, &tok)) { + if (streq(dec->type, "string")) { + error("pointer to string not allowed in program arguments\n"); + } + dec->rel = REL_POINTER; + if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */ + dec->name = (char *) strdup(tok.str); + } + if (peekscan(TOK_LANGLE, &tok)) { + if (!streq(dec->type, "string")) { + error("arrays cannot be declared as arguments to procedures -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan(TOK_RANGLE, &tok)) { + dec->array_max = "~0"; /* unspecified size, use max */ + } else { + scan_num(&tok); + dec->array_max = tok.str; + scan(TOK_RANGLE, &tok); + } + } + if (streq(dec->type, "string")) { + if (dec->rel != REL_ARRAY) { /* .x specifies just string as + * type of argument - make it + * string<> */ + dec->rel = REL_ARRAY; + dec->array_max = "~0"; /* unspecified size, use max */ + } + } +} + + + +static void +get_type(prefixp, typep, dkind) + char **prefixp; + char **typep; + defkind dkind; +{ + token tok; + + *prefixp = NULL; + get_token(&tok); + switch (tok.kind) { + case TOK_IDENT: + *typep = tok.str; + break; + case TOK_STRUCT: + case TOK_ENUM: + case TOK_UNION: + *prefixp = tok.str; + scan(TOK_IDENT, &tok); + *typep = tok.str; + break; + case TOK_UNSIGNED: + unsigned_dec(typep); + break; + case TOK_SHORT: + *typep = "short"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_LONG: + *typep = "long"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_HYPER: + *typep = "int64_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_VOID: + if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { + error("voids allowed only inside union and program definitions with one argument"); + } + *typep = tok.str; + break; + case TOK_STRING: + case TOK_OPAQUE: + case TOK_CHAR: + case TOK_INT: + case TOK_FLOAT: + case TOK_DOUBLE: + case TOK_QUAD: + case TOK_BOOL: + *typep = tok.str; + break; + default: + error("expected type specifier"); + } +} + +static void +unsigned_dec(typep) + char **typep; +{ + token tok; + + peek(&tok); + switch (tok.kind) { + case TOK_CHAR: + get_token(&tok); + *typep = "u_char"; + break; + case TOK_SHORT: + get_token(&tok); + *typep = "u_short"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_LONG: + get_token(&tok); + *typep = "u_long"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_HYPER: + get_token(&tok); + *typep = "u_int64_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_INT: + get_token(&tok); + *typep = "u_int"; + break; + default: + *typep = "u_int"; + break; + } +} diff --git a/developer_cmds/rpcgen/rpc_parse.h b/developer_cmds/rpcgen/rpc_parse.h new file mode 100644 index 0000000..e235bf5 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_parse.h @@ -0,0 +1,168 @@ +/* $NetBSD: rpc_parse.h,v 1.4 1997/10/11 21:01:42 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_parse.h 1.3 90/08/29 (C) 1987 SMI */ + +/* + * rpc_parse.h, Definitions for the RPCL parser + */ + +enum defkind { + DEF_CONST, + DEF_STRUCT, + DEF_UNION, + DEF_ENUM, + DEF_TYPEDEF, + DEF_PROGRAM +}; +typedef enum defkind defkind; + +typedef char *const_def; + +enum relation { + REL_VECTOR, /* fixed length array */ + REL_ARRAY, /* variable length array */ + REL_POINTER, /* pointer */ + REL_ALIAS, /* simple */ +}; +typedef enum relation relation; + +struct typedef_def { + char *old_prefix; + char *old_type; + relation rel; + char *array_max; +}; +typedef struct typedef_def typedef_def; + +struct enumval_list { + char *name; + char *assignment; + struct enumval_list *next; +}; +typedef struct enumval_list enumval_list; + +struct enum_def { + enumval_list *vals; +}; +typedef struct enum_def enum_def; + +struct declaration { + char *prefix; + char *type; + char *name; + relation rel; + char *array_max; +}; +typedef struct declaration declaration; + +struct decl_list { + declaration decl; + struct decl_list *next; +}; +typedef struct decl_list decl_list; + +struct struct_def { + decl_list *decls; +}; +typedef struct struct_def struct_def; + +struct case_list { + char *case_name; + int contflag; + declaration case_decl; + struct case_list *next; +}; +typedef struct case_list case_list; + +struct union_def { + declaration enum_decl; + case_list *cases; + declaration *default_decl; +}; +typedef struct union_def union_def; + +struct arg_list { + char *argname; /* name of struct for arg*/ + decl_list *decls; +}; + +typedef struct arg_list arg_list; + +struct proc_list { + char *proc_name; + char *proc_num; + arg_list args; + int arg_num; + char *res_type; + char *res_prefix; + struct proc_list *next; +}; +typedef struct proc_list proc_list; + +struct version_list { + char *vers_name; + char *vers_num; + proc_list *procs; + struct version_list *next; +}; +typedef struct version_list version_list; + +struct program_def { + char *prog_num; + version_list *versions; +}; +typedef struct program_def program_def; + +struct definition { + char *def_name; + defkind def_kind; + union { + const_def co; + struct_def st; + union_def un; + enum_def en; + typedef_def ty; + program_def pr; + } def; +}; +typedef struct definition definition; + +definition *get_definition __P((void)); + +struct bas_type +{ + char *name; + int length; + struct bas_type *next; +}; + +typedef struct bas_type bas_type; diff --git a/developer_cmds/rpcgen/rpc_sample.c b/developer_cmds/rpcgen/rpc_sample.c new file mode 100644 index 0000000..3fee135 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_sample.c @@ -0,0 +1,261 @@ +/* $NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_sample.c,v 1.5 1997/10/18 10:54:01 lukem Exp $"); +#endif +#endif + +/* + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler + */ + +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static char RQSTP[] = "rqstp"; + +static void write_sample_client __P((char *, version_list *)); +static void write_sample_server __P((definition *)); +static void return_type __P((proc_list *)); + +void +write_sample_svc(def) + definition *def; +{ + + if (def->def_kind != DEF_PROGRAM) + return; + write_sample_server(def); +} + + +int +write_sample_clnt(def) + definition *def; +{ + version_list *vp; + int count = 0; + + if (def->def_kind != DEF_PROGRAM) + return (0); + /* generate sample code for each version */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + write_sample_client(def->def_name, vp); + ++count; + } + return (count); +} + + +static void +write_sample_client(program_name, vp) + char *program_name; + version_list *vp; +{ + proc_list *proc; + int i; + decl_list *l; + + f_print(fout, "\n\nvoid\n"); + pvname(program_name, vp->vers_num); + if (Cflag) + f_print(fout, "( char* host )\n{\n"); + else + f_print(fout, "(host)\nchar *host;\n{\n"); + f_print(fout, "\tCLIENT *clnt;\n"); + + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\t"); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, " *result_%d;\n", ++i); + /* print out declarations for arguments */ + if (proc->arg_num < 2 && !newstyle) { + f_print(fout, "\t"); + if (!streq(proc->args.decls->decl.type, "void")) + ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1); + else + f_print(fout, "char* "); /* cannot have "void" + * type */ + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + } else + if (!streq(proc->args.decls->decl.type, "void")) { + for (l = proc->args.decls; l != NULL; l = l->next) { + f_print(fout, "\t"); + ptype(l->decl.prefix, l->decl.type, 1); + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_%s;\n", l->decl.name); +/* pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/ + } + } + } + + /* generate creation of client handle */ + f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n", + program_name, vp->vers_name, tirpcflag ? "netpath" : "udp"); + f_print(fout, "\tif (clnt == NULL) {\n"); + f_print(fout, "\t\tclnt_pcreateerror(host);\n"); + f_print(fout, "\t\texit(1);\n\t}\n"); + + /* generate calls to procedures */ + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\tresult_%d = ", ++i); + pvname(proc->proc_name, vp->vers_num); + if (proc->arg_num < 2 && !newstyle) { + f_print(fout, "("); + if (streq(proc->args.decls->decl.type, "void")) /* cast to void* */ + f_print(fout, "(void*)"); + f_print(fout, "&"); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg, clnt);\n"); + } else + if (streq(proc->args.decls->decl.type, "void")) { + f_print(fout, "(clnt);\n"); + } else { + f_print(fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) { + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_%s, ", l->decl.name); + } + f_print(fout, "clnt);\n"); + } + f_print(fout, "\tif (result_%d == NULL) {\n", i); + f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n"); + f_print(fout, "\t}\n"); + } + + f_print(fout, "\tclnt_destroy( clnt );\n"); + f_print(fout, "}\n"); +} + +static void +write_sample_server(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); +/* if( Cflag ) + f_print( fout, "extern \"C\"{\n"); +*/ + return_type(proc); + f_print(fout, "*\n"); + if (Cflag) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, RQSTP, "struct svc_req *"); + + f_print(fout, "{\n"); + f_print(fout, "\n\tstatic "); + if (!streq(proc->res_type, "void")) + return_type(proc); + else + f_print(fout, "char*"); /* cannot have void type */ + f_print(fout, " result;\n"); + f_print(fout, + "\n\t/*\n\t * insert server code here\n\t */\n\n"); + if (!streq(proc->res_type, "void")) + f_print(fout, "\treturn(&result);\n}\n"); + else /* cast back to void * */ + f_print(fout, "\treturn((void*) &result);\n}\n"); +/* if( Cflag) + f_print( fout, "};\n"); +*/ + + } + } +} + +static void +return_type(plist) + proc_list *plist; +{ + ptype(plist->res_prefix, plist->res_type, 1); +} + +void +add_sample_msg() +{ + f_print(fout, "/*\n"); + f_print(fout, " * This is sample code generated by rpcgen.\n"); + f_print(fout, " * These are only templates and you can use them\n"); + f_print(fout, " * as a guideline for developing your own functions.\n"); + f_print(fout, " */\n\n"); +} + +void +write_sample_clnt_main() +{ + list *l; + definition *def; + version_list *vp; + + f_print(fout, "\n\n"); + if (Cflag) + f_print(fout, "main( int argc, char* argv[] )\n{\n"); + else + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n"); + + f_print(fout, "\tchar *host;"); + f_print(fout, "\n\n\tif(argc < 2) {"); + f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n"); + f_print(fout, "\t\texit(1);\n\t}"); + f_print(fout, "\n\thost = argv[1];\n"); + + for (l = defined; l != NULL; l = l->next) { + def = l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "\t"); + pvname(def->def_name, vp->vers_num); + f_print(fout, "( host );\n"); + } + } + f_print(fout, "}\n"); +} diff --git a/developer_cmds/rpcgen/rpc_scan.c b/developer_cmds/rpcgen/rpc_scan.c new file mode 100644 index 0000000..4130107 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_scan.c @@ -0,0 +1,521 @@ +/* $NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_scan.c,v 1.6 1997/10/18 10:54:05 lukem Exp $"); +#endif +#endif + +/* + * rpc_scan.c, Scanner for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. + */ +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define startcomment(where) (where[0] == '/' && where[1] == '*') +#define endcomment(where) (where[-1] == '*' && where[0] == '/') + +static void unget_token __P((token *)); +static void findstrconst __P((char **, char **)); +static void findchrconst __P((char **, char **)); +static void findconst __P((char **, char **)); +static void findkind __P((char **, token *)); +static int cppline __P((char *)); +static int directive __P((char *)); +static void printdirective __P((char *)); +static void docppline __P((char *, int *, char **)); + +static int pushed = 0; /* is a token pushed */ +static token lasttok; /* last token, if pushed */ + +/* + * scan expecting 1 given token + */ +void +scan(expect, tokp) + tok_kind expect; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect) { + expected1(expect); + } +} +/* + * scan expecting any of the 2 given tokens + */ +void +scan2(expect1, expect2, tokp) + tok_kind expect1; + tok_kind expect2; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect1 && tokp->kind != expect2) { + expected2(expect1, expect2); + } +} +/* + * scan expecting any of the 3 given token + */ +void +scan3(expect1, expect2, expect3, tokp) + tok_kind expect1; + tok_kind expect2; + tok_kind expect3; + token *tokp; +{ + get_token(tokp); + if (tokp->kind != expect1 && tokp->kind != expect2 + && tokp->kind != expect3) { + expected3(expect1, expect2, expect3); + } +} +/* + * scan expecting a constant, possibly symbolic + */ +void +scan_num(tokp) + token *tokp; +{ + get_token(tokp); + switch (tokp->kind) { + case TOK_IDENT: + break; + default: + error("constant or identifier expected"); + } +} +/* + * Peek at the next token + */ +void +peek(tokp) + token *tokp; +{ + get_token(tokp); + unget_token(tokp); +} +/* + * Peek at the next token and scan it if it matches what you expect + */ +int +peekscan(expect, tokp) + tok_kind expect; + token *tokp; +{ + peek(tokp); + if (tokp->kind == expect) { + get_token(tokp); + return (1); + } + return (0); +} +/* + * Get the next token, printing out any directive that are encountered. + */ +void +get_token(tokp) + token *tokp; +{ + int commenting; + int stat = 0; + + if (pushed) { + pushed = 0; + *tokp = lasttok; + return; + } + commenting = 0; + for (;;) { + if (*where == 0) { + for (;;) { + if (!fgets(curline, MAXLINESIZE, fin)) { + tokp->kind = TOK_EOF; + /* now check if cpp returned non NULL value */ + waitpid(childpid, &stat, WUNTRACED); + if (stat > 0) { + /* Set return value from rpcgen */ + nonfatalerrors = stat >> 8; + } + *where = 0; + return; + } + linenum++; + if (commenting) { + break; + } else + /* skip lines beginning with #pragma */ + if (!strncmp(curline, "#pragma", 7)) *curline = 0; + else if (cppline(curline)) { + docppline(curline, &linenum, + &infilename); + } else + if (directive(curline)) { + printdirective(curline); + } else { + break; + } + } + where = curline; + } else + if (isspace(*where)) { + while (isspace(*where)) { + where++; /* eat */ + } + } else + if (commenting) { + for (where++; *where; where++) { + if (endcomment(where)) { + where++; + commenting--; + break; + } + } + } else + if (startcomment(where)) { + where += 2; + commenting++; + } else { + break; + } + } + + /* + * 'where' is not whitespace, comment or directive Must be a token! + */ + switch (*where) { + case ':': + tokp->kind = TOK_COLON; + where++; + break; + case ';': + tokp->kind = TOK_SEMICOLON; + where++; + break; + case ',': + tokp->kind = TOK_COMMA; + where++; + break; + case '=': + tokp->kind = TOK_EQUAL; + where++; + break; + case '*': + tokp->kind = TOK_STAR; + where++; + break; + case '[': + tokp->kind = TOK_LBRACKET; + where++; + break; + case ']': + tokp->kind = TOK_RBRACKET; + where++; + break; + case '{': + tokp->kind = TOK_LBRACE; + where++; + break; + case '}': + tokp->kind = TOK_RBRACE; + where++; + break; + case '(': + tokp->kind = TOK_LPAREN; + where++; + break; + case ')': + tokp->kind = TOK_RPAREN; + where++; + break; + case '<': + tokp->kind = TOK_LANGLE; + where++; + break; + case '>': + tokp->kind = TOK_RANGLE; + where++; + break; + + case '"': + tokp->kind = TOK_STRCONST; + findstrconst(&where, &tokp->str); + break; + case '\'': + tokp->kind = TOK_CHARCONST; + findchrconst(&where, &tokp->str); + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tokp->kind = TOK_IDENT; + findconst(&where, &tokp->str); + break; + + default: + if (!(isalpha(*where) || *where == '_')) { + char buf[100]; + char *p; + + s_print(buf, "illegal character in file: "); + p = buf + strlen(buf); + if (isprint(*where)) { + s_print(p, "%c", *where); + } else { + s_print(p, "%d", *where); + } + error(buf); + } + findkind(&where, tokp); + break; + } +} + +static void +unget_token(tokp) + token *tokp; +{ + lasttok = *tokp; + pushed = 1; +} + +static void +findstrconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + do { + p++; + } while (*p && *p != '"'); + if (*p == 0) { + error("unterminated string constant"); + } + p++; + size = p - *str; + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static void +findchrconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + do { + p++; + } while (*p && *p != '\''); + if (*p == 0) { + error("unterminated string constant"); + } + p++; + size = p - *str; + if (size != 3) { + error("empty char string"); + } + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static void +findconst(str, val) + char **str; + char **val; +{ + char *p; + int size; + + p = *str; + if (*p == '0' && *(p + 1) == 'x') { + p++; + do { + p++; + } while (isxdigit(*p)); + } else { + do { + p++; + } while (isdigit(*p)); + } + size = p - *str; + *val = alloc(size + 1); + (void) strncpy(*val, *str, size); + (*val)[size] = 0; + *str = p; +} + +static token symbols[] = { + {TOK_CONST, "const"}, + {TOK_UNION, "union"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_STRUCT, "struct"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_ENUM, "enum"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_CHAR, "char"}, + {TOK_INT, "int"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_HYPER, "hyper"}, + {TOK_FLOAT, "float"}, + {TOK_DOUBLE, "double"}, + {TOK_QUAD, "quadruple"}, + {TOK_STRING, "string"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"}, +}; + +static void +findkind(mark, tokp) + char **mark; + token *tokp; +{ + int len; + token *s; + char *str; + + str = *mark; + for (s = symbols; s->kind != TOK_EOF; s++) { + len = strlen(s->str); + if (strncmp(str, s->str, len) == 0) { + if (!isalnum(str[len]) && str[len] != '_') { + tokp->kind = s->kind; + tokp->str = s->str; + *mark = str + len; + return; + } + } + } + tokp->kind = TOK_IDENT; + for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); + tokp->str = alloc(len + 1); + (void) strncpy(tokp->str, str, len); + tokp->str[len] = 0; + *mark = str + len; +} + +static int +cppline(line) + char *line; +{ + return (line == curline && *line == '#'); +} + +static int +directive(line) + char *line; +{ + return (line == curline && *line == '%'); +} + +static void +printdirective(line) + char *line; +{ + f_print(fout, "%s", line + 1); +} + +static void +docppline(line, lineno, fname) + char *line; + int *lineno; + char **fname; +{ + char *file; + int num; + char *p; + + line++; + while (isspace(*line)) { + line++; + } + num = atoi(line); + while (isdigit(*line)) { + line++; + } + while (isspace(*line)) { + line++; + } + if (*line != '"') { + error("preprocessor error"); + } + line++; + p = file = alloc(strlen(line) + 1); + while (*line && *line != '"') { + *p++ = *line++; + } + if (*line == 0) { + error("preprocessor error"); + } + *p = 0; + if (*file == 0) { + *fname = NULL; + } else { + *fname = file; + } + *lineno = num - 1; +} diff --git a/developer_cmds/rpcgen/rpc_scan.h b/developer_cmds/rpcgen/rpc_scan.h new file mode 100644 index 0000000..e4c57c8 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_scan.h @@ -0,0 +1,104 @@ +/* $NetBSD: rpc_scan.h,v 1.4 1997/10/11 21:01:50 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_scan.h 1.3 90/08/29 (C) 1987 SMI */ + +/* + * rpc_scan.h, Definitions for the RPCL scanner + */ + +/* + * kinds of tokens + */ +enum tok_kind { + TOK_IDENT, + TOK_CHARCONST, + TOK_STRCONST, + TOK_LPAREN, + TOK_RPAREN, + TOK_LBRACE, + TOK_RBRACE, + TOK_LBRACKET, + TOK_RBRACKET, + TOK_LANGLE, + TOK_RANGLE, + TOK_STAR, + TOK_COMMA, + TOK_EQUAL, + TOK_COLON, + TOK_SEMICOLON, + TOK_CONST, + TOK_STRUCT, + TOK_UNION, + TOK_SWITCH, + TOK_CASE, + TOK_DEFAULT, + TOK_ENUM, + TOK_TYPEDEF, + TOK_INT, + TOK_SHORT, + TOK_LONG, + TOK_HYPER, + TOK_UNSIGNED, + TOK_FLOAT, + TOK_DOUBLE, + TOK_QUAD, + TOK_OPAQUE, + TOK_CHAR, + TOK_STRING, + TOK_BOOL, + TOK_VOID, + TOK_PROGRAM, + TOK_VERSION, + TOK_EOF +}; +typedef enum tok_kind tok_kind; + +/* + * a token + */ +struct token { + tok_kind kind; + char *str; +}; +typedef struct token token; + + +/* + * routine interface + */ +void scan __P((tok_kind, token *)); +void scan2 __P((tok_kind, tok_kind, token *)); +void scan3 __P((tok_kind, tok_kind, tok_kind, token *)); +void scan_num __P((token *)); +void peek __P((token *)); +int peekscan __P((tok_kind, token *)); +void get_token __P((token *)); diff --git a/developer_cmds/rpcgen/rpc_svcout.c b/developer_cmds/rpcgen/rpc_svcout.c new file mode 100644 index 0000000..cb0ed46 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_svcout.c @@ -0,0 +1,980 @@ +/* $NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_svcout.c,v 1.10 1997/10/18 10:54:07 lukem Exp $"); +#endif +#endif + +/* + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler + */ +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +static char RQSTP[] = "rqstp"; +static char TRANSP[] = "transp"; +static char ARG[] = "argument"; +static char RESULT[] = "result"; +static char ROUTINE[] = "local"; + +static void p_xdrfunc __P((char *, char *)); +static void internal_proctype __P((proc_list *)); +static void write_real_program __P((definition *)); +static void write_program __P((definition *, char *)); +static void printerr __P((char *, char *)); +static void printif __P((char *, char *, char *, char *)); +static void write_inetmost __P((char *)); +static void print_return __P((char *)); +static void print_pmapunset __P((char *)); +static void print_err_message __P((char *)); +static void write_timeout_func __P((void)); +static void write_caller_func __P((void)); +static void write_pm_most __P((char *, int)); +static void write_rpc_svc_fg __P((char *, char *)); +static void open_log_file __P((char *, char *)); + +char _errbuf[256]; /* For all messages */ + +static void +p_xdrfunc(rname, typename) + char *rname; + char *typename; +{ + if (Cflag) + f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname, + stringfix(typename)); + else + f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename)); +} + +static void +internal_proctype(plist) + proc_list *plist; +{ + f_print(fout, "static "); + ptype(plist->res_prefix, plist->res_type, 1); + f_print(fout, "*"); +} + + +/* + * write most of the service, that is, everything but the registrations. + */ +void +write_most(infile, netflag, nomain) + char *infile; /* our name */ + int netflag; + int nomain; +{ + if (inetdflag || pmflag) { + char *var_type; + var_type = (nomain ? "extern" : "static"); + f_print(fout, "%s int _rpcpmstart;", var_type); + f_print(fout, "\t\t/* Started by a port monitor ? */\n"); + f_print(fout, "%s int _rpcfdtype;", var_type); + f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n"); + if (timerflag) { + f_print(fout, "%s int _rpcsvcdirty;", var_type); + f_print(fout, "\t/* Still serving ? */\n"); + } + write_svc_aux(nomain); + } + /* write out dispatcher and stubs */ + write_programs(nomain ? (char *) NULL : "static"); + + if (nomain) + return; + + f_print(fout, "\n\n"); + if (Cflag) + f_print(fout, "int main( int argc, char* argv[] );\n"); + f_print(fout, "\nint\n"); + if (Cflag) + f_print(fout, "main( int argc, char* argv[] )\n"); + else + f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n"); + f_print(fout, "{\n"); + if (inetdflag) { + write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */ + } else { + if (tirpcflag) { + if (netflag) { + f_print(fout, "\tSVCXPRT *%s;\n", TRANSP); + f_print(fout, "\tstruct netconfig *nconf = NULL;\n"); + } + f_print(fout, "\tpid_t pid;\n"); + f_print(fout, "\tint i;\n"); + f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + write_pm_most(infile, netflag); + f_print(fout, "\telse {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t}\n"); + } else { + f_print(fout, "\tSVCXPRT *%s;\n", TRANSP); + f_print(fout, "\n"); + print_pmapunset("\t"); + } + } + + if (logflag && !inetdflag) { + open_log_file(infile, "\t"); + } +} +/* + * write a registration for the given transport + */ +void +write_netid_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + char *sp; + char tmpbuf[32]; + + sp = ""; + f_print(fout, "\n"); + f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp); + f_print(fout, "%s\tif (nconf == NULL) {\n", sp); + (void) sprintf(_errbuf, "cannot find %s netid.", transp); + sprintf(tmpbuf, "%s\t\t", sp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n", + sp, TRANSP); + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + (void) sprintf(_errbuf, "cannot create %s service.", transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, + "%s\t(void) rpcb_unset(%s, %s, nconf);\n", + sp, def->def_name, vp->vers_name); + f_print(fout, + "%s\tif (!svc_reg(%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", nconf)) {\n"); + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + } + } + f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp); +} +/* + * write a registration for the given transport for TLI + */ +void +write_nettype_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "\tif (!svc_create("); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", %s, %s, \"%s\")) {\n ", + def->def_name, vp->vers_name, transp); + (void) sprintf(_errbuf, + "unable to create (%s, %s) for %s.", + def->def_name, vp->vers_name, transp); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + } + } +} +/* + * write the rest of the service + */ +void +write_rest() +{ + f_print(fout, "\n"); + if (inetdflag) { + f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); + (void) sprintf(_errbuf, "could not create a handle"); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + if (timerflag) { + f_print(fout, "\tif (_rpcpmstart) {\n"); + f_print(fout, + "\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "\t}\n"); + } + } + f_print(fout, "\tsvc_run();\n"); + (void) sprintf(_errbuf, "svc_run returned"); + print_err_message("\t"); + f_print(fout, "\texit(1);\n"); + f_print(fout, "\t/* NOTREACHED */\n"); + f_print(fout, "}\n"); +} + +void +write_programs(storage) + char *storage; +{ + list *l; + definition *def; + + /* write out stubs for procedure definitions */ + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_real_program(def); + } + } + + /* write out dispatcher for each program */ + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_program(def, storage); + } + } + + +} +/* write out definition of internal function (e.g. _printmsg_1(...)) + which calls server's defintion of actual function (e.g. printmsg_1(...)). + Unpacks single user argument of printmsg_1 to call-by-value format + expected by printmsg_1. */ +static void +write_real_program(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + decl_list *l; + + if (!newstyle) + return; /* not needed for old style */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\n"); + internal_proctype(proc); + f_print(fout, "\n_"); + pvname(proc->proc_name, vp->vers_num); + if (Cflag) { + f_print(fout, "("); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, "%s", proc->args.argname); + else + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + f_print(fout, " *argp, struct svc_req *%s)\n", + RQSTP); + } else { + f_print(fout, "(argp, %s)\n", RQSTP); + /* arg name */ + if (proc->arg_num > 1) + f_print(fout, "\t%s *argp;\n", proc->args.argname); + else { + f_print(fout, "\t"); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + f_print(fout, " *argp;\n"); + } + f_print(fout, " struct svc_req *%s;\n", RQSTP); + } + + f_print(fout, "{\n"); + f_print(fout, "\treturn("); + pvname_svc(proc->proc_name, vp->vers_num); + f_print(fout, "("); + if (proc->arg_num < 2) { /* single argument */ + if (!streq(proc->args.decls->decl.type, "void")) + f_print(fout, "*argp, "); /* non-void */ + } else { + for (l = proc->args.decls; l != NULL; l = l->next) + f_print(fout, "argp->%s, ", l->decl.name); + } + f_print(fout, "%s));\n}\n", RQSTP); + } + } +} + +static void +write_program(def, storage) + definition *def; + char *storage; +{ + version_list *vp; + proc_list *proc; + int filled; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + if (Cflag) { + f_print(fout, "\n"); + if (storage != NULL) { + f_print(fout, "%s ", storage); + } + f_print(fout, "void "); + pvname(def->def_name, vp->vers_num); + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "SVCXPRT *%s);\n", TRANSP); + } + f_print(fout, "\n"); + if (storage != NULL) { + f_print(fout, "%s ", storage); + } + f_print(fout, "void\n"); + pvname(def->def_name, vp->vers_num); + + if (Cflag) { + f_print(fout, "(struct svc_req *%s, ", RQSTP); + f_print(fout, "SVCXPRT *%s)\n", TRANSP); + } else { + f_print(fout, "(%s, %s)\n", RQSTP, TRANSP); + f_print(fout, " struct svc_req *%s;\n", RQSTP); + f_print(fout, " SVCXPRT *%s;\n", TRANSP); + } + + f_print(fout, "{\n"); + + filled = 0; + f_print(fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (proc->arg_num < 2) { /* single argument */ + if (streq(proc->args.decls->decl.type, + "void")) { + continue; + } + filled = 1; + f_print(fout, "\t\t"); + ptype(proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + + } else { + filled = 1; + f_print(fout, "\t\t%s", proc->args.argname); + f_print(fout, " "); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_arg;\n"); + } + } + if (!filled) { + f_print(fout, "\t\tint fill;\n"); + } + f_print(fout, "\t} %s;\n", ARG); + f_print(fout, "\tchar *%s;\n", RESULT); + + if (Cflag) { + f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT); + f_print(fout, + "\tchar *(*%s)(char *, struct svc_req *);\n", + ROUTINE); + } else { + f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT); + f_print(fout, "\tchar *(*%s)();\n", ROUTINE); + } + + f_print(fout, "\n"); + + if (callerflag) + f_print(fout, "\tcaller = transp;\n"); /* EVAS */ + if (timerflag) + f_print(fout, "\t_rpcsvcdirty = 1;\n"); + f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP); + if (!nullproc(vp->procs)) { + f_print(fout, "\tcase NULLPROC:\n"); + f_print(fout, + "\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n", + TRANSP); + print_return("\t\t"); + f_print(fout, "\n"); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) { + f_print(fout, "\tcase %s:\n", proc->proc_name); + if (proc->arg_num < 2) { /* single argument */ + p_xdrfunc(ARG, proc->args.decls->decl.type); + } else { + p_xdrfunc(ARG, proc->args.argname); + } + p_xdrfunc(RESULT, proc->res_type); + if (Cflag) + f_print(fout, + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", + ROUTINE); + else + f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE); + + if (newstyle) { /* new style: calls internal routine */ + f_print(fout, "_"); + } + if (!newstyle) + pvname_svc(proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + f_print(fout, ";\n"); + f_print(fout, "\t\tbreak;\n\n"); + } + f_print(fout, "\tdefault:\n"); + printerr("noproc", TRANSP); + print_return("\t\t"); + f_print(fout, "\t}\n"); + + f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); + printif("getargs", TRANSP, "(caddr_t) &", ARG); + printerr("decode", TRANSP); + print_return("\t\t"); + f_print(fout, "\t}\n"); + + if (Cflag) + f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + else + f_print(fout, "\t%s = (*%s)(&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + f_print(fout, + "\tif (%s != NULL && !svc_sendreply(%s, (xdrproc_t) xdr_%s, %s)) {\n", + RESULT, TRANSP, RESULT, RESULT); + printerr("systemerr", TRANSP); + f_print(fout, "\t}\n"); + + printif("freeargs", TRANSP, "(caddr_t) &", ARG); + (void) sprintf(_errbuf, "unable to free arguments"); + print_err_message("\t\t"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t}\n"); + print_return("\t"); + f_print(fout, "}\n"); + } +} + +static void +printerr(err, transp) + char *err; + char *transp; +{ + f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp); +} + +static void +printif(proc, transp, prefix, arg) + char *proc; + char *transp; + char *prefix; + char *arg; +{ + f_print(fout, "\tif (!svc_%s(%s, xdr_%s, %s%s)) {\n", + proc, transp, arg, prefix, arg); +} + +int +nullproc(proc) + proc_list *proc; +{ + for (; proc != NULL; proc = proc->next) { + if (streq(proc->proc_num, "0")) { + return (1); + } + } + return (0); +} + +static void +write_inetmost(infile) + char *infile; +{ + f_print(fout, "\tSVCXPRT *%s = NULL;\n", TRANSP); + f_print(fout, "\tint sock;\n"); + f_print(fout, "\tint proto = 0;\n"); + f_print(fout, "\tstruct sockaddr_in saddr;\n"); + f_print(fout, "\tint asize = sizeof (saddr);\n"); + f_print(fout, "\n"); + f_print(fout, + "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print(fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n"); + f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\tsock = 0;\n"); + f_print(fout, "\t\t_rpcpmstart = 1;\n"); + f_print(fout, "\t\tproto = 0;\n"); + open_log_file(infile, "\t\t"); + f_print(fout, "\t} else {\n"); + write_rpc_svc_fg(infile, "\t\t"); + f_print(fout, "\t\tsock = RPC_ANYSOCK;\n"); + print_pmapunset("\t\t"); + f_print(fout, "\t}\n"); +} + +static void +print_return(space) + char *space; +{ + if (exitnow) + f_print(fout, "%sexit(0);\n", space); + else { + if (timerflag) + f_print(fout, "%s_rpcsvcdirty = 0;\n", space); + f_print(fout, "%sreturn;\n", space); + } +} + +static void +print_pmapunset(space) + char *space; +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + for (vp = def->def.pr.versions; vp != NULL; + vp = vp->next) { + f_print(fout, "%s(void) pmap_unset(%s, %s);\n", + space, def->def_name, vp->vers_name); + } + } + } +} + +static void +print_err_message(space) + char *space; +{ + if (logflag) + f_print(fout, "%ssyslog(LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf); + else + if (inetdflag || pmflag) + f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf); + else + f_print(fout, "%sfprintf(stderr, \"%%s\", \"%s\");\n", space, _errbuf); +} +/* + * Write the server auxiliary function ( _msgout, timeout) + */ +void +write_svc_aux(nomain) + int nomain; +{ + if (!logflag) + write_msg_out(); + if (!nomain) + write_timeout_func(); + if (callerflag) /* EVAS */ + write_caller_func(); /* EVAS */ +} +/* + * Write the _msgout function + */ +void +write_msg_out() +{ + f_print(fout, "\n"); + f_print(fout, "static\n"); + if (!Cflag) { + f_print(fout, "void _msgout(msg)\n"); + f_print(fout, "\tchar *msg;\n"); + } else { + f_print(fout, "void _msgout(char* msg)\n"); + } + f_print(fout, "{\n"); + f_print(fout, "#ifdef RPC_SVC_FG\n"); + if (inetdflag || pmflag) + f_print(fout, "\tif (_rpcpmstart)\n"); + f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n"); + f_print(fout, "\telse\n"); + f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n"); + f_print(fout, "#else\n"); + f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n"); + f_print(fout, "#endif\n"); + f_print(fout, "}\n"); +} +/* + * Write the timeout function + */ +static void +write_timeout_func() +{ + if (!timerflag) + return; + if (Cflag) { + f_print(fout, "\n"); + f_print(fout, "static void closedown(void);\n"); + } + f_print(fout, "\n"); + f_print(fout, "static void\n"); + f_print(fout, "closedown()\n"); + f_print(fout, "{\n"); + f_print(fout, "\tif (_rpcsvcdirty == 0) {\n"); + f_print(fout, "\t\textern fd_set svc_fdset;\n"); + f_print(fout, "\t\tstatic int size;\n"); + f_print(fout, "\t\tint i, openfd;\n"); + if (tirpcflag && pmflag) { + f_print(fout, "\t\tstruct t_info tinfo;\n\n"); + f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n"); + } else { + f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n"); + } + f_print(fout, "\t\t\texit(0);\n"); + f_print(fout, "\t\tif (size == 0) {\n"); + if (tirpcflag) { + f_print(fout, "\t\t\tstruct rlimit rl;\n\n"); + f_print(fout, "\t\t\trl.rlim_max = 0;\n"); + f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n"); + f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n"); + f_print(fout, "\t\t\t\treturn;\n"); + } else { + f_print(fout, "\t\t\tsize = getdtablesize();\n"); + } + f_print(fout, "\t\t}\n"); + f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n"); + f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); + f_print(fout, "\t\t\t\topenfd++;\n"); + f_print(fout, "\t\tif (openfd <= (_rpcpmstart?0:1))\n"); + f_print(fout, "\t\t\texit(0);\n"); + f_print(fout, "\t}\n"); + f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "}\n"); +} + +static void +write_caller_func() +{ /* EVAS */ +#define P(s) f_print(fout, s); + + P("\n"); + P("char *svc_caller()\n"); + P("{\n"); + P(" struct sockaddr_in actual;\n"); + P(" struct hostent *hp;\n"); + P(" static struct in_addr prev;\n"); + P(" static char cname[128];\n\n"); + + P(" actual = *svc_getcaller(caller);\n\n"); + + P(" if (memcmp((char *)&actual.sin_addr, (char *)&prev,\n"); + P(" sizeof(struct in_addr)) == 0)\n"); + P(" return (cname);\n\n"); + + P(" prev = actual.sin_addr;\n\n"); + + P(" hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET);\n"); + P(" if (hp == NULL) { /* dummy one up */\n"); + P(" extern char *inet_ntoa();\n"); + P(" strcpy(cname, inet_ntoa(actual.sin_addr));\n"); + P(" } else {\n"); + P(" strcpy(cname, hp->h_name);\n"); + P(" }\n\n"); + + P(" return (cname);\n"); + P("}\n"); + +#undef P +} +/* + * Write the most of port monitor support + */ +static void +write_pm_most(infile, netflag) + char *infile; + int netflag; +{ + list *l; + definition *def; + version_list *vp; + + f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); + f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); + f_print(fout, " !strcmp(mname, \"timod\"))) {\n"); + f_print(fout, "\t\tchar *netid;\n"); + if (!netflag) { /* Not included by -n option */ + f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n"); + f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP); + } + if (timerflag) + f_print(fout, "\t\tint pmclose;\n"); +/* not necessary, defined in /usr/include/stdlib */ +/* f_print(fout, "\t\textern char *getenv();\n");*/ + f_print(fout, "\n"); + f_print(fout, "\t\t_rpcpmstart = 1;\n"); + if (logflag) + open_log_file(infile, "\t\t"); + f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); + sprintf(_errbuf, "cannot get transport name"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); + sprintf(_errbuf, "cannot get transport info"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t}\n"); + /* + * A kludgy support for inetd services. Inetd only works with + * sockmod, and RPC works only with timod, hence all this jugglery + */ + f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); + f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); + sprintf(_errbuf, "could not get the right module"); + print_err_message("\t\t\t\t"); + f_print(fout, "\t\t\t\texit(1);\n"); + f_print(fout, "\t\t\t}\n"); + f_print(fout, "\t\t}\n"); + if (timerflag) + f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); + f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", + TRANSP); + sprintf(_errbuf, "cannot create server handle"); + print_err_message("\t\t\t"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\t}\n"); + f_print(fout, "\t\tif (nconf)\n"); + f_print(fout, "\t\t\tfreenetconfigent(nconf);\n"); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, + "\t\tif (!svc_reg(%s, %s, %s, ", + TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + f_print(fout, ", 0)) {\n"); + (void) sprintf(_errbuf, "unable to register (%s, %s).", + def->def_name, vp->vers_name); + print_err_message("\t\t\t"); + f_print(fout, "\t\t\texit(1);\n"); + f_print(fout, "\t\t}\n"); + } + } + if (timerflag) { + f_print(fout, "\t\tif (pmclose) {\n"); + f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print(fout, "\t\t}\n"); + } + f_print(fout, "\t\tsvc_run();\n"); + f_print(fout, "\t\texit(1);\n"); + f_print(fout, "\t\t/* NOTREACHED */\n"); + f_print(fout, "\t}\n"); +} +/* + * Support for backgrounding the server if self started. + */ +static void +write_rpc_svc_fg(infile, sp) + char *infile; + char *sp; +{ + f_print(fout, "#ifndef RPC_SVC_FG\n"); + f_print(fout, "%sint size;\n", sp); + if (tirpcflag) + f_print(fout, "%sstruct rlimit rl;\n", sp); + if (inetdflag) + f_print(fout, "%sint pid, i;\n\n", sp); + f_print(fout, "%spid = fork();\n", sp); + f_print(fout, "%sif (pid < 0) {\n", sp); + f_print(fout, "%s\tperror(\"cannot fork\");\n", sp); + f_print(fout, "%s\texit(1);\n", sp); + f_print(fout, "%s}\n", sp); + f_print(fout, "%sif (pid)\n", sp); + f_print(fout, "%s\texit(0);\n", sp); + /* get number of file descriptors */ + if (tirpcflag) { + f_print(fout, "%srl.rlim_max = 0;\n", sp); + f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); + f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); + f_print(fout, "%s\texit(1);\n", sp); + } else { + f_print(fout, "%ssize = getdtablesize();\n", sp); + } + + f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp); + f_print(fout, "%s\t(void) close(i);\n", sp); + /* Redirect stderr and stdout to console */ + f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp); + f_print(fout, "%s(void) dup2(i, 1);\n", sp); + f_print(fout, "%s(void) dup2(i, 2);\n", sp); + /* This removes control of the controlling terminal */ + if (tirpcflag) + f_print(fout, "%ssetsid();\n", sp); + else { + f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp); + f_print(fout, "%sif (i >= 0) {\n", sp); + f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);; + f_print(fout, "%s\t(void) close(i);\n", sp); + f_print(fout, "%s}\n", sp); + } + if (!logflag) + open_log_file(infile, sp); + f_print(fout, "#endif\n"); + if (logflag) + open_log_file(infile, sp); +} + +static void +open_log_file(infile, sp) + char *infile; + char *sp; +{ + char *s, *p; + + s = strrchr(infile, '.'); + if (s) + *s = '\0'; + p = strrchr(infile, '/'); + if (p) + p++; + else + p = infile; + f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, p); + if (s) + *s = '.'; +} + +/* + * write a registration for the given transport for Inetd + */ +void +write_inetd_register(transp) + char *transp; +{ + list *l; + definition *def; + version_list *vp; + char *sp; + int isudp; + char tmpbuf[32]; + + if (inetdflag) + sp = "\t"; + else + sp = ""; + if (streq(transp, "udp")) + isudp = 1; + else + isudp = 0; + f_print(fout, "\n"); + if (inetdflag) { + f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n", + isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); + } + if (inetdflag && streq(transp, "tcp")) { + f_print(fout, "%s\tif (_rpcpmstart)\n", sp); + + f_print(fout, "%s\t\t%s = svc%s_create(%s", + sp, TRANSP, "fd", inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + + f_print(fout, "%s\telse\n", sp); + + f_print(fout, "%s\t\t%s = svc%s_create(%s", + sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + + } else { + f_print(fout, "%s\t%s = svc%s_create(%s", + sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print(fout, ", 0, 0"); + f_print(fout, ");\n"); + } + f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + (void) sprintf(_errbuf, "cannot create %s service.", transp); + (void) sprintf(tmpbuf, "%s\t\t", sp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + + if (inetdflag) { + f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp); + f_print(fout, "%s\tproto = IPPROTO_%s;\n", + sp, isudp ? "UDP" : "TCP"); + } + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname(def->def_name, vp->vers_num); + if (inetdflag) + f_print(fout, ", proto)) {\n"); + else + f_print(fout, ", IPPROTO_%s)) {\n", + isudp ? "UDP" : "TCP"); + (void) sprintf(_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message(tmpbuf); + f_print(fout, "%s\t\texit(1);\n", sp); + f_print(fout, "%s\t}\n", sp); + } + } + if (inetdflag) + f_print(fout, "\t}\n"); +} diff --git a/developer_cmds/rpcgen/rpc_tblout.c b/developer_cmds/rpcgen/rpc_tblout.c new file mode 100644 index 0000000..610dcd0 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_tblout.c @@ -0,0 +1,179 @@ +/* $NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI"; +#else +__RCSID("$NetBSD: rpc_tblout.c,v 1.7 1997/10/18 10:54:11 lukem Exp $"); +#endif +#endif + +/* + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler + */ +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define TABSIZE 8 +#define TABCOUNT 5 +#define TABSTOP (TABSIZE*TABCOUNT) + +static char tabstr[TABCOUNT + 1] = "\t\t\t\t\t"; + +static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n"; +static char tbl_end[] = "};\n"; + +static char null_entry[] = "\t(char *(*)())0,\n\ + \t(xdrproc_t)xdr_void,\t\t0,\n\ + \t(xdrproc_t)xdr_void,\t\t0,\n"; + +static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; + +static void write_table __P((definition *)); +static void printit __P((char *, char *)); + +void +write_tables() +{ + list *l; + definition *def; + + f_print(fout, "\n"); + for (l = defined; l != NULL; l = l->next) { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) { + write_table(def); + } + } +} + +static void +write_table(def) + definition *def; +{ + version_list *vp; + proc_list *proc; + int current; + int expected; + char progvers[100]; + int warning; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) { + warning = 0; + s_print(progvers, "%s_%s", + locase(def->def_name), vp->vers_num); + /* print the table header */ + f_print(fout, tbl_hdr, progvers); + + if (nullproc(vp->procs)) { + expected = 0; + } else { + expected = 1; + f_print(fout, "%s", null_entry); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) { + if (expected != 0) + f_print(fout, "\n"); + current = atoi(proc->proc_num); + if (current != expected++) { + f_print(fout, + "/*\n * WARNING: table out of order\n */\n\n"); + if (warning == 0) { + f_print(stderr, + "WARNING %s table is out of order\n", + progvers); + warning = 1; + nonfatalerrors = 1; + } + expected = current + 1; + } + f_print(fout, "\t(char *(*)())RPCGEN_ACTION("); + + /* routine to invoke */ + if (!newstyle) + pvname_svc(proc->proc_name, vp->vers_num); + else { + if (newstyle) + f_print(fout, "_"); /* calls internal func */ + pvname(proc->proc_name, vp->vers_num); + } + f_print(fout, "),\n"); + + /* argument info */ + if (proc->arg_num > 1) + printit((char *) NULL, proc->args.argname); + else + /* do we have to do something special for + * newstyle */ + printit(proc->args.decls->decl.prefix, + proc->args.decls->decl.type); + /* result info */ + printit(proc->res_prefix, proc->res_type); + } + + /* print the table trailer */ + f_print(fout, "%s", tbl_end); + f_print(fout, tbl_nproc, progvers, progvers, progvers); + } +} + +static void +printit(prefix, type) + char *prefix; + char *type; +{ + int len; + int tabs; + + + len = fprintf(fout, "\txdr_%s,", stringfix(type)); + /* account for leading tab expansion */ + len += TABSIZE - 1; + /* round up to tabs required */ + tabs = (TABSTOP - len + TABSIZE - 1) / TABSIZE; + f_print(fout, "%s", &tabstr[TABCOUNT - tabs]); + + if (streq(type, "void")) { + f_print(fout, "0"); + } else { + f_print(fout, "sizeof ( "); + /* XXX: should "follow" be 1 ??? */ + ptype(prefix, type, 0); + f_print(fout, ")"); + } + f_print(fout, ",\n"); +} diff --git a/developer_cmds/rpcgen/rpc_util.c b/developer_cmds/rpcgen/rpc_util.c new file mode 100644 index 0000000..f51114c --- /dev/null +++ b/developer_cmds/rpcgen/rpc_util.c @@ -0,0 +1,513 @@ +/* $NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI"; +#else +__RCSID("$NetBSD: rpc_util.c,v 1.8 1997/10/18 10:54:14 lukem Exp $"); +#endif +#endif + +/* + * rpc_util.c, Utility routines for the RPC protocol compiler + */ +#include +#include +#include +#include +#include +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" + +#define ARGEXT "argument" + +static void printwhere __P((void)); + +char curline[MAXLINESIZE]; /* current read line */ +char *where = curline; /* current point in line */ +int linenum = 0; /* current line number */ + +char *infilename; /* input filename */ + +#define NFILES 7 +char *outfiles[NFILES]; /* output file names */ +int nfiles; + +FILE *fout; /* file pointer of current output */ +FILE *fin; /* file pointer of current input */ + +list *defined; /* list of defined things */ + +static char *toktostr __P((tok_kind)); +static void printbuf __P((void)); +static void printwhere __P((void)); +static int findit __P((definition *, char *)); +static char *fixit __P((char *, char *)); +static int typedefed __P((definition *, char *)); + +/* + * Reinitialize the world + */ +void +reinitialize() +{ + memset(curline, 0, MAXLINESIZE); + where = curline; + linenum = 0; + defined = NULL; +} +/* + * string equality + */ +int +streq(a, b) + char *a; + char *b; +{ + return (strcmp(a, b) == 0); +} +/* + * find a value in a list + */ +definition * +findval(lst, val, cmp) + list *lst; + char *val; + int (*cmp) __P((definition *, char *)); + +{ + + for (; lst != NULL; lst = lst->next) { + if ((*cmp) (lst->val, val)) { + return (lst->val); + } + } + return (NULL); +} +/* + * store a value in a list + */ +void +storeval(lstp, val) + list **lstp; + definition *val; +{ + list **l; + list *lst; + + + for (l = lstp; *l != NULL; l = (list **) & (*l)->next); + lst = ALLOC(list); + lst->val = val; + lst->next = NULL; + *l = lst; +} + +static int +findit(def, type) + definition *def; + char *type; +{ + return (streq(def->def_name, type)); +} + +static char * +fixit(type, orig) + char *type; + char *orig; +{ + definition *def; + + def = (definition *) FINDVAL(defined, type, findit); + if (def == NULL || def->def_kind != DEF_TYPEDEF) { + return (orig); + } + switch (def->def.ty.rel) { + case REL_VECTOR: + return (def->def.ty.old_type); + case REL_ALIAS: + return (fixit(def->def.ty.old_type, orig)); + default: + return (orig); + } +} + +char * +fixtype(type) + char *type; +{ + return (fixit(type, type)); +} + +char * +stringfix(type) + char *type; +{ + if (streq(type, "string")) { + return ("wrapstring"); + } else { + return (type); + } +} + +void +ptype(prefix, type, follow) + char *prefix; + char *type; + int follow; +{ + if (prefix != NULL) { + if (streq(prefix, "enum")) { + f_print(fout, "enum "); + } else { + f_print(fout, "struct "); + } + } + if (streq(type, "bool")) { + f_print(fout, "bool_t "); + } else + if (streq(type, "string")) { + f_print(fout, "char *"); + } else { + f_print(fout, "%s ", follow ? fixtype(type) : type); + } +} + +static int +typedefed(def, type) + definition *def; + char *type; +{ + if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) { + return (0); + } else { + return (streq(def->def_name, type)); + } +} + +int +isvectordef(type, rel) + char *type; + relation rel; +{ + definition *def; + + for (;;) { + switch (rel) { + case REL_VECTOR: + return (!streq(type, "string")); + case REL_ARRAY: + return (0); + case REL_POINTER: + return (0); + case REL_ALIAS: + def = (definition *) FINDVAL(defined, type, typedefed); + if (def == NULL) { + return (0); + } + type = def->def.ty.old_type; + rel = def->def.ty.rel; + } + } +} + +char * +locase(str) + char *str; +{ + char c; + static char buf[100]; + char *p = buf; + + while ((c = *str++) != '\0') { + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; + } + *p = 0; + return (buf); +} + +void +pvname_svc(pname, vnum) + char *pname; + char *vnum; +{ + f_print(fout, "%s_%s_svc", locase(pname), vnum); +} + +void +pvname(pname, vnum) + char *pname; + char *vnum; +{ + f_print(fout, "%s_%s", locase(pname), vnum); +} +/* + * print a useful (?) error message, and then die + */ +void +error(msg) + char *msg; +{ + printwhere(); + f_print(stderr, "%s, line %d: ", infilename, linenum); + f_print(stderr, "%s\n", msg); + crash(); +} +/* + * Something went wrong, unlink any files that we may have created and then + * die. + */ +void +crash() +{ + int i; + + for (i = 0; i < nfiles; i++) { + (void) unlink(outfiles[i]); + } + exit(1); +} + +void +record_open(file) + char *file; +{ + if (nfiles < NFILES) { + outfiles[nfiles++] = file; + } else { + f_print(stderr, "too many files!\n"); + crash(); + } +} + +static char expectbuf[100]; + +/* + * error, token encountered was not the expected one + */ +void +expected1(exp1) + tok_kind exp1; +{ + s_print(expectbuf, "expected '%s'", + toktostr(exp1)); + error(expectbuf); +} +/* + * error, token encountered was not one of two expected ones + */ +void +expected2(exp1, exp2) + tok_kind exp1, exp2; +{ + s_print(expectbuf, "expected '%s' or '%s'", + toktostr(exp1), + toktostr(exp2)); + error(expectbuf); +} +/* + * error, token encountered was not one of 3 expected ones + */ +void +expected3(exp1, exp2, exp3) + tok_kind exp1, exp2, exp3; +{ + s_print(expectbuf, "expected '%s', '%s' or '%s'", + toktostr(exp1), + toktostr(exp2), + toktostr(exp3)); + error(expectbuf); +} + +void +tabify(f, tab) + FILE *f; + int tab; +{ + while (tab--) { + (void) fputc('\t', f); + } +} + + +static token tokstrings[] = { + {TOK_IDENT, "identifier"}, + {TOK_CONST, "const"}, + {TOK_RPAREN, ")"}, + {TOK_LPAREN, "("}, + {TOK_RBRACE, "}"}, + {TOK_LBRACE, "{"}, + {TOK_LBRACKET, "["}, + {TOK_RBRACKET, "]"}, + {TOK_STAR, "*"}, + {TOK_COMMA, ","}, + {TOK_EQUAL, "="}, + {TOK_COLON, ":"}, + {TOK_SEMICOLON, ";"}, + {TOK_UNION, "union"}, + {TOK_STRUCT, "struct"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_ENUM, "enum"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_INT, "int"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_DOUBLE, "double"}, + {TOK_FLOAT, "float"}, + {TOK_CHAR, "char"}, + {TOK_STRING, "string"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"} +}; + +static char * +toktostr(kind) + tok_kind kind; +{ + token *sp; + + for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); + return (sp->str); +} + +static void +printbuf() +{ + char c; + int i; + int cnt; + +#define TABSIZE 4 + + for (i = 0; (c = curline[i]) != '\0'; i++) { + if (c == '\t') { + cnt = 8 - (i % TABSIZE); + c = ' '; + } else { + cnt = 1; + } + while (cnt--) { + (void) fputc(c, stderr); + } + } +} + +static void +printwhere() +{ + int i; + char c; + int cnt; + + printbuf(); + for (i = 0; i < where - curline; i++) { + c = curline[i]; + if (c == '\t') { + cnt = 8 - (i % TABSIZE); + } else { + cnt = 1; + } + while (cnt--) { + (void) fputc('^', stderr); + } + } + (void) fputc('\n', stderr); +} + +char * +make_argname(pname, vname) + char *pname; + char *vname; +{ + char *name; + + name = (char *) malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3); + if (!name) { + fprintf(stderr, "failed in malloc"); + exit(1); + } + sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT); + return (name); +} + +bas_type *typ_list_h; +bas_type *typ_list_t; + +void +add_type(len, type) + int len; + char *type; +{ + bas_type *ptr; + + if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) { + fprintf(stderr, "failed in malloc"); + exit(1); + } + ptr->name = type; + ptr->length = len; + ptr->next = NULL; + if (typ_list_t == NULL) { + typ_list_t = ptr; + typ_list_h = ptr; + } else { + typ_list_t->next = ptr; + typ_list_t = ptr; + } +} + +bas_type * +find_type(type) + char *type; +{ + bas_type *ptr; + + ptr = typ_list_h; + + + while (ptr != NULL) { + if (strcmp(ptr->name, type) == 0) + return (ptr); + else + ptr = ptr->next; + } + return (NULL); +} diff --git a/developer_cmds/rpcgen/rpc_util.h b/developer_cmds/rpcgen/rpc_util.h new file mode 100644 index 0000000..33a84b3 --- /dev/null +++ b/developer_cmds/rpcgen/rpc_util.h @@ -0,0 +1,178 @@ +/* $NetBSD: rpc_util.h,v 1.4 1997/10/11 21:01:58 christos Exp $ */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* @(#)rpc_util.h 1.5 90/08/29 (C) 1987 SMI */ + +/* + * rpc_util.h, Useful definitions for the RPC protocol compiler + */ +#include +#include + +#define alloc(size) (void *)malloc((unsigned)(size)) +#define ALLOC(object) (object *) malloc(sizeof(object)) + +#define s_print (void) sprintf +#define f_print (void) fprintf + +struct list { + definition *val; + struct list *next; +}; +typedef struct list list; + +#define PUT 1 +#define GET 2 + +/* + * Global variables + */ +#define MAXLINESIZE 1024 +extern char curline[MAXLINESIZE]; +extern char *where; +extern int linenum; + +extern char *infilename; +extern FILE *fout; +extern FILE *fin; + +extern list *defined; + + +extern bas_type *typ_list_h; +extern bas_type *typ_list_t; + +/* + * All the option flags + */ +extern int inetdflag; +extern int pmflag; +extern int tblflag; +extern int logflag; +extern int newstyle; +extern int Cflag; /* C++ flag */ +extern int tirpcflag; /* flag for generating tirpc code */ +extern int doinline; /* if this is 0, then do not generate inline code */ +extern int callerflag; + +/* + * Other flags related with inetd jumpstart. + */ +extern int indefinitewait; +extern int exitnow; +extern int timerflag; + +extern int nonfatalerrors; + +extern pid_t childpid; + +/* + * rpc_util routines + */ + +#define STOREVAL(list,item) \ + storeval(list,item) + +#define FINDVAL(list,item,finder) \ + findval(list, item, finder) + +void reinitialize __P((void)); +int streq __P((char *, char *)); +definition *findval __P((list *, char *, int (*)(definition *, char *))); +void storeval __P((list **, definition *)); +char *fixtype __P((char *)); +char *stringfix __P((char *)); +void ptype __P((char *, char *, int)); +int isvectordef __P((char *, relation)); +char *locase __P((char *)); +void pvname_svc __P((char *, char *)); +void pvname __P((char *, char *)); +void error __P((char *)); +void crash __P((void)); +void record_open __P((char *)); +void expected1 __P((tok_kind)); +void expected2 __P((tok_kind, tok_kind )); +void expected3 __P((tok_kind, tok_kind, tok_kind)); +void tabify __P((FILE *, int)); +void record_open __P((char *)); +char *make_argname __P((char *, char *)); +void add_type __P((int, char *)); +bas_type *find_type __P((char *)); +/* + * rpc_cout routines + */ +void emit __P((definition *)); +void emit_inline __P((declaration *, int)); +void emit_single_in_line __P((declaration *, int, relation)); +char *upcase __P((char *)); + +/* + * rpc_hout routines + */ + +void print_datadef __P((definition *)); +void print_funcdef __P((definition *)); +void pxdrfuncdecl __P((char *, int)); +void pprocdef __P((proc_list *, version_list *, char *, int, int)); +void pdeclaration __P((char *, declaration *, int, char *)); + +/* + * rpc_svcout routines + */ +void write_most __P((char *, int, int)); +void write_netid_register __P((char *)); +void write_nettype_register __P((char *)); +void write_rest __P((void)); +void write_programs __P((char *)); +int nullproc __P((proc_list *)); +void write_svc_aux __P((int)); +void write_msg_out __P((void)); +void write_inetd_register __P((char *)); + +/* + * rpc_clntout routines + */ +void write_stubs __P((void)); +void printarglist __P((proc_list *, char *, char *)); + + +/* + * rpc_tblout routines + */ +void write_tables __P((void)); + +/* + * rpc_sample routines + */ +void write_sample_svc __P((definition *)); +int write_sample_clnt __P((definition *)); +void add_sample_msg __P((void)); +void write_sample_clnt_main __P((void)); diff --git a/developer_cmds/rpcgen/rpcgen.1 b/developer_cmds/rpcgen/rpcgen.1 new file mode 100644 index 0000000..a5764a6 --- /dev/null +++ b/developer_cmds/rpcgen/rpcgen.1 @@ -0,0 +1,452 @@ +.\" $NetBSD: rpcgen.1,v 1.8 1998/04/28 07:19:29 fair Exp $ +.\" from: @(#)rpcgen.new.1 1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89 +.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved. +.Dd June 11, 1995 +.Dt RPCGEN 1 +.Sh NAME +.Nm rpcgen +.Nd Remote Procedure Call (RPC) protocol compiler +.Sh SYNOPSIS +.Nm +.Ar infile +.Nm +.Op Fl D Op Ar name=value +.Op Fl A +.Op Fl M +.Op Fl T +.Op Fl K Ar secs +.Ar infile +.Nm +.Op Fl L +.Fl c Li | +.Fl h Li | +.Fl l Li | +.Fl m Li | +.Fl t Li | +.Fl S\&c Li | +.Fl S\&s Li | +.Op Fl o Ar outfile +.Op Ar infile +.Nm +.Fl c Li | +.Ar nettype +.Op Fl o Ar outfile +.Op Ar infile +.Nm +.Fl s Li | +.Ar netid +.Op Fl o Ar outfile +.Op Ar infile +.Sh DESCRIPTION +.Nm +is a tool that generates C code to implement an +.Tn RPC +protocol. +The input to +.Nm +is a language similar to C known as +.Tn RPC +Language (Remote Procedure Call Language). +.Nm +is normally used as in the first synopsis where +it takes an input file and generates up to four output files. +If the +.Ar infile +is named +.Pa proto.x , +then +.Nm +will generate a header file in +.Pa proto.h , +.Tn XDR +routines in +.Pa proto_xdr.c , +server-side stubs in +.Pa proto_svc.c , +and client-side stubs in +.Pa proto_clnt.c . +With the +.Fl T +option, +it will also generate the +.Tn RPC +dispatch table in +.Pa proto_tbl.i . +With the +.Fl S\&c +option, +it will also generate sample code which would illustrate how to use the +remote procedures on the client side. This code would be created in +.Pa proto_client.c . +With the +.Fl S\&s +option, +it will also generate a sample server code which would illustrate how to write +the remote procedures. This code would be created in +.Pa proto_server.c . +.Pp +The server created can be started both by the port monitors +(for example, +.Em inetd +or +.Em listen ) +or by itself. +When it is started by a port monitor, +it creates servers only for the transport for which +the file descriptor 0 was passed. +The name of the transport must be specified +by setting up the environmental variable +.Ev PM_TRANSPORT . +When the server generated by +.Nm +is executed, +it creates server handles for all the transports +specified in +.Ev NETPATH +environment variable, +or if it is unset, +it creates server handles for all the visible transports from +.Pa /etc/netconfig +file. +.Pp +.Em Note: +the transports are chosen at run time and not at compile time. +When the server is self-started, +it backgrounds itself by default. +A special define symbol +.Dv RPC_SVC_FG +can be used to run the server process in foreground. +.P +The second synopsis provides special features which allow +for the creation of more sophisticated +.Tn RPC +servers. +These features include support for user provided +.Li #defines +and +.Tn RPC +dispatch tables. +The entries in the +.Tn RPC +dispatch table contain: +.Pp +.Bl -inset -offset indent -compact +.It + +pointers to the service routine corresponding to that procedure, +.It + +a pointer to the input and output arguments, +.It + +the size of these routines +.El +.Pp +A server can use the dispatch table to check authorization +and then to execute the service routine; +a client library may use it to deal with the details of storage +management and +.Tn XDR +data conversion. +.Pp +The other three synopses shown above are used when +one does not want to generate all the output files, +but only a particular one. +Some examples of their usage is described in the +EXAMPLE +section below. +When +.Nm +is executed with the +.Fl s +option, +it creates servers for that particular class of transports. +When +executed with the +.Fl n +option, +it creates a server for the transport specified by +.Em netid . +If +.Ar infile +is not specified, +.Nm +accepts the standard input. +.Pp +The C preprocessor, +.Xr cpp 1 +is run on the input file before it is actually interpreted by +.Nm +For each type of output file, +.Nm +defines a special preprocessor symbol for use by the +.Nm +programmer: +.Bl -tag -width RPC_CLNT +.It Dv RPC_HDR +defined when compiling into header files +.It Dv RPC_XDR +defined when compiling into +.Tn XDR +routines +.It Dv RPC_SVC +defined when compiling into server-side stubs +.It Dv RPC_CLNT +defined when compiling into client-side stubs +.It Dv RPC_TBL +defined when compiling into +.Tn RPC +dispatch tables +.El +.Pp +Any line beginning with +.Sq % +is passed directly into the output file, +uninterpreted by +.Nm . +.Pp +For every data type referred to in +.Ar infile +.Nm +assumes that there exists a +routine with the string +.Dq xdr_ +prepended to the name of the data type. +If this routine does not exist in the +.Tn RPC/XDR +library, it must be provided. +Providing an undefined data type +allows customization of +.Tn XDR +routines. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl a +Generate all the files including sample code for client and server side. +.It Fl b +This generates code for the +.Tn "SunOS 4.1" +style of +.Tn RPC . +This is the default. +.It Fl C +Generate code in +.Tn ANSI +C. +This option also generates code that could be compiled with the +C++ compiler. +.It Fl c +Compile into +.Tn XDR +routines. +.It Fl D Ar name Ns Op Ar =value +Define a symbol +.Dv name . +Equivalent to the +.Dv #define +directive in the source. +If no +.Dv value +is given, +.Dv value +is defined as 1. +This option may be specified more than once. +.It Fl h +Compile into C data-definitions (a header file). +The +.Fl T +option can be used in conjunction to produce a +header file which supports +.Tn RPC +dispatch tables. +.It Fl K Ar secs +By default, services created using +.Nm +wait 120 seconds +after servicing a request before exiting. +That interval can be changed using the +.Fl K +flag. +To create a server that exits immediately upon servicing a request, +.Dq Fl K No 0 +can be used. +To create a server that never exits, the appropriate argument is +.Dq Fl K No -1 . +.Pp +When monitoring for a server, +some port monitors, like the +.At V.4 +utility +.Xr listen 1 , +.Em always +spawn a new process in response to a service request. +If it is known that a server will be used with such a monitor, the +server should exit immediately on completion. +For such servers, +.Nm +should be used with +.Dq Fl K No -1 . +.It Fl L +Server errors will be sent to syslog instead of stderr. +.It Fl l +Compile into client-side stubs. +.It Fl m +Compile into server-side stubs, +but do not generate a +.Fn main +routine. +This option is useful for doing callback-routines +and for users who need to write their own +.Fn main +routine to do initialization. +.It Fl N +Use the newstyle of +.Nm . +This allows procedures to have multiple arguments. +It also uses the style of parameter passing that closely resembles C. +So, when passing an argument to a remote procedure you do not have +to pass a pointer to the argument but the argument itself. +This behaviour is different from the oldstyle +of +.Nm +generated code. +The newstyle is not the default case because of backward compatibility. +.It Fl n Ar netid +Compile into server-side stubs for the transport +specified by +.Ar netid. +There should be an entry for +.Ar netid +in the +netconfig database. +This option may be specified more than once, +so as to compile a server that serves multiple transports. +.It Fl o Ar outfile +Specify the name of the output file. +If none is specified, +standard output is used +.Po +.Fl c Fl h Fl l +.Fl m Fl n Fl s +modes only +.Pc +.It Fl S\&c +Generate sample code to show the use of remote procedure and how to bind +to the server before calling the client side stubs generated by +.Nm . +.It Fl S\&s +Generate skeleton code for the remote procedures on the server side. You would need +to fill in the actual code for the remote procedures. +.It Fl s Ar nettype +Compile into server-side stubs for all the +transports belonging to the class +.Ar nettype . +The supported classes are +.Em netpath, +.Em visible, +.Em circuit_n, +.Em circuit_v, +.Em datagram_n, +.Em datagram_v, +.Em tcp, +and +.Em udp +[see +.Xr rpc 3 +for the meanings associated with these classes. +.Em Note: +.Bx +currently supports only the +.Em tcp +and +.Em udp +classes]. +This option may be specified more than once. +.Em Note: +the transports are chosen at run time and not at compile time. +.It Fl T +Generate the code to support +.Tn RPC +dispatch tables. +.It Fl t +Compile into +.Tn RPC +dispatch table. +.El +.Pp +The options +.Fl c , +.Fl h , +.Fl l , +.Fl m , +.Fl s , +and +.Fl t +are used exclusively to generate a particular type of file, +while the options +.Fl D +and +.Fl T +are global and can be used with the other options. +.Sh NOTES +The +.Tn RPC +Language does not support nesting of structures. +As a work-around, +structures can be declared at the top-level, +and their name used inside other structures in +order to achieve the same effect. +.Pp +Name clashes can occur when using program definitions, +since the apparent scoping does not really apply. +Most of these can be avoided by giving +unique names for programs, +versions, +procedures and types. +.Pp +The server code generated with +.Fl n +option refers to the transport indicated by +.Em netid +and hence is very site specific. +.Sh EXAMPLE +.Pp +The command +.Pp +.Bd -literal -offset indent +$ rpcgen -T prot.x +.Ed +.Pp +generates the five files: +.Pa prot.h , +.Pa prot_clnt.c , +.Pa prot_svc.c , +.Pa prot_xdr.c +and +.Pa prot_tbl.i . +.Pp +The following example sends the C data-definitions (header file) +to standard output. +.Pp +.Bd -literal -offset indent +$ rpcgen -h prot.x +.Ed +.Pp +To send the test version of the +.Dv -DTEST , +server side stubs for +all the transport belonging to the class +.Em datagram_n +to standard output, use: +.Pp +.Bd -literal -offset indent +$ rpcgen -s datagram_n -DTEST prot.x +.Ed +.Pp +To create the server side stubs for the transport indicated by +.Em netid +.Em tcp , +use: +.Pp +.Bd -literal -offset indent +$ rpcgen -n tcp -o prot_svc.c prot.x +.Ed +.Sh SEE ALSO +.Xr cpp 1 diff --git a/developer_cmds/unifdef/unifdef.1 b/developer_cmds/unifdef/unifdef.1 new file mode 100644 index 0000000..292ee67 --- /dev/null +++ b/developer_cmds/unifdef/unifdef.1 @@ -0,0 +1,415 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2002 - 2010 Tony Finch . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Dave Yost. It was rewritten to support ANSI C by Tony Finch. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/usr.bin/unifdef/unifdef.1,v 1.30 2010/08/01 09:10:09 joel Exp $ +.\" +.Dd March 11, 2010 +.Dt UNIFDEF 1 +.Os +.Sh NAME +.Nm unifdef , unifdefall +.Nd remove preprocessor conditionals from code +.Sh SYNOPSIS +.Nm +.Op Fl bBcdeKknsStV +.Op Fl I Ns Ar path +.Op Fl D Ns Ar sym Ns Op = Ns Ar val +.Op Fl U Ns Ar sym +.Op Fl iD Ns Ar sym Ns Op = Ns Ar val +.Op Fl iU Ns Ar sym +.Ar ... +.Op Fl o Ar outfile +.Op Ar infile +.Nm unifdefall +.Op Fl I Ns Ar path +.Ar ... +.Ar file +.Sh DESCRIPTION +The +.Nm +utility selectively processes conditional +.Xr cpp 1 +directives. +It removes from a file +both the directives +and any additional text that they specify should be removed, +while otherwise leaving the file alone. +.Pp +The +.Nm +utility acts on +.Ic #if , #ifdef , #ifndef , #elif , #else , +and +.Ic #endif +lines. +A directive is only processed +if the symbols specified on the command line are sufficient to allow +.Nm +to get a definite value for its control expression. +If the result is false, +the directive and the following lines under its control are removed. +If the result is true, +only the directive is removed. +An +.Ic #ifdef +or +.Ic #ifndef +directive is passed through unchanged +if its controlling symbol is not specified on the command line. +Any +.Ic #if +or +.Ic #elif +control expression that has an unknown value or that +.Nm +cannot parse is passed through unchanged. +By default, +.Nm +ignores +.Ic #if +and +.Ic #elif +lines with constant expressions; +it can be told to process them by specifying the +.Fl k +flag on the command line. +.Pp +It understands a commonly-used subset +of the expression syntax for +.Ic #if +and +.Ic #elif +lines: +integer constants, +integer values of symbols defined on the command line, +the +.Fn defined +operator, +the operators +.Ic \&! , < , > , <= , >= , == , != , && , || , +and parenthesized expressions. +A kind of +.Dq "short circuit" +evaluation is used for the +.Ic && +operator: +if either operand is definitely false then the result is false, +even if the value of the other operand is unknown. +Similarly, +if either operand of +.Ic || +is definitely true then the result is true. +.Pp +In most cases, the +.Nm +utility does not distinguish between object-like macros +(without arguments) and function-like arguments (with arguments). +If a macro is not explicitly defined, or is defined with the +.Fl D +flag on the command-line, its arguments are ignored. +If a macro is explicitly undefined on the command line with the +.Fl U +flag, it may not have any arguments since this leads to a syntax error. +.Pp +The +.Nm +utility understands just enough about C +to know when one of the directives is inactive +because it is inside +a comment, +or affected by a backslash-continued line. +It spots unusually-formatted preprocessor directives +and knows when the layout is too odd for it to handle. +.Pp +A script called +.Nm unifdefall +can be used to remove all conditional +.Xr cpp 1 +directives from a file. +It uses +.Nm Fl s +and +.Nm cpp Fl dM +to get lists of all the controlling symbols +and their definitions (or lack thereof), +then invokes +.Nm +with appropriate arguments to process the file. +.Sh OPTIONS +.Pp +.Bl -tag -width indent -compact +.It Fl D Ns Ar sym Ns = Ns Ar val +Specify that a symbol is defined to a given value +which is used when evaluating +.Ic #if +and +.Ic #elif +control expressions. +.Pp +.It Fl D Ns Ar sym +Specify that a symbol is defined to the value 1. +.Pp +.It Fl U Ns Ar sym +Specify that a symbol is undefined. +If the same symbol appears in more than one argument, +the last occurrence dominates. +.Pp +.It Fl b +Replace removed lines with blank lines +instead of deleting them. +Mutually exclusive with the +.Fl B +option. +.Pp +.It Fl B +Compress blank lines around a deleted section. +Mutually exclusive with the +.Fl b +option. +.Pp +.It Fl c +If the +.Fl c +flag is specified, +then the operation of +.Nm +is complemented, +i.e., the lines that would have been removed or blanked +are retained and vice versa. +.Pp +.It Fl d +Turn on printing of debugging messages. +.Pp +.It Fl e +Because +.Nm +processes its input one line at a time, +it cannot remove preprocessor directives that span more than one line. +The most common example of this is a directive with a multi-line +comment hanging off its right hand end. +By default, +if +.Nm +has to process such a directive, +it will complain that the line is too obfuscated. +The +.Fl e +option changes the behaviour so that, +where possible, +such lines are left unprocessed instead of reporting an error. +.Pp +.It Fl K +Always treat the result of +.Ic && +and +.Ic || +operators as unknown if either operand is unknown, +instead of short-circuiting when unknown operands can't affect the result. +This option is for compatibility with older versions of +.Nm . +.Pp +.It Fl k +Process +.Ic #if +and +.Ic #elif +lines with constant expressions. +By default, sections controlled by such lines are passed through unchanged +because they typically start +.Dq Li "#if 0" +and are used as a kind of comment to sketch out future or past development. +It would be rude to strip them out, just as it would be for normal comments. +.Pp +.It Fl n +Add +.Li #line +directives to the output following any deleted lines, +so that errors produced when compiling the output file correspond to +line numbers in the input file. +.Pp +.It Fl o Ar outfile +Write output to the file +.Ar outfile +instead of the standard output. +If +.Ar outfile +is the same as the input file, +the output is written to a temporary file +which is renamed into place when +.Nm +completes successfully. +.Pp +.It Fl s +Instead of processing the input file as usual, +this option causes +.Nm +to produce a list of symbols that appear in expressions +that +.Nm +understands. +It is useful in conjunction with the +.Fl dM +option of +.Xr cpp 1 +for creating +.Nm +command lines. +.Pp +.It Fl S +Like the +.Fl s +option, but the nesting depth of each symbol is also printed. +This is useful for working out the number of possible combinations +of interdependent defined/undefined symbols. +.Pp +.It Fl t +Disables parsing for C comments +and line continuations, +which is useful +for plain text. +.Pp +.It Fl iD Ns Ar sym Ns Op = Ns Ar val +.It Fl iU Ns Ar sym +Ignore +.Ic #ifdef Ns s . +If your C code uses +.Ic #ifdef Ns s +to delimit non-C lines, +such as comments +or code which is under construction, +then you must tell +.Nm +which symbols are used for that purpose so that it will not try to parse +comments +and line continuations +inside those +.Ic #ifdef Ns s . +You can specify ignored symbols with +.Fl iD Ns Ar sym Ns Oo = Ns Ar val Oc +and +.Fl iU Ns Ar sym +similar to +.Fl D Ns Ar sym Ns Op = Ns Ar val +and +.Fl U Ns Ar sym +above. +.Pp +.It Fl I Ns Ar path +Specifies to +.Nm unifdefall +an additional place to look for +.Ic #include +files. +This option is ignored by +.Nm +for compatibility with +.Xr cpp 1 +and to simplify the implementation of +.Nm unifdefall . +.Pp +.It Fl V +Print version details. +.El +.Pp +The +.Nm +utility copies its output to +.Em stdout +and will take its input from +.Em stdin +if no +.Ar file +argument is given. +.Pp +The +.Nm +utility works nicely with the +.Fl D Ns Ar sym +option of +.Xr diff 1 . +.Sh EXIT STATUS +The +.Nm +utility exits 0 if the output is an exact copy of the input, +1 if not, and 2 if in trouble. +.Sh DIAGNOSTICS +.Bl -item +.It +Too many levels of nesting. +.It +Inappropriate +.Ic #elif , +.Ic #else +or +.Ic #endif . +.It +Obfuscated preprocessor control line. +.It +Premature +.Tn EOF +(with the line number of the most recent unterminated +.Ic #if ) . +.It +.Tn EOF +in comment. +.El +.Sh SEE ALSO +.Xr cpp 1 , +.Xr diff 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 2.9 . +.Tn ANSI\~C +support was added in +.Fx 4.7 . +.Sh AUTHORS +The original implementation was written by +.An Dave Yost Aq Dave@Yost.com . +.An Tony Finch Aq dot@dotat.at +rewrote it to support +.Tn ANSI\~C . +.Sh BUGS +Expression evaluation is very limited. +.Pp +Preprocessor control lines split across more than one physical line +(because of comments or backslash-newline) +cannot be handled in every situation. +.Pp +Trigraphs are not recognized. +.Pp +There is no support for symbols with different definitions at +different points in the source file. +.Pp +The text-mode and ignore functionality does not correspond to modern +.Xr cpp 1 +behaviour. diff --git a/developer_cmds/unifdef/unifdef.c b/developer_cmds/unifdef/unifdef.c new file mode 100644 index 0000000..8c54e6e --- /dev/null +++ b/developer_cmds/unifdef/unifdef.c @@ -0,0 +1,1235 @@ +/* + * Copyright (c) 2002 - 2011 Tony Finch + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * unifdef - remove ifdef'ed lines + * + * This code was derived from software contributed to Berkeley by Dave Yost. + * It was rewritten to support ANSI C by Tony Finch. The original version + * of unifdef carried the 4-clause BSD copyright licence. None of its code + * remains in this version (though some of the names remain) so it now + * carries a more liberal licence. + * + * Wishlist: + * provide an option which will append the name of the + * appropriate symbol after #else's and #endif's + * provide an option which will check symbols after + * #else's and #endif's to see that they match their + * corresponding #ifdef or #ifndef + * + * These require better buffer handling, which would also make + * it possible to handle all "dodgy" directives correctly. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char copyright[] = + "@(#) $Version: unifdef-2.5.6.21f1388 $\n" + "@(#) $FreeBSD: src/usr.bin/unifdef/unifdef.c,v 1.31 2011/01/21 18:10:11 fanf Exp $\n" + "@(#) $Author: Tony Finch (dot@dotat.at) $\n" + "@(#) $URL: http://dotat.at/prog/unifdef $\n" +; + +/* types of input lines: */ +typedef enum { + LT_TRUEI, /* a true #if with ignore flag */ + LT_FALSEI, /* a false #if with ignore flag */ + LT_IF, /* an unknown #if */ + LT_TRUE, /* a true #if */ + LT_FALSE, /* a false #if */ + LT_ELIF, /* an unknown #elif */ + LT_ELTRUE, /* a true #elif */ + LT_ELFALSE, /* a false #elif */ + LT_ELSE, /* #else */ + LT_ENDIF, /* #endif */ + LT_DODGY, /* flag: directive is not on one line */ + LT_DODGY_LAST = LT_DODGY + LT_ENDIF, + LT_PLAIN, /* ordinary line */ + LT_EOF, /* end of file */ + LT_ERROR, /* unevaluable #if */ + LT_COUNT +} Linetype; + +static char const * const linetype_name[] = { + "TRUEI", "FALSEI", "IF", "TRUE", "FALSE", + "ELIF", "ELTRUE", "ELFALSE", "ELSE", "ENDIF", + "DODGY TRUEI", "DODGY FALSEI", + "DODGY IF", "DODGY TRUE", "DODGY FALSE", + "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE", + "DODGY ELSE", "DODGY ENDIF", + "PLAIN", "EOF", "ERROR" +}; + +/* state of #if processing */ +typedef enum { + IS_OUTSIDE, + IS_FALSE_PREFIX, /* false #if followed by false #elifs */ + IS_TRUE_PREFIX, /* first non-false #(el)if is true */ + IS_PASS_MIDDLE, /* first non-false #(el)if is unknown */ + IS_FALSE_MIDDLE, /* a false #elif after a pass state */ + IS_TRUE_MIDDLE, /* a true #elif after a pass state */ + IS_PASS_ELSE, /* an else after a pass state */ + IS_FALSE_ELSE, /* an else after a true state */ + IS_TRUE_ELSE, /* an else after only false states */ + IS_FALSE_TRAILER, /* #elifs after a true are false */ + IS_COUNT +} Ifstate; + +static char const * const ifstate_name[] = { + "OUTSIDE", "FALSE_PREFIX", "TRUE_PREFIX", + "PASS_MIDDLE", "FALSE_MIDDLE", "TRUE_MIDDLE", + "PASS_ELSE", "FALSE_ELSE", "TRUE_ELSE", + "FALSE_TRAILER" +}; + +/* state of comment parser */ +typedef enum { + NO_COMMENT = false, /* outside a comment */ + C_COMMENT, /* in a comment like this one */ + CXX_COMMENT, /* between // and end of line */ + STARTING_COMMENT, /* just after slash-backslash-newline */ + FINISHING_COMMENT, /* star-backslash-newline in a C comment */ + CHAR_LITERAL, /* inside '' */ + STRING_LITERAL /* inside "" */ +} Comment_state; + +static char const * const comment_name[] = { + "NO", "C", "CXX", "STARTING", "FINISHING", "CHAR", "STRING" +}; + +/* state of preprocessor line parser */ +typedef enum { + LS_START, /* only space and comments on this line */ + LS_HASH, /* only space, comments, and a hash */ + LS_DIRTY /* this line can't be a preprocessor line */ +} Line_state; + +static char const * const linestate_name[] = { + "START", "HASH", "DIRTY" +}; + +/* + * Minimum translation limits from ISO/IEC 9899:1999 5.2.4.1 + */ +#define MAXDEPTH 64 /* maximum #if nesting */ +#define MAXLINE 4096 /* maximum length of line */ +#define MAXSYMS 4096 /* maximum number of symbols */ + +/* + * Sometimes when editing a keyword the replacement text is longer, so + * we leave some space at the end of the tline buffer to accommodate this. + */ +#define EDITSLOP 10 + +/* + * For temporary filenames + */ +#define TEMPLATE "unifdef.XXXXXX" + +/* + * Globals. + */ + +static bool compblank; /* -B: compress blank lines */ +static bool lnblank; /* -b: blank deleted lines */ +static bool complement; /* -c: do the complement */ +static bool debugging; /* -d: debugging reports */ +static bool iocccok; /* -e: fewer IOCCC errors */ +static bool strictlogic; /* -K: keep ambiguous #ifs */ +static bool killconsts; /* -k: eval constant #ifs */ +static bool lnnum; /* -n: add #line directives */ +static bool symlist; /* -s: output symbol list */ +static bool symdepth; /* -S: output symbol depth */ +static bool text; /* -t: this is a text file */ + +static const char *symname[MAXSYMS]; /* symbol name */ +static const char *value[MAXSYMS]; /* -Dsym=value */ +static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */ +static int nsyms; /* number of symbols */ + +static FILE *input; /* input file pointer */ +static const char *filename; /* input file name */ +static int linenum; /* current line number */ +static FILE *output; /* output file pointer */ +static const char *ofilename; /* output file name */ +static bool overwriting; /* output overwrites input */ +static char tempname[FILENAME_MAX]; /* used when overwriting */ + +static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ +static char *keyword; /* used for editing #elif's */ + +static const char *newline; /* input file format */ +static const char newline_unix[] = "\n"; +static const char newline_crlf[] = "\r\n"; + +static Comment_state incomment; /* comment parser state */ +static Line_state linestate; /* #if line parser state */ +static Ifstate ifstate[MAXDEPTH]; /* #if processor state */ +static bool ignoring[MAXDEPTH]; /* ignore comments state */ +static int stifline[MAXDEPTH]; /* start of current #if */ +static int depth; /* current #if nesting */ +static int delcount; /* count of deleted lines */ +static unsigned blankcount; /* count of blank lines */ +static unsigned blankmax; /* maximum recent blankcount */ +static bool constexpr; /* constant #if expression */ +static bool zerosyms = true; /* to format symdepth output */ +static bool firstsym; /* ditto */ + +static int exitstat; /* program exit status */ + +static void addsym(bool, bool, char *); +static void closeout(void); +static void debug(const char *, ...); +static void done(void); +static void error(const char *); +static int findsym(const char *); +static void flushline(bool); +static Linetype parseline(void); +static Linetype ifeval(const char **); +static void ignoreoff(void); +static void ignoreon(void); +static void keywordedit(const char *); +static void nest(void); +static void process(void); +static const char *skipargs(const char *); +static const char *skipcomment(const char *); +static const char *skipsym(const char *); +static void state(Ifstate); +static int strlcmp(const char *, const char *, size_t); +static void unnest(void); +static void usage(void); +static void version(void); + +#define endsym(c) (!isalnum((unsigned char)c) && c != '_') + +/* + * The main program. + */ +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1) + switch (opt) { + case 'i': /* treat stuff controlled by these symbols as text */ + /* + * For strict backwards-compatibility the U or D + * should be immediately after the -i but it doesn't + * matter much if we relax that requirement. + */ + opt = *optarg++; + if (opt == 'D') + addsym(true, true, optarg); + else if (opt == 'U') + addsym(true, false, optarg); + else + usage(); + break; + case 'D': /* define a symbol */ + addsym(false, true, optarg); + break; + case 'U': /* undef a symbol */ + addsym(false, false, optarg); + break; + case 'I': /* no-op for compatibility with cpp */ + break; + case 'b': /* blank deleted lines instead of omitting them */ + case 'l': /* backwards compatibility */ + lnblank = true; + break; + case 'B': /* compress blank lines around removed section */ + compblank = true; + break; + case 'c': /* treat -D as -U and vice versa */ + complement = true; + break; + case 'd': + debugging = true; + break; + case 'e': /* fewer errors from dodgy lines */ + iocccok = true; + break; + case 'K': /* keep ambiguous #ifs */ + strictlogic = true; + break; + case 'k': /* process constant #ifs */ + killconsts = true; + break; + case 'n': /* add #line directive after deleted lines */ + lnnum = true; + break; + case 'o': /* output to a file */ + ofilename = optarg; + break; + case 's': /* only output list of symbols that control #ifs */ + symlist = true; + break; + case 'S': /* list symbols with their nesting depth */ + symlist = symdepth = true; + break; + case 't': /* don't parse C comments */ + text = true; + break; + case 'V': /* print version */ + version(); + default: + usage(); + } + argc -= optind; + argv += optind; + if (compblank && lnblank) + errx(2, "-B and -b are mutually exclusive"); + if (argc > 1) { + errx(2, "can only do one file"); + } else if (argc == 1 && strcmp(*argv, "-") != 0) { + filename = *argv; + input = fopen(filename, "rb"); + if (input == NULL) + err(2, "can't open %s", filename); + } else { + filename = "[stdin]"; + input = stdin; + } + if (ofilename == NULL) { + ofilename = "[stdout]"; + output = stdout; + } else { + struct stat ist, ost; + if (stat(ofilename, &ost) == 0 && + fstat(fileno(input), &ist) == 0) + overwriting = (ist.st_dev == ost.st_dev + && ist.st_ino == ost.st_ino); + if (overwriting) { + const char *dirsep; + int ofd; + + dirsep = strrchr(ofilename, '/'); + if (dirsep != NULL) + snprintf(tempname, sizeof(tempname), + "%.*s/" TEMPLATE, + (int)(dirsep - ofilename), ofilename); + else + snprintf(tempname, sizeof(tempname), + TEMPLATE); + ofd = mkstemp(tempname); + if (ofd != -1) + output = fdopen(ofd, "wb+"); + if (output == NULL) + err(2, "can't create temporary file"); + fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)); + } else { + output = fopen(ofilename, "wb"); + if (output == NULL) + err(2, "can't open %s", ofilename); + } + } + process(); + abort(); /* bug */ +} + +static void +version(void) +{ + const char *c = copyright; + for (;;) { + while (*++c != '$') + if (*c == '\0') + exit(0); + while (*++c != '$') + putc(*c, stderr); + putc('\n', stderr); + } +} + +static void +usage(void) +{ + fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]" + " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); + exit(2); +} + +/* + * A state transition function alters the global #if processing state + * in a particular way. The table below is indexed by the current + * processing state and the type of the current line. + * + * Nesting is handled by keeping a stack of states; some transition + * functions increase or decrease the depth. They also maintain the + * ignore state on a stack. In some complicated cases they have to + * alter the preprocessor directive, as follows. + * + * When we have processed a group that starts off with a known-false + * #if/#elif sequence (which has therefore been deleted) followed by a + * #elif that we don't understand and therefore must keep, we edit the + * latter into a #if to keep the nesting correct. We use strncpy() to + * overwrite the 4 byte token "elif" with "if " without a '\0' byte. + * + * When we find a true #elif in a group, the following block will + * always be kept and the rest of the sequence after the next #elif or + * #else will be discarded. We edit the #elif into a #else and the + * following directive to #endif since this has the desired behaviour. + * + * "Dodgy" directives are split across multiple lines, the most common + * example being a multi-line comment hanging off the right of the + * directive. We can handle them correctly only if there is no change + * from printing to dropping (or vice versa) caused by that directive. + * If the directive is the first of a group we have a choice between + * failing with an error, or passing it through unchanged instead of + * evaluating it. The latter is not the default to avoid questions from + * users about unifdef unexpectedly leaving behind preprocessor directives. + */ +typedef void state_fn(void); + +/* report an error */ +static void Eelif (void) { error("Inappropriate #elif"); } +static void Eelse (void) { error("Inappropriate #else"); } +static void Eendif(void) { error("Inappropriate #endif"); } +static void Eeof (void) { error("Premature EOF"); } +static void Eioccc(void) { error("Obfuscated preprocessor control line"); } +/* plain line handling */ +static void print (void) { flushline(true); } +static void drop (void) { flushline(false); } +/* output lacks group's start line */ +static void Strue (void) { drop(); ignoreoff(); state(IS_TRUE_PREFIX); } +static void Sfalse(void) { drop(); ignoreoff(); state(IS_FALSE_PREFIX); } +static void Selse (void) { drop(); state(IS_TRUE_ELSE); } +/* print/pass this block */ +static void Pelif (void) { print(); ignoreoff(); state(IS_PASS_MIDDLE); } +static void Pelse (void) { print(); state(IS_PASS_ELSE); } +static void Pendif(void) { print(); unnest(); } +/* discard this block */ +static void Dfalse(void) { drop(); ignoreoff(); state(IS_FALSE_TRAILER); } +static void Delif (void) { drop(); ignoreoff(); state(IS_FALSE_MIDDLE); } +static void Delse (void) { drop(); state(IS_FALSE_ELSE); } +static void Dendif(void) { drop(); unnest(); } +/* first line of group */ +static void Fdrop (void) { nest(); Dfalse(); } +static void Fpass (void) { nest(); Pelif(); } +static void Ftrue (void) { nest(); Strue(); } +static void Ffalse(void) { nest(); Sfalse(); } +/* variable pedantry for obfuscated lines */ +static void Oiffy (void) { if (!iocccok) Eioccc(); Fpass(); ignoreon(); } +static void Oif (void) { if (!iocccok) Eioccc(); Fpass(); } +static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); } +/* ignore comments in this block */ +static void Idrop (void) { Fdrop(); ignoreon(); } +static void Itrue (void) { Ftrue(); ignoreon(); } +static void Ifalse(void) { Ffalse(); ignoreon(); } +/* modify this line */ +static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } +static void Mtrue (void) { keywordedit("else"); state(IS_TRUE_MIDDLE); } +static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); } +static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); } + +static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { +/* IS_OUTSIDE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif, + print, done, abort }, +/* IS_FALSE_PREFIX */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_PREFIX */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + print, Eeof, abort }, +/* IS_PASS_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif, + print, Eeof, abort }, +/* IS_FALSE_MIDDLE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif, + print, Eeof, abort }, +/* IS_PASS_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif, + print, Eeof, abort }, +/* IS_FALSE_ELSE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc, + drop, Eeof, abort }, +/* IS_TRUE_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc, + print, Eeof, abort }, +/* IS_FALSE_TRAILER */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc, + drop, Eeof, abort } +/*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF + TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY) + PLAIN EOF ERROR */ +}; + +/* + * State machine utility functions + */ +static void +ignoreoff(void) +{ + if (depth == 0) + abort(); /* bug */ + ignoring[depth] = ignoring[depth-1]; +} +static void +ignoreon(void) +{ + ignoring[depth] = true; +} +static void +keywordedit(const char *replacement) +{ + snprintf(keyword, tline + sizeof(tline) - keyword, + "%s%s", replacement, newline); + print(); +} +static void +nest(void) +{ + if (depth > MAXDEPTH-1) + abort(); /* bug */ + if (depth == MAXDEPTH-1) + error("Too many levels of nesting"); + depth += 1; + stifline[depth] = linenum; +} +static void +unnest(void) +{ + if (depth == 0) + abort(); /* bug */ + depth -= 1; +} +static void +state(Ifstate is) +{ + ifstate[depth] = is; +} + +/* + * Write a line to the output or not, according to command line options. + * If writing fails, closeout() will print the error and exit. + */ +static void +flushline(bool keep) +{ + if (symlist) + return; + if (keep ^ complement) { + bool blankline = tline[strspn(tline, " \t\r\n")] == '\0'; + if (blankline && compblank && blankcount != blankmax) { + delcount += 1; + blankcount += 1; + } else { + if (lnnum && delcount > 0 && + fprintf(output, "#line %d%s", linenum, newline) < 0) + closeout(); + if (fputs(tline, output) == EOF) + closeout(); + delcount = 0; + blankmax = blankcount = blankline ? blankcount + 1 : 0; + } + } else { + if (lnblank && fputs(newline, output) == EOF) + closeout(); + exitstat = 1; + delcount += 1; + blankcount = 0; + } + if (debugging && fflush(output) == EOF) + closeout(); +} + +/* + * The driver for the state machine. + */ +static void +process(void) +{ + /* When compressing blank lines, act as if the file + is preceded by a large number of blank lines. */ + blankmax = blankcount = 1000; + for (;;) { + Linetype lineval = parseline(); + trans_table[ifstate[depth]][lineval](); + debug("process line %d %s -> %s depth %d", + linenum, linetype_name[lineval], + ifstate_name[ifstate[depth]], depth); + } +} + +/* + * Flush the output and handle errors. + */ +static void +closeout(void) +{ + if (symdepth && !zerosyms) + printf("\n"); + if (ferror(output) || fclose(output) == EOF) { + if (overwriting) { + warn("couldn't write to temporary file"); + unlink(tempname); + errx(2, "%s unchanged", ofilename); + } else { + err(2, "couldn't write to %s", ofilename); + } + } +} + +/* + * Clean up and exit. + */ +static void +done(void) +{ + if (incomment) + error("EOF in comment"); + closeout(); + if (overwriting && rename(tempname, ofilename) == -1) { + warn("couldn't rename temporary file"); + unlink(tempname); + errx(2, "%s unchanged", ofilename); + } + exit(exitstat); +} + +/* + * Parse a line and determine its type. We keep the preprocessor line + * parser state between calls in the global variable linestate, with + * help from skipcomment(). + */ +static Linetype +parseline(void) +{ + const char *cp; + int cursym; + int kwlen; + Linetype retval; + Comment_state wascomment; + + linenum++; + if (fgets(tline, MAXLINE, input) == NULL) { + if (ferror(input)) + error(strerror(errno)); + else + return (LT_EOF); + } + if (newline == NULL) { + if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1) + newline = newline_crlf; + else + newline = newline_unix; + } + retval = LT_PLAIN; + wascomment = incomment; + cp = skipcomment(tline); + if (linestate == LS_START) { + if (*cp == '#') { + linestate = LS_HASH; + firstsym = true; + cp = skipcomment(cp + 1); + } else if (*cp != '\0') + linestate = LS_DIRTY; + } + if (!incomment && linestate == LS_HASH) { + keyword = tline + (cp - tline); + cp = skipsym(cp); + kwlen = cp - keyword; + /* no way can we deal with a continuation inside a keyword */ + if (strncmp(cp, "\\\r\n", 3) == 0 || + strncmp(cp, "\\\n", 2) == 0) + Eioccc(); + if (strlcmp("ifdef", keyword, kwlen) == 0 || + strlcmp("ifndef", keyword, kwlen) == 0) { + cp = skipcomment(cp); + if ((cursym = findsym(cp)) < 0) + retval = LT_IF; + else { + retval = (keyword[2] == 'n') + ? LT_FALSE : LT_TRUE; + if (value[cursym] == NULL) + retval = (retval == LT_TRUE) + ? LT_FALSE : LT_TRUE; + if (ignore[cursym]) + retval = (retval == LT_TRUE) + ? LT_TRUEI : LT_FALSEI; + } + cp = skipsym(cp); + } else if (strlcmp("if", keyword, kwlen) == 0) + retval = ifeval(&cp); + else if (strlcmp("elif", keyword, kwlen) == 0) + retval = ifeval(&cp) - LT_IF + LT_ELIF; + else if (strlcmp("else", keyword, kwlen) == 0) + retval = LT_ELSE; + else if (strlcmp("endif", keyword, kwlen) == 0) + retval = LT_ENDIF; + else { + linestate = LS_DIRTY; + retval = LT_PLAIN; + } + cp = skipcomment(cp); + if (*cp != '\0') { + linestate = LS_DIRTY; + if (retval == LT_TRUE || retval == LT_FALSE || + retval == LT_TRUEI || retval == LT_FALSEI) + retval = LT_IF; + if (retval == LT_ELTRUE || retval == LT_ELFALSE) + retval = LT_ELIF; + } + if (retval != LT_PLAIN && (wascomment || incomment)) { + retval += LT_DODGY; + if (incomment) + linestate = LS_DIRTY; + } + /* skipcomment normally changes the state, except + if the last line of the file lacks a newline, or + if there is too much whitespace in a directive */ + if (linestate == LS_HASH) { + size_t len = cp - tline; + if (fgets(tline + len, MAXLINE - len, input) == NULL) { + if (ferror(input)) + error(strerror(errno)); + /* append the missing newline at eof */ + strcpy(tline + len, newline); + cp += strlen(newline); + linestate = LS_START; + } else { + linestate = LS_DIRTY; + } + } + } + if (linestate == LS_DIRTY) { + while (*cp != '\0') + cp = skipcomment(cp + 1); + } + debug("parser line %d state %s comment %s line", linenum, + comment_name[incomment], linestate_name[linestate]); + return (retval); +} + +/* + * These are the binary operators that are supported by the expression + * evaluator. + */ +static Linetype op_strict(int *p, int v, Linetype at, Linetype bt) { + if(at == LT_IF || bt == LT_IF) return (LT_IF); + return (*p = v, v ? LT_TRUE : LT_FALSE); +} +static Linetype op_lt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a < b, at, bt); +} +static Linetype op_gt(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a > b, at, bt); +} +static Linetype op_le(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a <= b, at, bt); +} +static Linetype op_ge(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a >= b, at, bt); +} +static Linetype op_eq(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a == b, at, bt); +} +static Linetype op_ne(int *p, Linetype at, int a, Linetype bt, int b) { + return op_strict(p, a != b, at, bt); +} +static Linetype op_or(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_TRUE || bt == LT_TRUE)) + return (*p = 1, LT_TRUE); + return op_strict(p, a || b, at, bt); +} +static Linetype op_and(int *p, Linetype at, int a, Linetype bt, int b) { + if (!strictlogic && (at == LT_FALSE || bt == LT_FALSE)) + return (*p = 0, LT_FALSE); + return op_strict(p, a && b, at, bt); +} + +/* + * An evaluation function takes three arguments, as follows: (1) a pointer to + * an element of the precedence table which lists the operators at the current + * level of precedence; (2) a pointer to an integer which will receive the + * value of the expression; and (3) a pointer to a char* that points to the + * expression to be evaluated and that is updated to the end of the expression + * when evaluation is complete. The function returns LT_FALSE if the value of + * the expression is zero, LT_TRUE if it is non-zero, LT_IF if the expression + * depends on an unknown symbol, or LT_ERROR if there is a parse failure. + */ +struct ops; + +typedef Linetype eval_fn(const struct ops *, int *, const char **); + +static eval_fn eval_table, eval_unary; + +/* + * The precedence table. Expressions involving binary operators are evaluated + * in a table-driven way by eval_table. When it evaluates a subexpression it + * calls the inner function with its first argument pointing to the next + * element of the table. Innermost expressions have special non-table-driven + * handling. + */ +static const struct ops { + eval_fn *inner; + struct op { + const char *str; + Linetype (*fn)(int *, Linetype, int, Linetype, int); + } op[5]; +} eval_ops[] = { + { eval_table, { { "||", op_or } } }, + { eval_table, { { "&&", op_and } } }, + { eval_table, { { "==", op_eq }, + { "!=", op_ne } } }, + { eval_unary, { { "<=", op_le }, + { ">=", op_ge }, + { "<", op_lt }, + { ">", op_gt } } } +}; + +/* + * Function for evaluating the innermost parts of expressions, + * viz. !expr (expr) number defined(symbol) symbol + * We reset the constexpr flag in the last two cases. + */ +static Linetype +eval_unary(const struct ops *ops, int *valp, const char **cpp) +{ + const char *cp; + char *ep; + int sym; + bool defparen; + Linetype lt; + + cp = skipcomment(*cpp); + if (*cp == '!') { + debug("eval%d !", ops - eval_ops); + cp++; + lt = eval_unary(ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + if (lt != LT_IF) { + *valp = !*valp; + lt = *valp ? LT_TRUE : LT_FALSE; + } + } else if (*cp == '(') { + cp++; + debug("eval%d (", ops - eval_ops); + lt = eval_table(eval_ops, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + cp = skipcomment(cp); + if (*cp++ != ')') + return (LT_ERROR); + } else if (isdigit((unsigned char)*cp)) { + debug("eval%d number", ops - eval_ops); + *valp = strtol(cp, &ep, 0); + if (ep == cp) + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; + cp = skipsym(cp); + } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { + cp = skipcomment(cp+7); + debug("eval%d defined", ops - eval_ops); + if (*cp == '(') { + cp = skipcomment(cp+1); + defparen = true; + } else { + defparen = false; + } + sym = findsym(cp); + if (sym < 0) { + lt = LT_IF; + } else { + *valp = (value[sym] != NULL); + lt = *valp ? LT_TRUE : LT_FALSE; + } + cp = skipsym(cp); + cp = skipcomment(cp); + if (defparen && *cp++ != ')') + return (LT_ERROR); + constexpr = false; + } else if (!endsym(*cp)) { + debug("eval%d symbol", ops - eval_ops); + sym = findsym(cp); + cp = skipsym(cp); + if (sym < 0) { + lt = LT_IF; + cp = skipargs(cp); + } else if (value[sym] == NULL) { + *valp = 0; + lt = LT_FALSE; + } else { + *valp = strtol(value[sym], &ep, 0); + if (*ep != '\0' || ep == value[sym]) + return (LT_ERROR); + lt = *valp ? LT_TRUE : LT_FALSE; + cp = skipargs(cp); + } + constexpr = false; + } else { + debug("eval%d bad expr", ops - eval_ops); + return (LT_ERROR); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + return (lt); +} + +/* + * Table-driven evaluation of binary operators. + */ +static Linetype +eval_table(const struct ops *ops, int *valp, const char **cpp) +{ + const struct op *op; + const char *cp; + int val; + Linetype lt, rt; + + debug("eval%d", ops - eval_ops); + cp = *cpp; + lt = ops->inner(ops+1, valp, &cp); + if (lt == LT_ERROR) + return (LT_ERROR); + for (;;) { + cp = skipcomment(cp); + for (op = ops->op; op->str != NULL; op++) + if (strncmp(cp, op->str, strlen(op->str)) == 0) + break; + if (op->str == NULL) + break; + cp += strlen(op->str); + debug("eval%d %s", ops - eval_ops, op->str); + rt = ops->inner(ops+1, &val, &cp); + if (rt == LT_ERROR) + return (LT_ERROR); + lt = op->fn(valp, lt, *valp, rt, val); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + debug("eval%d lt = %s", ops - eval_ops, linetype_name[lt]); + return (lt); +} + +/* + * Evaluate the expression on a #if or #elif line. If we can work out + * the result we return LT_TRUE or LT_FALSE accordingly, otherwise we + * return just a generic LT_IF. + */ +static Linetype +ifeval(const char **cpp) +{ + int ret; + int val = 0; + + debug("eval %s", *cpp); + constexpr = killconsts ? false : true; + ret = eval_table(eval_ops, &val, cpp); + debug("eval = %d", val); + return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret); +} + +/* + * Skip over comments, strings, and character literals and stop at the + * next character position that is not whitespace. Between calls we keep + * the comment state in the global variable incomment, and we also adjust + * the global variable linestate when we see a newline. + * XXX: doesn't cope with the buffer splitting inside a state transition. + */ +static const char * +skipcomment(const char *cp) +{ + if (text || ignoring[depth]) { + for (; isspace((unsigned char)*cp); cp++) + if (*cp == '\n') + linestate = LS_START; + return (cp); + } + while (*cp != '\0') + /* don't reset to LS_START after a line continuation */ + if (strncmp(cp, "\\\r\n", 3) == 0) + cp += 3; + else if (strncmp(cp, "\\\n", 2) == 0) + cp += 2; + else switch (incomment) { + case NO_COMMENT: + if (strncmp(cp, "/\\\r\n", 4) == 0) { + incomment = STARTING_COMMENT; + cp += 4; + } else if (strncmp(cp, "/\\\n", 3) == 0) { + incomment = STARTING_COMMENT; + cp += 3; + } else if (strncmp(cp, "/*", 2) == 0) { + incomment = C_COMMENT; + cp += 2; + } else if (strncmp(cp, "//", 2) == 0) { + incomment = CXX_COMMENT; + cp += 2; + } else if (strncmp(cp, "\'", 1) == 0) { + incomment = CHAR_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\"", 1) == 0) { + incomment = STRING_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\n", 1) == 0) { + linestate = LS_START; + cp += 1; + } else if (strchr(" \r\t", *cp) != NULL) { + cp += 1; + } else + return (cp); + continue; + case CXX_COMMENT: + if (strncmp(cp, "\n", 1) == 0) { + incomment = NO_COMMENT; + linestate = LS_START; + } + cp += 1; + continue; + case CHAR_LITERAL: + case STRING_LITERAL: + if ((incomment == CHAR_LITERAL && cp[0] == '\'') || + (incomment == STRING_LITERAL && cp[0] == '\"')) { + incomment = NO_COMMENT; + cp += 1; + } else if (cp[0] == '\\') { + if (cp[1] == '\0') + cp += 1; + else + cp += 2; + } else if (strncmp(cp, "\n", 1) == 0) { + if (incomment == CHAR_LITERAL) + error("unterminated char literal"); + else + error("unterminated string literal"); + } else + cp += 1; + continue; + case C_COMMENT: + if (strncmp(cp, "*\\\r\n", 4) == 0) { + incomment = FINISHING_COMMENT; + cp += 4; + } else if (strncmp(cp, "*\\\n", 3) == 0) { + incomment = FINISHING_COMMENT; + cp += 3; + } else if (strncmp(cp, "*/", 2) == 0) { + incomment = NO_COMMENT; + cp += 2; + } else + cp += 1; + continue; + case STARTING_COMMENT: + if (*cp == '*') { + incomment = C_COMMENT; + cp += 1; + } else if (*cp == '/') { + incomment = CXX_COMMENT; + cp += 1; + } else { + incomment = NO_COMMENT; + linestate = LS_DIRTY; + } + continue; + case FINISHING_COMMENT: + if (*cp == '/') { + incomment = NO_COMMENT; + cp += 1; + } else + incomment = C_COMMENT; + continue; + default: + abort(); /* bug */ + } + return (cp); +} + +/* + * Skip macro arguments. + */ +static const char * +skipargs(const char *cp) +{ + const char *ocp = cp; + int level = 0; + cp = skipcomment(cp); + if (*cp != '(') + return (cp); + do { + if (*cp == '(') + level++; + if (*cp == ')') + level--; + cp = skipcomment(cp+1); + } while (level != 0 && *cp != '\0'); + if (level == 0) + return (cp); + else + /* Rewind and re-detect the syntax error later. */ + return (ocp); +} + +/* + * Skip over an identifier. + */ +static const char * +skipsym(const char *cp) +{ + while (!endsym(*cp)) + ++cp; + return (cp); +} + +/* + * Look for the symbol in the symbol table. If it is found, we return + * the symbol table index, else we return -1. + */ +static int +findsym(const char *str) +{ + const char *cp; + int symind; + + cp = skipsym(str); + if (cp == str) + return (-1); + if (symlist) { + if (symdepth && firstsym) + printf("%s%3d", zerosyms ? "" : "\n", depth); + firstsym = zerosyms = false; + printf("%s%.*s%s", + symdepth ? " " : "", + (int)(cp-str), str, + symdepth ? "" : "\n"); + /* we don't care about the value of the symbol */ + return (0); + } + for (symind = 0; symind < nsyms; ++symind) { + if (strlcmp(symname[symind], str, cp-str) == 0) { + debug("findsym %s %s", symname[symind], + value[symind] ? value[symind] : ""); + return (symind); + } + } + return (-1); +} + +/* + * Add a symbol to the symbol table. + */ +static void +addsym(bool ignorethis, bool definethis, char *sym) +{ + int symind; + char *val; + + symind = findsym(sym); + if (symind < 0) { + if (nsyms >= MAXSYMS) + errx(2, "too many symbols"); + symind = nsyms++; + } + symname[symind] = sym; + ignore[symind] = ignorethis; + val = sym + (skipsym(sym) - sym); + if (definethis) { + if (*val == '=') { + value[symind] = val+1; + *val = '\0'; + } else if (*val == '\0') + value[symind] = "1"; + else + usage(); + } else { + if (*val != '\0') + usage(); + value[symind] = NULL; + } + debug("addsym %s=%s", symname[symind], + value[symind] ? value[symind] : "undef"); +} + +/* + * Compare s with n characters of t. + * The same as strncmp() except that it checks that s[n] == '\0'. + */ +static int +strlcmp(const char *s, const char *t, size_t n) +{ + while (n-- && *t != '\0') + if (*s != *t) + return ((unsigned char)*s - (unsigned char)*t); + else + ++s, ++t; + return ((unsigned char)*s); +} + +/* + * Diagnostics. + */ +static void +debug(const char *msg, ...) +{ + va_list ap; + + if (debugging) { + va_start(ap, msg); + vwarnx(msg, ap); + va_end(ap); + } +} + +static void +error(const char *msg) +{ + if (depth == 0) + warnx("%s: %d: %s", filename, linenum, msg); + else + warnx("%s: %d: %s (#if line %d depth %d)", + filename, linenum, msg, stifline[depth], depth); + closeout(); + errx(2, "output may be truncated"); +} diff --git a/developer_cmds/unifdef/unifdefall.sh b/developer_cmds/unifdef/unifdefall.sh new file mode 100644 index 0000000..6d6165a --- /dev/null +++ b/developer_cmds/unifdef/unifdefall.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# unifdefall: remove all the #if's from a source file +# +# Copyright (c) 2002 - 2010 Tony Finch +# Copyright (c) 2009 - 2010 Jonathan Nieder +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD: src/usr.bin/unifdef/unifdefall.sh,v 1.7 2010/03/12 17:55:29 fanf Exp $ + +set -e + +unifdef="$(dirname "$0")/unifdef" +if [ ! -e "$unifdef" ] +then + unifdef=unifdef +fi + +case "$@" in +"-d "*) echo DEBUGGING 1>&2 + debug=-d + shift +esac + +basename=$(basename "$0") +tmp=$(mktemp -d "${TMPDIR:-/tmp}/$basename.XXXXXXXXXX") || exit 2 +trap 'rm -r "$tmp" || exit 2' EXIT + +export LC_ALL=C + +# list of all controlling macros +"$unifdef" $debug -s "$@" | sort | uniq >"$tmp/ctrl" +# list of all macro definitions +cpp -dM "$@" | sort | sed 's/^#define //' >"$tmp/hashdefs" +# list of defined macro names +sed 's/[^A-Za-z0-9_].*$//' <"$tmp/hashdefs" >"$tmp/alldef" +# list of undefined and defined controlling macros +comm -23 "$tmp/ctrl" "$tmp/alldef" >"$tmp/undef" +comm -12 "$tmp/ctrl" "$tmp/alldef" >"$tmp/def" +# create a sed script that extracts the controlling macro definitions +# and converts them to unifdef command-line arguments +sed 's|.*|s/^&\\(([^)]*)\\)\\{0,1\\} /-D&=/p|' <"$tmp/def" >"$tmp/script" +# create the final unifdef command +{ echo "$unifdef" $debug -k '\' + # convert the controlling undefined macros to -U arguments + sed 's/.*/-U& \\/' <"$tmp/undef" + # convert the controlling defined macros to quoted -D arguments + sed -nf "$tmp/script" <"$tmp/hashdefs" | + sed "s/'/'\\\\''/g;s/.*/'&' \\\\/" + echo '"$@"' +} >"$tmp/cmd" +case $debug in +-d) for i in ctrl hashdefs alldef undef def script cmd + do echo ==== $i + cat "$tmp/$i" + done 1>&2 +esac +# run the command we just created +sh "$tmp/cmd" "$@" diff --git a/developer_cmds/xcodescripts/install-lorder.sh b/developer_cmds/xcodescripts/install-lorder.sh new file mode 100644 index 0000000..8da52b7 --- /dev/null +++ b/developer_cmds/xcodescripts/install-lorder.sh @@ -0,0 +1,7 @@ +set -ex + +BINDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/bin + +install -c -o root -g wheel -m 0755 \ + "$PROJECT_DIR"/lorder/lorder.sh \ + "$BINDIR"/lorder diff --git a/developer_cmds/xcodescripts/install-unifdefall.sh b/developer_cmds/xcodescripts/install-unifdefall.sh new file mode 100644 index 0000000..7424b3f --- /dev/null +++ b/developer_cmds/xcodescripts/install-unifdefall.sh @@ -0,0 +1,9 @@ +set -e -x + +BINDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/bin +MANDIR="$DSTROOT"/"$DT_TOOLCHAIN_DIR"/usr/share/man/man1 + +ln -f "$MANDIR"/unifdef.1 "$MANDIR"/unifdefall.1 +install -c -o root -g wheel -m 0755 \ + "$PROJECT_DIR"/unifdef/unifdefall.sh \ + "$BINDIR"/unifdefall diff --git a/diskdev_cmds/APPLE_LICENSE b/diskdev_cmds/APPLE_LICENSE new file mode 100644 index 0000000..fe81a60 --- /dev/null +++ b/diskdev_cmds/APPLE_LICENSE @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License." diff --git a/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 new file mode 100644 index 0000000..9369b2b --- /dev/null +++ b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 @@ -0,0 +1,81 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. 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. +.\" +.\" @(#)dev_mkdb.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Os +.Dt DEV_MKDB 8 +.Sh NAME +.Nm dev_mkdb +.Nd create +.Pa /dev +database +.Sh SYNOPSIS +.Nm dev_mkdb +.Sh DESCRIPTION +The +.Nm dev_mkdb +command creates a +.Xr db 3 +hash access method database in +.Dq Pa /var/run/dev.db +which contains the names of all of the character and block special +files in the +.Dq Pa /dev +directory, using the file type and the +.Fa st_rdev +field as the key. +.Pp +Keys are a structure containing a mode_t followed by a dev_t, +with any padding zero'd out. +The former is the type of the file (st_mode & S_IFMT), +the latter is the st_rdev field. +.Sh FILES +.Bl -tag -width /var/run/dev.db -compact +.It Pa /dev +Device directory. +.It Pa /var/run/dev.db +Database file. +.El +.Sh SEE ALSO +.Xr ps 1 , +.Xr stat 2 , +.Xr db 3 , +.Xr devname 3 , +.Xr kvm_nlist 3 , +.Xr ttyname 3 , +.Xr kvm_mkdb 8 +.Sh HISTORY +The +.Nm dev_mkdb +command appeared in +.Bx 4.4 . diff --git a/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c new file mode 100644 index 0000000..82c7429 --- /dev/null +++ b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + */ + +/****** +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +******/ + +/****** +static char sccsid[] = "@(#)dev_mkdb.c 8.1 (Berkeley) 6/6/93"; +******/ + +#include +#include + +#include +#undef DIRBLKSIZ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void err __P((const char *, ...)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register DIR *dirp; + register struct dirent *dp; + struct stat sb; + struct { + mode_t type; + dev_t dev; + } bkey; + DB *db; + DBT data, key; + int ch; + u_char buf[MAXNAMLEN + 1]; + char dbtmp[MAXPATHLEN + 1], dbname[MAXPATHLEN + 1]; + + while ((ch = getopt(argc, argv, "")) != EOF) + switch((char)ch) { + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc > 0) + usage(); + + if (chdir(_PATH_DEV)) + err("%s: %s", _PATH_DEV, strerror(errno)); + + dirp = opendir("."); + + (void)snprintf(dbtmp, sizeof(dbtmp), "%sdev.tmp", _PATH_VARRUN); + (void)snprintf(dbname, sizeof(dbtmp), "%sdev.db", _PATH_VARRUN); + db = dbopen(dbtmp, O_CREAT|O_EXLOCK|O_RDWR|O_TRUNC, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, DB_HASH, NULL); + if (db == NULL) + err("%s: %s", dbtmp, strerror(errno)); + + /* + * Keys are a mode_t followed by a dev_t. The former is the type of + * the file (mode & S_IFMT), the latter is the st_rdev field. Note + * that the structure may contain padding, so we have to clear it + * out here. + */ + bzero(&bkey, sizeof(bkey)); + key.data = &bkey; + key.size = sizeof(bkey); + data.data = buf; + while ((dp = readdir(dirp))) { + if (lstat(dp->d_name, &sb)) { + (void)fprintf(stderr, + "dev_mkdb: %s: %s\n", dp->d_name, strerror(errno)); + continue; + } + + /* Create the key. */ + if (S_ISCHR(sb.st_mode)) + bkey.type = S_IFCHR; + else if (S_ISBLK(sb.st_mode)) + bkey.type = S_IFBLK; + else + continue; + bkey.dev = sb.st_rdev; + + /* + * Create the data; nul terminate the name so caller doesn't + * have to. + */ + bcopy(dp->d_name, buf, dp->d_namlen); + buf[dp->d_namlen] = '\0'; + data.size = dp->d_namlen + 1; + if ((db->put)(db, &key, &data, 0)) + err("dbput %s: %s\n", dbtmp, strerror(errno)); + } + (void)(db->close)(db); + if (rename(dbtmp, dbname)) + err("rename %s to %s: %s", dbtmp, dbname, strerror(errno)); + exit(0); +} + +void +usage() +{ + (void)fprintf(stderr, "usage: dev_mkdb\n"); + exit(1); +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "dev_mkdb: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj b/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ff896ee --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj @@ -0,0 +1,2411 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 4D55934F153CE4CC009F2584 /* Common */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4D559350153CE4CC009F2584 /* Build configuration list for PBXAggregateTarget "Common" */; + buildPhases = ( + ); + dependencies = ( + 4D559357153CE4EA009F2584 /* PBXTargetDependency */, + 4D559472153DC87B009F2584 /* PBXTargetDependency */, + 4D559359153CE4EC009F2584 /* PBXTargetDependency */, + 4D55935B153CE4ED009F2584 /* PBXTargetDependency */, + 4D559498153DC9E8009F2584 /* PBXTargetDependency */, + 4D5594A7153DCA04009F2584 /* PBXTargetDependency */, + 4D5594B9153DCA5E009F2584 /* PBXTargetDependency */, + 4D5594DF153DCC73009F2584 /* PBXTargetDependency */, + 4D559373153CE5F8009F2584 /* PBXTargetDependency */, + 4D559426153DC38F009F2584 /* PBXTargetDependency */, + 4D55943A153DC4C0009F2584 /* PBXTargetDependency */, + 4D55939C153CE83A009F2584 /* PBXTargetDependency */, + 4D559415153DC282009F2584 /* PBXTargetDependency */, + 071077D92488A09C003B97C7 /* PBXTargetDependency */, + ); + name = Common; + productName = All; + }; + 4D559440153DC57D009F2584 /* All_MacOSX */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4D559441153DC57D009F2584 /* Build configuration list for PBXAggregateTarget "All_MacOSX" */; + buildPhases = ( + ); + dependencies = ( + 4D559447153DC597009F2584 /* PBXTargetDependency */, + B12C9C9222A7CDE300B9F497 /* PBXTargetDependency */, + B12C9C9422A7CDE300B9F497 /* PBXTargetDependency */, + B12C9C9622A7CDE300B9F497 /* PBXTargetDependency */, + B12C9C9822A7CDE300B9F497 /* PBXTargetDependency */, + B12C9C9A22A7CDE300B9F497 /* PBXTargetDependency */, + B12C9C9C22A7CDE300B9F497 /* PBXTargetDependency */, + 07747AA21DA8511D00ACE020 /* PBXTargetDependency */, + 4D55945C153DC665009F2584 /* PBXTargetDependency */, + ); + name = All_MacOSX; + productName = All_MacOSX; + }; + 4D559443153DC587009F2584 /* All_iOS */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4D559444153DC587009F2584 /* Build configuration list for PBXAggregateTarget "All_iOS" */; + buildPhases = ( + ); + dependencies = ( + 4D559449153DC599009F2584 /* PBXTargetDependency */, + ); + name = All_iOS; + productName = All_iOS; + }; + 4D559514153DE116009F2584 /* quotaoff */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4D559515153DE116009F2584 /* Build configuration list for PBXAggregateTarget "quotaoff" */; + buildPhases = ( + 4D55951B153DE1EF009F2584 /* ShellScript */, + ); + dependencies = ( + 4D55951A153DE1CB009F2584 /* PBXTargetDependency */, + ); + name = quotaoff; + productName = quotaoff; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 072AAAA62167CE8F004ED4E2 /* mount_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 072AAAA42167CE8E004ED4E2 /* mount_flags.c */; }; + 078B970D2190682600674625 /* mount_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 072AAAA42167CE8E004ED4E2 /* mount_flags.c */; }; + 07CE4C1821906BB800BF11C0 /* mount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55936C153CE58E009F2584 /* mount.c */; }; + 1A9041022091EE830061D05A /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; }; + 1A9041042091EE910061D05A /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; }; + 1A9041062091EE980061D05A /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; }; + 4D07DD57153CA9DC002B57CB /* dkcksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4D153CA9DC002B57CB /* dkcksum.c */; }; + 4D07DD58153CA9DC002B57CB /* dkdisklabel.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */; }; + 4D07DD59153CA9DC002B57CB /* dkopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4F153CA9DC002B57CB /* dkopen.c */; }; + 4D07DD5A153CA9DC002B57CB /* dkopen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D07DD50153CA9DC002B57CB /* dkopen.h */; }; + 4D07DD5B153CA9DC002B57CB /* dksecsize.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD51153CA9DC002B57CB /* dksecsize.c */; }; + 4D07DD5E153CA9DC002B57CB /* pathnames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D07DD54153CA9DC002B57CB /* pathnames.h */; }; + 4D07DD5F153CA9DC002B57CB /* preen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD55153CA9DC002B57CB /* preen.c */; }; + 4D07DD60153CA9DC002B57CB /* vfslist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD56153CA9DC002B57CB /* vfslist.c */; }; + 4D559332153CE1D9009F2584 /* auto.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55931E153CE1D9009F2584 /* auto.c */; }; + 4D559333153CE1D9009F2584 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559320153CE1D9009F2584 /* cmd.c */; }; + 4D559334153CE1D9009F2584 /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559322153CE1D9009F2584 /* disk.c */; }; + 4D559335153CE1D9009F2584 /* fdisk.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559325153CE1D9009F2584 /* fdisk.c */; }; + 4D559336153CE1D9009F2584 /* getrawpartition.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559326153CE1D9009F2584 /* getrawpartition.c */; }; + 4D559337153CE1D9009F2584 /* mbr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559327153CE1D9009F2584 /* mbr.c */; }; + 4D559338153CE1D9009F2584 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932A153CE1D9009F2584 /* misc.c */; }; + 4D559339153CE1D9009F2584 /* opendev.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932C153CE1D9009F2584 /* opendev.c */; }; + 4D55933A153CE1D9009F2584 /* part.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932D153CE1D9009F2584 /* part.c */; }; + 4D55933B153CE1D9009F2584 /* user.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932F153CE1D9009F2584 /* user.c */; }; + 4D55933C153CE242009F2584 /* fdisk.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559324153CE1D9009F2584 /* fdisk.8 */; }; + 4D55934D153CE44E009F2584 /* fsck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55934B153CE44E009F2584 /* fsck.c */; }; + 4D55934E153CE4B1009F2584 /* fsck.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55934A153CE44E009F2584 /* fsck.8 */; }; + 4D55936F153CE5D6009F2584 /* fstab.5 in Copy man5 */ = {isa = PBXBuildFile; fileRef = 4D559369153CE58E009F2584 /* fstab.5 */; }; + 4D559371153CE5EA009F2584 /* mount.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55936B153CE58E009F2584 /* mount.8 */; }; + 4D559389153CE794009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; }; + 4D559399153CE826009F2584 /* umount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559398153CE826009F2584 /* umount.c */; }; + 4D55939A153CE82E009F2584 /* umount.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559397153CE826009F2584 /* umount.8 */; }; + 4D55939D153CE8AF009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; }; + 4D5593B2153CEABD009F2584 /* edquota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593B0153CEABD009F2584 /* edquota.c */; }; + 4D5593C4153CEB9A009F2584 /* quota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593C3153CEB9A009F2584 /* quota.c */; }; + 4D5593C5153CEBB4009F2584 /* edquota.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593AF153CEABD009F2584 /* edquota.8 */; }; + 4D5593C6153CEBC3009F2584 /* quota.1 in Copy man1 */ = {isa = PBXBuildFile; fileRef = 4D5593C2153CEB9A009F2584 /* quota.1 */; }; + 4D5593DC153CED51009F2584 /* hfs_quotacheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */; }; + 4D5593DD153CED51009F2584 /* quotacheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593DA153CED51009F2584 /* quotacheck.c */; }; + 4D5593DE153CED6A009F2584 /* quotacheck.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593D9153CED51009F2584 /* quotacheck.8 */; }; + 4D5593DF153CED8D009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; }; + 4D5593EF153CEE66009F2584 /* quotaon.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593EE153CEE66009F2584 /* quotaon.c */; }; + 4D5593F0153CEE74009F2584 /* quotaon.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593ED153CEE66009F2584 /* quotaon.8 */; }; + 4D559403153DC13D009F2584 /* repquota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559402153DC13D009F2584 /* repquota.c */; }; + 4D559404153DC150009F2584 /* repquota.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559401153DC13D009F2584 /* repquota.8 */; }; + 4D559417153DC2AB009F2584 /* vndevice.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559416153DC2AB009F2584 /* vndevice.c */; }; + 4D559428153DC3A6009F2584 /* mount_devfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559427153DC3A6009F2584 /* mount_devfs.c */; }; + 4D55942B153DC427009F2584 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D55942A153DC420009F2584 /* libutil.dylib */; }; + 4D55943D153DC4DE009F2584 /* mount_fdesc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55943C153DC4DE009F2584 /* mount_fdesc.c */; }; + 4D55943E153DC4E9009F2584 /* mount_fdesc.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */; }; + 4D55943F153DC534009F2584 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D55942A153DC420009F2584 /* libutil.dylib */; }; + 4D55945A153DC650009F2584 /* vsdbutil_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559458153DC650009F2584 /* vsdbutil_main.c */; }; + 4D55945D153DC728009F2584 /* vsdbutil.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559459153DC650009F2584 /* vsdbutil.8 */; }; + 4D55945F153DC735009F2584 /* com.apple.vsdbutil.plist in Copy com.apple.vsdbutil.plist */ = {isa = PBXBuildFile; fileRef = 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */; }; + 4D55946F153DC839009F2584 /* dev_mkdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55946E153DC839009F2584 /* dev_mkdb.c */; }; + 4D559470153DC84E009F2584 /* dev_mkdb.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55946D153DC839009F2584 /* dev_mkdb.8 */; }; + 4D559482153DC912009F2584 /* fstyp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559481153DC912009F2584 /* fstyp.c */; }; + 4D559483153DC92D009F2584 /* fstyp.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559480153DC912009F2584 /* fstyp.8 */; }; + 4D559495153DC9AE009F2584 /* fstyp_msdos.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559494153DC9AE009F2584 /* fstyp_msdos.c */; }; + 4D559496153DC9BC009F2584 /* fstyp_msdos.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */; }; + 4D5594AA153DCA19009F2584 /* fstyp_ntfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */; }; + 4D5594BC153DCA74009F2584 /* fstyp_udf.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594BB153DCA74009F2584 /* fstyp_udf.c */; }; + 4D5594BD153DCA85009F2584 /* fstyp_udf.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */; }; + 4D5594CD153DCB72009F2584 /* setclass.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594CC153DCB72009F2584 /* setclass.c */; }; + 4D5594CE153DCB82009F2584 /* setclass.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594CB153DCB72009F2584 /* setclass.8 */; }; + 4D5594E2153DCCAC009F2584 /* fuser.1 in Copy man1 */ = {isa = PBXBuildFile; fileRef = 4D5594E0153DCC92009F2584 /* fuser.1 */; }; + 4D5594E6153DCFFB009F2584 /* fstyp_ntfs.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */; }; + 785314FF227120BD00B25661 /* MediaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 785314FE227120BD00B25661 /* MediaKit.framework */; }; + B19B239C21C8DF660001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; }; + B19B239D21C8DF6E0001F35C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; }; + B19B239E21C8DF740001F35C /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; }; + B19B239F21C8DF7B0001F35C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; }; + B19B23A021C8DFA40001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; }; + B19B23A221C8DFC30001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; }; + B19B23A321C8DFCF0001F35C /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; }; + B19B23A421C8DFD50001F35C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; }; + B19B23A521C8DFE10001F35C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 071077D82488A09C003B97C7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5594C1153DCAFC009F2584; + remoteInfo = setclass; + }; + 07747AA11DA8511D00ACE020 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559476153DC8FC009F2584; + remoteInfo = fstyp; + }; + 4D559356153CE4EA009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D07DD48153CA9A0002B57CB; + remoteInfo = libdisk; + }; + 4D559358153CE4EC009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559314153CE198009F2584; + remoteInfo = fdisk; + }; + 4D55935A153CE4ED009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559340153CE41E009F2584; + remoteInfo = fsck; + }; + 4D559372153CE5F8009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55935F153CE561009F2584; + remoteInfo = mount; + }; + 4D55939B153CE83A009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55938D153CE7FD009F2584; + remoteInfo = umount; + }; + 4D55939E153CE8B6009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D07DD48153CA9A0002B57CB; + remoteInfo = libdisk; + }; + 4D5593A0153CE8BC009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D07DD48153CA9A0002B57CB; + remoteInfo = libdisk; + }; + 4D559414153DC282009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55940A153DC27A009F2584; + remoteInfo = vndevice; + }; + 4D559425153DC38F009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55941B153DC383009F2584; + remoteInfo = mount_devfs; + }; + 4D559439153DC4C0009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55942F153DC49A009F2584; + remoteInfo = mount_fdesc; + }; + 4D559446153DC597009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55934F153CE4CC009F2584; + remoteInfo = Common; + }; + 4D559448153DC599009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55934F153CE4CC009F2584; + remoteInfo = Common; + }; + 4D55945B153DC665009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55944D153DC634009F2584; + remoteInfo = vsdbutil; + }; + 4D559471153DC87B009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559463153DC808009F2584; + remoteInfo = dev_mkdb; + }; + 4D559497153DC9E8009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559489153DC98D009F2584; + remoteInfo = fstyp_msdos; + }; + 4D5594A6153DCA04009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D55949C153DC9FB009F2584; + remoteInfo = fstyp_ntfs; + }; + 4D5594B8153DCA5E009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5594AE153DCA53009F2584; + remoteInfo = fstyp_udf; + }; + 4D5594DE153DCC73009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5594D4153DCC66009F2584; + remoteInfo = fuser; + }; + 4D559519153DE1CB009F2584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593E3153CEE4A009F2584; + remoteInfo = quotaon; + }; + B12C9C9122A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593A5153CEA90009F2584; + remoteInfo = edquota; + }; + B12C9C9322A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593B8153CEB7E009F2584; + remoteInfo = quota; + }; + B12C9C9522A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593CC153CED29009F2584; + remoteInfo = quotacheck; + }; + B12C9C9722A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593E3153CEE4A009F2584; + remoteInfo = quotaon; + }; + B12C9C9922A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D559514153DE116009F2584; + remoteInfo = quotaoff; + }; + B12C9C9B22A7CDE300B9F497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4D07DD2B153CA616002B57CB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D5593F7153DC0DE009F2584; + remoteInfo = repquota; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4D559313153CE198009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D55933C153CE242009F2584 /* fdisk.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55933F153CE41E009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D55934E153CE4B1009F2584 /* fsck.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55935E153CE561009F2584 /* Copy man5 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man5/; + dstSubfolderSpec = 0; + files = ( + 4D55936F153CE5D6009F2584 /* fstab.5 in Copy man5 */, + ); + name = "Copy man5"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D559370153CE5DC009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D559371153CE5EA009F2584 /* mount.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55938C153CE7FD009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D55939A153CE82E009F2584 /* umount.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5593A4153CEA90009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5593C5153CEBB4009F2584 /* edquota.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5593B7153CEB7E009F2584 /* Copy man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4D5593C6153CEBC3009F2584 /* quota.1 in Copy man1 */, + ); + name = "Copy man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5593CB153CED29009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5593DE153CED6A009F2584 /* quotacheck.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5593E2153CEE4A009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5593F0153CEE74009F2584 /* quotaon.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5593F6153DC0DE009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D559404153DC150009F2584 /* repquota.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D559409153DC27A009F2584 /* Copy man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + name = "Copy man1"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55941A153DC383009F2584 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55942E153DC49A009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D55943E153DC4E9009F2584 /* mount_fdesc.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55944C153DC634009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D55945D153DC728009F2584 /* vsdbutil.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55945E153DC730009F2584 /* Copy com.apple.vsdbutil.plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + 4D55945F153DC735009F2584 /* com.apple.vsdbutil.plist in Copy com.apple.vsdbutil.plist */, + ); + name = "Copy com.apple.vsdbutil.plist"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D559462153DC808009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D559470153DC84E009F2584 /* dev_mkdb.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D559475153DC8FC009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D559483153DC92D009F2584 /* fstyp.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D559488153DC98D009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D559496153DC9BC009F2584 /* fstyp_msdos.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D55949B153DC9FB009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5594E6153DCFFB009F2584 /* fstyp_ntfs.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5594AD153DCA53009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5594BD153DCA85009F2584 /* fstyp_udf.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5594C0153DCAFC009F2584 /* Copy man8 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/local/share/man/man8/; + dstSubfolderSpec = 0; + files = ( + 4D5594CE153DCB82009F2584 /* setclass.8 in Copy man8 */, + ); + name = "Copy man8"; + runOnlyForDeploymentPostprocessing = 1; + }; + 4D5594D3153DCC66009F2584 /* Copy man1 */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4D5594E2153DCCAC009F2584 /* fuser.1 in Copy man1 */, + ); + name = "Copy man1"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 072AAAA42167CE8E004ED4E2 /* mount_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mount_flags.c; sourceTree = ""; }; + 072AAAA52167CE8E004ED4E2 /* mount_flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mount_flags.h; sourceTree = ""; }; + 07AF95B12323281D001E9266 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = System/Library/Frameworks/System.framework; sourceTree = SDKROOT; }; + 07AF95B323232837001E9266 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; + 1A9041012091EE830061D05A /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 1A9041032091EE910061D05A /* APFS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = APFS.framework; path = System/Library/PrivateFrameworks/APFS.framework; sourceTree = SDKROOT; }; + 1A9041052091EE980061D05A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 4D07DD49153CA9A0002B57CB /* libdisk.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdisk.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D07DD4D153CA9DC002B57CB /* dkcksum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkcksum.c; path = disklib/dkcksum.c; sourceTree = ""; }; + 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkdisklabel.c; path = disklib/dkdisklabel.c; sourceTree = ""; }; + 4D07DD4F153CA9DC002B57CB /* dkopen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkopen.c; path = disklib/dkopen.c; sourceTree = ""; }; + 4D07DD50153CA9DC002B57CB /* dkopen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dkopen.h; path = disklib/dkopen.h; sourceTree = ""; }; + 4D07DD51153CA9DC002B57CB /* dksecsize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dksecsize.c; path = disklib/dksecsize.c; sourceTree = ""; }; + 4D07DD54153CA9DC002B57CB /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = disklib/pathnames.h; sourceTree = ""; }; + 4D07DD55153CA9DC002B57CB /* preen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preen.c; path = disklib/preen.c; sourceTree = ""; }; + 4D07DD56153CA9DC002B57CB /* vfslist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vfslist.c; path = disklib/vfslist.c; sourceTree = ""; }; + 4D559315153CE198009F2584 /* fdisk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fdisk; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D55931E153CE1D9009F2584 /* auto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = auto.c; path = fdisk.tproj/auto.c; sourceTree = SOURCE_ROOT; }; + 4D55931F153CE1D9009F2584 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = auto.h; path = fdisk.tproj/auto.h; sourceTree = SOURCE_ROOT; }; + 4D559320153CE1D9009F2584 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cmd.c; path = fdisk.tproj/cmd.c; sourceTree = SOURCE_ROOT; }; + 4D559321153CE1D9009F2584 /* cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmd.h; path = fdisk.tproj/cmd.h; sourceTree = SOURCE_ROOT; }; + 4D559322153CE1D9009F2584 /* disk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = disk.c; path = fdisk.tproj/disk.c; sourceTree = SOURCE_ROOT; }; + 4D559323153CE1D9009F2584 /* disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = disk.h; path = fdisk.tproj/disk.h; sourceTree = SOURCE_ROOT; }; + 4D559324153CE1D9009F2584 /* fdisk.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fdisk.8; path = fdisk.tproj/fdisk.8; sourceTree = SOURCE_ROOT; }; + 4D559325153CE1D9009F2584 /* fdisk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fdisk.c; path = fdisk.tproj/fdisk.c; sourceTree = SOURCE_ROOT; }; + 4D559326153CE1D9009F2584 /* getrawpartition.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = getrawpartition.c; path = fdisk.tproj/getrawpartition.c; sourceTree = SOURCE_ROOT; }; + 4D559327153CE1D9009F2584 /* mbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mbr.c; path = fdisk.tproj/mbr.c; sourceTree = SOURCE_ROOT; }; + 4D559328153CE1D9009F2584 /* mbr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mbr.h; path = fdisk.tproj/mbr.h; sourceTree = SOURCE_ROOT; }; + 4D559329153CE1D9009F2584 /* mbrcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mbrcode.h; path = fdisk.tproj/mbrcode.h; sourceTree = SOURCE_ROOT; }; + 4D55932A153CE1D9009F2584 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = misc.c; path = fdisk.tproj/misc.c; sourceTree = SOURCE_ROOT; }; + 4D55932B153CE1D9009F2584 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = misc.h; path = fdisk.tproj/misc.h; sourceTree = SOURCE_ROOT; }; + 4D55932C153CE1D9009F2584 /* opendev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = opendev.c; path = fdisk.tproj/opendev.c; sourceTree = SOURCE_ROOT; }; + 4D55932D153CE1D9009F2584 /* part.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = part.c; path = fdisk.tproj/part.c; sourceTree = SOURCE_ROOT; }; + 4D55932E153CE1D9009F2584 /* part.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = part.h; path = fdisk.tproj/part.h; sourceTree = SOURCE_ROOT; }; + 4D55932F153CE1D9009F2584 /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = user.c; path = fdisk.tproj/user.c; sourceTree = SOURCE_ROOT; }; + 4D559330153CE1D9009F2584 /* user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = user.h; path = fdisk.tproj/user.h; sourceTree = SOURCE_ROOT; }; + 4D559331153CE1D9009F2584 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = fdisk.tproj/util.h; sourceTree = SOURCE_ROOT; }; + 4D559341153CE41E009F2584 /* fsck */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fsck; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D55934A153CE44E009F2584 /* fsck.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fsck.8; path = fsck.tproj/fsck.8; sourceTree = SOURCE_ROOT; }; + 4D55934B153CE44E009F2584 /* fsck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fsck.c; path = fsck.tproj/fsck.c; sourceTree = SOURCE_ROOT; }; + 4D55934C153CE44E009F2584 /* fsck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fsck.h; path = fsck.tproj/fsck.h; sourceTree = SOURCE_ROOT; }; + 4D559360153CE561009F2584 /* mount */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559369153CE58E009F2584 /* fstab.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstab.5; path = mount.tproj/fstab.5; sourceTree = SOURCE_ROOT; }; + 4D55936B153CE58E009F2584 /* mount.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mount.8; path = mount.tproj/mount.8; sourceTree = SOURCE_ROOT; }; + 4D55936C153CE58E009F2584 /* mount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount.c; path = mount.tproj/mount.c; sourceTree = SOURCE_ROOT; }; + 4D55936D153CE58E009F2584 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = mount.tproj/pathnames.h; sourceTree = SOURCE_ROOT; }; + 4D55938E153CE7FD009F2584 /* umount */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = umount; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559397153CE826009F2584 /* umount.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = umount.8; path = umount.tproj/umount.8; sourceTree = SOURCE_ROOT; }; + 4D559398153CE826009F2584 /* umount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = umount.c; path = umount.tproj/umount.c; sourceTree = SOURCE_ROOT; }; + 4D5593A6153CEA90009F2584 /* edquota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = edquota; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5593AF153CEABD009F2584 /* edquota.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = edquota.8; path = edquota.tproj/edquota.8; sourceTree = SOURCE_ROOT; }; + 4D5593B0153CEABD009F2584 /* edquota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = edquota.c; path = edquota.tproj/edquota.c; sourceTree = SOURCE_ROOT; }; + 4D5593B1153CEABD009F2584 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = edquota.tproj/pathnames.h; sourceTree = SOURCE_ROOT; }; + 4D5593B9153CEB7E009F2584 /* quota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quota; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5593C2153CEB9A009F2584 /* quota.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = quota.1; path = quota.tproj/quota.1; sourceTree = SOURCE_ROOT; }; + 4D5593C3153CEB9A009F2584 /* quota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quota.c; path = quota.tproj/quota.c; sourceTree = SOURCE_ROOT; }; + 4D5593CD153CED29009F2584 /* quotacheck */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quotacheck; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hfs_quotacheck.c; path = quotacheck.tproj/hfs_quotacheck.c; sourceTree = SOURCE_ROOT; }; + 4D5593D9153CED51009F2584 /* quotacheck.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = quotacheck.8; path = quotacheck.tproj/quotacheck.8; sourceTree = SOURCE_ROOT; }; + 4D5593DA153CED51009F2584 /* quotacheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quotacheck.c; path = quotacheck.tproj/quotacheck.c; sourceTree = SOURCE_ROOT; }; + 4D5593DB153CED51009F2584 /* quotacheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quotacheck.h; path = quotacheck.tproj/quotacheck.h; sourceTree = SOURCE_ROOT; }; + 4D5593E4153CEE4A009F2584 /* quotaon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quotaon; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5593ED153CEE66009F2584 /* quotaon.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = quotaon.8; path = quotaon.tproj/quotaon.8; sourceTree = SOURCE_ROOT; }; + 4D5593EE153CEE66009F2584 /* quotaon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quotaon.c; path = quotaon.tproj/quotaon.c; sourceTree = SOURCE_ROOT; }; + 4D5593F8153DC0DE009F2584 /* repquota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = repquota; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559401153DC13D009F2584 /* repquota.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = repquota.8; path = repquota.tproj/repquota.8; sourceTree = SOURCE_ROOT; }; + 4D559402153DC13D009F2584 /* repquota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = repquota.c; path = repquota.tproj/repquota.c; sourceTree = SOURCE_ROOT; }; + 4D55940B153DC27A009F2584 /* vndevice */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vndevice; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559416153DC2AB009F2584 /* vndevice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vndevice.c; path = vndevice.tproj/vndevice.c; sourceTree = SOURCE_ROOT; }; + 4D55941C153DC383009F2584 /* mount_devfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount_devfs; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559427153DC3A6009F2584 /* mount_devfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount_devfs.c; path = mount_devfs.tproj/mount_devfs.c; sourceTree = SOURCE_ROOT; }; + 4D55942A153DC420009F2584 /* libutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libutil.dylib; path = usr/lib/libutil.dylib; sourceTree = SDKROOT; }; + 4D559430153DC49A009F2584 /* mount_fdesc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount_fdesc; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mount_fdesc.8; path = mount_fdesc.tproj/mount_fdesc.8; sourceTree = SOURCE_ROOT; }; + 4D55943C153DC4DE009F2584 /* mount_fdesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount_fdesc.c; path = mount_fdesc.tproj/mount_fdesc.c; sourceTree = SOURCE_ROOT; }; + 4D55944E153DC634009F2584 /* vsdbutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vsdbutil; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.vsdbutil.plist; path = vsdbutil.tproj/com.apple.vsdbutil.plist; sourceTree = SOURCE_ROOT; }; + 4D559458153DC650009F2584 /* vsdbutil_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vsdbutil_main.c; path = vsdbutil.tproj/vsdbutil_main.c; sourceTree = SOURCE_ROOT; }; + 4D559459153DC650009F2584 /* vsdbutil.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = vsdbutil.8; path = vsdbutil.tproj/vsdbutil.8; sourceTree = SOURCE_ROOT; }; + 4D559464153DC808009F2584 /* dev_mkdb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dev_mkdb; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D55946D153DC839009F2584 /* dev_mkdb.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dev_mkdb.8; path = dev_mkdb.tproj/dev_mkdb.8; sourceTree = SOURCE_ROOT; }; + 4D55946E153DC839009F2584 /* dev_mkdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dev_mkdb.c; path = dev_mkdb.tproj/dev_mkdb.c; sourceTree = SOURCE_ROOT; }; + 4D559477153DC8FC009F2584 /* fstyp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559480153DC912009F2584 /* fstyp.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp.8; path = fstyp.tproj/fstyp.8; sourceTree = SOURCE_ROOT; }; + 4D559481153DC912009F2584 /* fstyp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp.c; path = fstyp.tproj/fstyp.c; sourceTree = SOURCE_ROOT; }; + 4D55948A153DC98D009F2584 /* fstyp_msdos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_msdos; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_msdos.8; path = fstyp.tproj/fstyp_msdos.8; sourceTree = SOURCE_ROOT; }; + 4D559494153DC9AE009F2584 /* fstyp_msdos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_msdos.c; path = fstyp.tproj/fstyp_msdos.c; sourceTree = SOURCE_ROOT; }; + 4D55949D153DC9FB009F2584 /* fstyp_ntfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_ntfs; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_ntfs.8; path = fstyp.tproj/fstyp_ntfs.8; sourceTree = SOURCE_ROOT; }; + 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_ntfs.c; path = fstyp.tproj/fstyp_ntfs.c; sourceTree = SOURCE_ROOT; }; + 4D5594AF153DCA53009F2584 /* fstyp_udf */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_udf; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_udf.8; path = fstyp.tproj/fstyp_udf.8; sourceTree = SOURCE_ROOT; }; + 4D5594BB153DCA74009F2584 /* fstyp_udf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_udf.c; path = fstyp.tproj/fstyp_udf.c; sourceTree = SOURCE_ROOT; }; + 4D5594C2153DCAFC009F2584 /* setclass */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = setclass; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5594CB153DCB72009F2584 /* setclass.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = setclass.8; path = setclass.tproj/setclass.8; sourceTree = SOURCE_ROOT; }; + 4D5594CC153DCB72009F2584 /* setclass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = setclass.c; path = setclass.tproj/setclass.c; sourceTree = SOURCE_ROOT; }; + 4D5594D5153DCC66009F2584 /* fuser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuser; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D5594E0153DCC92009F2584 /* fuser.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = fuser.1; path = fuser.tproj/fuser.1; sourceTree = SOURCE_ROOT; }; + 4D5594E1153DCC92009F2584 /* fuser.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = fuser.pl; path = fuser.tproj/fuser.pl; sourceTree = SOURCE_ROOT; }; + 785314FE227120BD00B25661 /* MediaKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaKit.framework; path = System/Library/PrivateFrameworks/MediaKit.framework; sourceTree = SDKROOT; }; + 785315012277BEA700B25661 /* mount.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = mount.entitlements; path = mount.tproj/mount.entitlements; sourceTree = SOURCE_ROOT; }; + B19B239A21C8DEF90001F35C /* edt_fstab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = edt_fstab.c; sourceTree = ""; }; + B19B239B21C8DEFA0001F35C /* edt_fstab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = edt_fstab.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4D07DD46153CA9A0002B57CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559312153CE198009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55933E153CE41E009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B19B239F21C8DF7B0001F35C /* CoreFoundation.framework in Frameworks */, + B19B239E21C8DF740001F35C /* APFS.framework in Frameworks */, + B19B239D21C8DF6E0001F35C /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55935D153CE561009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 785314FF227120BD00B25661 /* MediaKit.framework in Frameworks */, + 1A9041062091EE980061D05A /* CoreFoundation.framework in Frameworks */, + 1A9041042091EE910061D05A /* APFS.framework in Frameworks */, + 1A9041022091EE830061D05A /* IOKit.framework in Frameworks */, + 4D559389153CE794009F2584 /* libdisk.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55938B153CE7FD009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B19B23A521C8DFE10001F35C /* CoreFoundation.framework in Frameworks */, + B19B23A421C8DFD50001F35C /* IOKit.framework in Frameworks */, + B19B23A321C8DFCF0001F35C /* APFS.framework in Frameworks */, + 4D55939D153CE8AF009F2584 /* libdisk.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593A3153CEA90009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593B6153CEB7E009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593CA153CED29009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5593DF153CED8D009F2584 /* libdisk.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593E1153CEE4A009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593F5153DC0DE009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559408153DC27A009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559419153DC383009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D55942B153DC427009F2584 /* libutil.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55942D153DC49A009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D55943F153DC534009F2584 /* libutil.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55944B153DC634009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559461153DC808009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559474153DC8FC009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559487153DC98D009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55949A153DC9FB009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594AC153DCA53009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594BF153DCAFC009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594D2153DCC66009F2584 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 072AAAA32167CD68004ED4E2 /* mount_flags_dir */ = { + isa = PBXGroup; + children = ( + 072AAAA42167CE8E004ED4E2 /* mount_flags.c */, + 072AAAA52167CE8E004ED4E2 /* mount_flags.h */, + ); + path = mount_flags_dir; + sourceTree = ""; + }; + 1A9041002091EE820061D05A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 07AF95B323232837001E9266 /* Kernel.framework */, + 07AF95B12323281D001E9266 /* System.framework */, + 785314FE227120BD00B25661 /* MediaKit.framework */, + 1A9041052091EE980061D05A /* CoreFoundation.framework */, + 1A9041032091EE910061D05A /* APFS.framework */, + 1A9041012091EE830061D05A /* IOKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4D07DD29153CA616002B57CB = { + isa = PBXGroup; + children = ( + B1DF3D3D21C27FE00099F594 /* edt_fstab */, + 072AAAA32167CD68004ED4E2 /* mount_flags_dir */, + 4D559466153DC808009F2584 /* dev_mkdb */, + 4D07DD4C153CA9C4002B57CB /* disklib */, + 4D5593A8153CEA90009F2584 /* edquota */, + 4D559317153CE199009F2584 /* fdisk */, + 4D559343153CE41E009F2584 /* fsck */, + 4D559479153DC8FC009F2584 /* fstyp */, + 4D55948C153DC98D009F2584 /* fstyp_msdos */, + 4D55949F153DC9FB009F2584 /* fstyp_ntfs */, + 4D5594B1153DCA53009F2584 /* fstyp_udf */, + 4D5594D7153DCC66009F2584 /* fuser */, + 4D559362153CE561009F2584 /* mount */, + 4D55941E153DC384009F2584 /* mount_devfs */, + 4D559432153DC49A009F2584 /* mount_fdesc */, + 4D5593BB153CEB7E009F2584 /* quota */, + 4D5593CF153CED29009F2584 /* quotacheck */, + 4D5593E6153CEE4A009F2584 /* quotaon */, + 4D5593FA153DC0DE009F2584 /* repquota */, + 4D5594C4153DCAFC009F2584 /* setclass */, + 4D559390153CE7FD009F2584 /* umount */, + 4D55940D153DC27A009F2584 /* vndevice */, + 4D559450153DC634009F2584 /* vsdbutil */, + 4D559429153DC3F3009F2584 /* Libraries */, + 4D07DD35153CA616002B57CB /* Products */, + 1A9041002091EE820061D05A /* Frameworks */, + ); + sourceTree = ""; + }; + 4D07DD35153CA616002B57CB /* Products */ = { + isa = PBXGroup; + children = ( + 4D07DD49153CA9A0002B57CB /* libdisk.a */, + 4D559315153CE198009F2584 /* fdisk */, + 4D559341153CE41E009F2584 /* fsck */, + 4D559360153CE561009F2584 /* mount */, + 4D55938E153CE7FD009F2584 /* umount */, + 4D5593A6153CEA90009F2584 /* edquota */, + 4D5593B9153CEB7E009F2584 /* quota */, + 4D5593CD153CED29009F2584 /* quotacheck */, + 4D5593E4153CEE4A009F2584 /* quotaon */, + 4D5593F8153DC0DE009F2584 /* repquota */, + 4D55940B153DC27A009F2584 /* vndevice */, + 4D55941C153DC383009F2584 /* mount_devfs */, + 4D559430153DC49A009F2584 /* mount_fdesc */, + 4D55944E153DC634009F2584 /* vsdbutil */, + 4D559464153DC808009F2584 /* dev_mkdb */, + 4D559477153DC8FC009F2584 /* fstyp */, + 4D55948A153DC98D009F2584 /* fstyp_msdos */, + 4D55949D153DC9FB009F2584 /* fstyp_ntfs */, + 4D5594AF153DCA53009F2584 /* fstyp_udf */, + 4D5594C2153DCAFC009F2584 /* setclass */, + 4D5594D5153DCC66009F2584 /* fuser */, + ); + name = Products; + sourceTree = ""; + }; + 4D07DD4C153CA9C4002B57CB /* disklib */ = { + isa = PBXGroup; + children = ( + 4D07DD50153CA9DC002B57CB /* dkopen.h */, + 4D07DD54153CA9DC002B57CB /* pathnames.h */, + 4D07DD4D153CA9DC002B57CB /* dkcksum.c */, + 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */, + 4D07DD4F153CA9DC002B57CB /* dkopen.c */, + 4D07DD51153CA9DC002B57CB /* dksecsize.c */, + 4D07DD55153CA9DC002B57CB /* preen.c */, + 4D07DD56153CA9DC002B57CB /* vfslist.c */, + ); + name = disklib; + sourceTree = ""; + }; + 4D559317153CE199009F2584 /* fdisk */ = { + isa = PBXGroup; + children = ( + 4D55931F153CE1D9009F2584 /* auto.h */, + 4D559321153CE1D9009F2584 /* cmd.h */, + 4D559323153CE1D9009F2584 /* disk.h */, + 4D559328153CE1D9009F2584 /* mbr.h */, + 4D559329153CE1D9009F2584 /* mbrcode.h */, + 4D55932B153CE1D9009F2584 /* misc.h */, + 4D55932E153CE1D9009F2584 /* part.h */, + 4D559330153CE1D9009F2584 /* user.h */, + 4D559331153CE1D9009F2584 /* util.h */, + 4D55931E153CE1D9009F2584 /* auto.c */, + 4D559320153CE1D9009F2584 /* cmd.c */, + 4D559322153CE1D9009F2584 /* disk.c */, + 4D559325153CE1D9009F2584 /* fdisk.c */, + 4D559326153CE1D9009F2584 /* getrawpartition.c */, + 4D559327153CE1D9009F2584 /* mbr.c */, + 4D55932A153CE1D9009F2584 /* misc.c */, + 4D55932C153CE1D9009F2584 /* opendev.c */, + 4D55932D153CE1D9009F2584 /* part.c */, + 4D55932F153CE1D9009F2584 /* user.c */, + 4D559324153CE1D9009F2584 /* fdisk.8 */, + ); + path = fdisk; + sourceTree = ""; + }; + 4D559343153CE41E009F2584 /* fsck */ = { + isa = PBXGroup; + children = ( + 4D55934C153CE44E009F2584 /* fsck.h */, + 4D55934B153CE44E009F2584 /* fsck.c */, + 4D55934A153CE44E009F2584 /* fsck.8 */, + ); + path = fsck; + sourceTree = ""; + }; + 4D559362153CE561009F2584 /* mount */ = { + isa = PBXGroup; + children = ( + 4D55936D153CE58E009F2584 /* pathnames.h */, + 4D55936C153CE58E009F2584 /* mount.c */, + 4D55936B153CE58E009F2584 /* mount.8 */, + 4D559369153CE58E009F2584 /* fstab.5 */, + 785315012277BEA700B25661 /* mount.entitlements */, + ); + path = mount; + sourceTree = ""; + }; + 4D559390153CE7FD009F2584 /* umount */ = { + isa = PBXGroup; + children = ( + 4D559398153CE826009F2584 /* umount.c */, + 4D559397153CE826009F2584 /* umount.8 */, + ); + path = umount; + sourceTree = ""; + }; + 4D5593A8153CEA90009F2584 /* edquota */ = { + isa = PBXGroup; + children = ( + 4D5593B1153CEABD009F2584 /* pathnames.h */, + 4D5593B0153CEABD009F2584 /* edquota.c */, + 4D5593AF153CEABD009F2584 /* edquota.8 */, + ); + path = edquota; + sourceTree = ""; + }; + 4D5593BB153CEB7E009F2584 /* quota */ = { + isa = PBXGroup; + children = ( + 4D5593C2153CEB9A009F2584 /* quota.1 */, + 4D5593C3153CEB9A009F2584 /* quota.c */, + ); + path = quota; + sourceTree = ""; + }; + 4D5593CF153CED29009F2584 /* quotacheck */ = { + isa = PBXGroup; + children = ( + 4D5593DB153CED51009F2584 /* quotacheck.h */, + 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */, + 4D5593DA153CED51009F2584 /* quotacheck.c */, + 4D5593D9153CED51009F2584 /* quotacheck.8 */, + ); + path = quotacheck; + sourceTree = ""; + }; + 4D5593E6153CEE4A009F2584 /* quotaon */ = { + isa = PBXGroup; + children = ( + 4D5593EE153CEE66009F2584 /* quotaon.c */, + 4D5593ED153CEE66009F2584 /* quotaon.8 */, + ); + path = quotaon; + sourceTree = ""; + }; + 4D5593FA153DC0DE009F2584 /* repquota */ = { + isa = PBXGroup; + children = ( + 4D559402153DC13D009F2584 /* repquota.c */, + 4D559401153DC13D009F2584 /* repquota.8 */, + ); + path = repquota; + sourceTree = ""; + }; + 4D55940D153DC27A009F2584 /* vndevice */ = { + isa = PBXGroup; + children = ( + 4D559416153DC2AB009F2584 /* vndevice.c */, + ); + path = vndevice; + sourceTree = ""; + }; + 4D55941E153DC384009F2584 /* mount_devfs */ = { + isa = PBXGroup; + children = ( + 4D559427153DC3A6009F2584 /* mount_devfs.c */, + ); + path = mount_devfs; + sourceTree = ""; + }; + 4D559429153DC3F3009F2584 /* Libraries */ = { + isa = PBXGroup; + children = ( + 4D55942A153DC420009F2584 /* libutil.dylib */, + ); + name = Libraries; + sourceTree = ""; + }; + 4D559432153DC49A009F2584 /* mount_fdesc */ = { + isa = PBXGroup; + children = ( + 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */, + 4D55943C153DC4DE009F2584 /* mount_fdesc.c */, + ); + path = mount_fdesc; + sourceTree = ""; + }; + 4D559450153DC634009F2584 /* vsdbutil */ = { + isa = PBXGroup; + children = ( + 4D559458153DC650009F2584 /* vsdbutil_main.c */, + 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */, + 4D559459153DC650009F2584 /* vsdbutil.8 */, + ); + path = vsdbutil; + sourceTree = ""; + }; + 4D559466153DC808009F2584 /* dev_mkdb */ = { + isa = PBXGroup; + children = ( + 4D55946D153DC839009F2584 /* dev_mkdb.8 */, + 4D55946E153DC839009F2584 /* dev_mkdb.c */, + ); + path = dev_mkdb; + sourceTree = ""; + }; + 4D559479153DC8FC009F2584 /* fstyp */ = { + isa = PBXGroup; + children = ( + 4D559480153DC912009F2584 /* fstyp.8 */, + 4D559481153DC912009F2584 /* fstyp.c */, + ); + path = fstyp; + sourceTree = ""; + }; + 4D55948C153DC98D009F2584 /* fstyp_msdos */ = { + isa = PBXGroup; + children = ( + 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */, + 4D559494153DC9AE009F2584 /* fstyp_msdos.c */, + ); + path = fstyp_msdos; + sourceTree = ""; + }; + 4D55949F153DC9FB009F2584 /* fstyp_ntfs */ = { + isa = PBXGroup; + children = ( + 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */, + 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */, + ); + path = fstyp_ntfs; + sourceTree = ""; + }; + 4D5594B1153DCA53009F2584 /* fstyp_udf */ = { + isa = PBXGroup; + children = ( + 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */, + 4D5594BB153DCA74009F2584 /* fstyp_udf.c */, + ); + path = fstyp_udf; + sourceTree = ""; + }; + 4D5594C4153DCAFC009F2584 /* setclass */ = { + isa = PBXGroup; + children = ( + 4D5594CB153DCB72009F2584 /* setclass.8 */, + 4D5594CC153DCB72009F2584 /* setclass.c */, + ); + path = setclass; + sourceTree = ""; + }; + 4D5594D7153DCC66009F2584 /* fuser */ = { + isa = PBXGroup; + children = ( + 4D5594E0153DCC92009F2584 /* fuser.1 */, + 4D5594E1153DCC92009F2584 /* fuser.pl */, + ); + path = fuser; + sourceTree = ""; + }; + B1DF3D3D21C27FE00099F594 /* edt_fstab */ = { + isa = PBXGroup; + children = ( + B19B239A21C8DEF90001F35C /* edt_fstab.c */, + B19B239B21C8DEFA0001F35C /* edt_fstab.h */, + ); + path = edt_fstab; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4D07DD47153CA9A0002B57CB /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D07DD5A153CA9DC002B57CB /* dkopen.h in Headers */, + 4D07DD5E153CA9DC002B57CB /* pathnames.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4D07DD48153CA9A0002B57CB /* libdisk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D07DD4A153CA9A0002B57CB /* Build configuration list for PBXNativeTarget "libdisk" */; + buildPhases = ( + 4D07DD45153CA9A0002B57CB /* Sources */, + 4D07DD46153CA9A0002B57CB /* Frameworks */, + 4D07DD47153CA9A0002B57CB /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libdisk; + productName = disklib; + productReference = 4D07DD49153CA9A0002B57CB /* libdisk.a */; + productType = "com.apple.product-type.library.static"; + }; + 4D559314153CE198009F2584 /* fdisk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D55931C153CE199009F2584 /* Build configuration list for PBXNativeTarget "fdisk" */; + buildPhases = ( + 4D559311153CE198009F2584 /* Sources */, + 4D559312153CE198009F2584 /* Frameworks */, + 4D559313153CE198009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fdisk; + productName = fdisk; + productReference = 4D559315153CE198009F2584 /* fdisk */; + productType = "com.apple.product-type.tool"; + }; + 4D559340153CE41E009F2584 /* fsck */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559348153CE41E009F2584 /* Build configuration list for PBXNativeTarget "fsck" */; + buildPhases = ( + 4D55933D153CE41E009F2584 /* Sources */, + 4D55933E153CE41E009F2584 /* Frameworks */, + 4D55933F153CE41E009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fsck; + productName = fsck; + productReference = 4D559341153CE41E009F2584 /* fsck */; + productType = "com.apple.product-type.tool"; + }; + 4D55935F153CE561009F2584 /* mount */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559367153CE561009F2584 /* Build configuration list for PBXNativeTarget "mount" */; + buildPhases = ( + 4D55935C153CE561009F2584 /* Sources */, + 4D55935D153CE561009F2584 /* Frameworks */, + 4D55935E153CE561009F2584 /* Copy man5 */, + 4D559370153CE5DC009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + 4D5593A1153CE8BC009F2584 /* PBXTargetDependency */, + ); + name = mount; + productName = mount; + productReference = 4D559360153CE561009F2584 /* mount */; + productType = "com.apple.product-type.tool"; + }; + 4D55938D153CE7FD009F2584 /* umount */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559395153CE7FE009F2584 /* Build configuration list for PBXNativeTarget "umount" */; + buildPhases = ( + 4D55938A153CE7FD009F2584 /* Sources */, + 4D55938B153CE7FD009F2584 /* Frameworks */, + 4D55938C153CE7FD009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + 4D55939F153CE8B6009F2584 /* PBXTargetDependency */, + ); + name = umount; + productName = umount; + productReference = 4D55938E153CE7FD009F2584 /* umount */; + productType = "com.apple.product-type.tool"; + }; + 4D5593A5153CEA90009F2584 /* edquota */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5593AD153CEA90009F2584 /* Build configuration list for PBXNativeTarget "edquota" */; + buildPhases = ( + 4D5593A2153CEA90009F2584 /* Sources */, + 4D5593A3153CEA90009F2584 /* Frameworks */, + 4D5593A4153CEA90009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = edquota; + productName = edquota; + productReference = 4D5593A6153CEA90009F2584 /* edquota */; + productType = "com.apple.product-type.tool"; + }; + 4D5593B8153CEB7E009F2584 /* quota */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5593C0153CEB7E009F2584 /* Build configuration list for PBXNativeTarget "quota" */; + buildPhases = ( + 4D5593B5153CEB7E009F2584 /* Sources */, + 4D5593B6153CEB7E009F2584 /* Frameworks */, + 4D5593B7153CEB7E009F2584 /* Copy man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = quota; + productName = quota; + productReference = 4D5593B9153CEB7E009F2584 /* quota */; + productType = "com.apple.product-type.tool"; + }; + 4D5593CC153CED29009F2584 /* quotacheck */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5593D4153CED29009F2584 /* Build configuration list for PBXNativeTarget "quotacheck" */; + buildPhases = ( + 4D5593C9153CED29009F2584 /* Sources */, + 4D5593CA153CED29009F2584 /* Frameworks */, + 4D5593CB153CED29009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = quotacheck; + productName = quotacheck; + productReference = 4D5593CD153CED29009F2584 /* quotacheck */; + productType = "com.apple.product-type.tool"; + }; + 4D5593E3153CEE4A009F2584 /* quotaon */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5593EB153CEE4A009F2584 /* Build configuration list for PBXNativeTarget "quotaon" */; + buildPhases = ( + 4D5593E0153CEE4A009F2584 /* Sources */, + 4D5593E1153CEE4A009F2584 /* Frameworks */, + 4D5593E2153CEE4A009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = quotaon; + productName = quotaon; + productReference = 4D5593E4153CEE4A009F2584 /* quotaon */; + productType = "com.apple.product-type.tool"; + }; + 4D5593F7153DC0DE009F2584 /* repquota */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5593FF153DC0DE009F2584 /* Build configuration list for PBXNativeTarget "repquota" */; + buildPhases = ( + 4D5593F4153DC0DE009F2584 /* Sources */, + 4D5593F5153DC0DE009F2584 /* Frameworks */, + 4D5593F6153DC0DE009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = repquota; + productName = repquota; + productReference = 4D5593F8153DC0DE009F2584 /* repquota */; + productType = "com.apple.product-type.tool"; + }; + 4D55940A153DC27A009F2584 /* vndevice */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559412153DC27A009F2584 /* Build configuration list for PBXNativeTarget "vndevice" */; + buildPhases = ( + 4D559407153DC27A009F2584 /* Sources */, + 4D559408153DC27A009F2584 /* Frameworks */, + 4D559409153DC27A009F2584 /* Copy man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = vndevice; + productName = vndevice; + productReference = 4D55940B153DC27A009F2584 /* vndevice */; + productType = "com.apple.product-type.tool"; + }; + 4D55941B153DC383009F2584 /* mount_devfs */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559423153DC384009F2584 /* Build configuration list for PBXNativeTarget "mount_devfs" */; + buildPhases = ( + 4D559418153DC383009F2584 /* Sources */, + 4D559419153DC383009F2584 /* Frameworks */, + 4D55941A153DC383009F2584 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = mount_devfs; + productName = mount_devfs; + productReference = 4D55941C153DC383009F2584 /* mount_devfs */; + productType = "com.apple.product-type.tool"; + }; + 4D55942F153DC49A009F2584 /* mount_fdesc */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559437153DC49A009F2584 /* Build configuration list for PBXNativeTarget "mount_fdesc" */; + buildPhases = ( + 4D55942C153DC49A009F2584 /* Sources */, + 4D55942D153DC49A009F2584 /* Frameworks */, + 4D55942E153DC49A009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = mount_fdesc; + productName = mount_fdesc; + productReference = 4D559430153DC49A009F2584 /* mount_fdesc */; + productType = "com.apple.product-type.tool"; + }; + 4D55944D153DC634009F2584 /* vsdbutil */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559455153DC634009F2584 /* Build configuration list for PBXNativeTarget "vsdbutil" */; + buildPhases = ( + 4D55944A153DC634009F2584 /* Sources */, + 4D55944B153DC634009F2584 /* Frameworks */, + 4D55944C153DC634009F2584 /* Copy man8 */, + 4D55945E153DC730009F2584 /* Copy com.apple.vsdbutil.plist */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = vsdbutil; + productName = vsdbutil; + productReference = 4D55944E153DC634009F2584 /* vsdbutil */; + productType = "com.apple.product-type.tool"; + }; + 4D559463153DC808009F2584 /* dev_mkdb */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D55946B153DC808009F2584 /* Build configuration list for PBXNativeTarget "dev_mkdb" */; + buildPhases = ( + 4D559460153DC808009F2584 /* Sources */, + 4D559461153DC808009F2584 /* Frameworks */, + 4D559462153DC808009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = dev_mkdb; + productName = dev_mkdb; + productReference = 4D559464153DC808009F2584 /* dev_mkdb */; + productType = "com.apple.product-type.tool"; + }; + 4D559476153DC8FC009F2584 /* fstyp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D55947E153DC8FC009F2584 /* Build configuration list for PBXNativeTarget "fstyp" */; + buildPhases = ( + 4D559473153DC8FC009F2584 /* Sources */, + 4D559474153DC8FC009F2584 /* Frameworks */, + 4D559475153DC8FC009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fstyp; + productName = fstyp; + productReference = 4D559477153DC8FC009F2584 /* fstyp */; + productType = "com.apple.product-type.tool"; + }; + 4D559489153DC98D009F2584 /* fstyp_msdos */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D559491153DC98D009F2584 /* Build configuration list for PBXNativeTarget "fstyp_msdos" */; + buildPhases = ( + 4D559486153DC98D009F2584 /* Sources */, + 4D559487153DC98D009F2584 /* Frameworks */, + 4D559488153DC98D009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fstyp_msdos; + productName = fstyp_msdos; + productReference = 4D55948A153DC98D009F2584 /* fstyp_msdos */; + productType = "com.apple.product-type.tool"; + }; + 4D55949C153DC9FB009F2584 /* fstyp_ntfs */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5594A4153DC9FB009F2584 /* Build configuration list for PBXNativeTarget "fstyp_ntfs" */; + buildPhases = ( + 4D559499153DC9FB009F2584 /* Sources */, + 4D55949A153DC9FB009F2584 /* Frameworks */, + 4D55949B153DC9FB009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fstyp_ntfs; + productName = fstyp_ntfs; + productReference = 4D55949D153DC9FB009F2584 /* fstyp_ntfs */; + productType = "com.apple.product-type.tool"; + }; + 4D5594AE153DCA53009F2584 /* fstyp_udf */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5594B6153DCA53009F2584 /* Build configuration list for PBXNativeTarget "fstyp_udf" */; + buildPhases = ( + 4D5594AB153DCA53009F2584 /* Sources */, + 4D5594AC153DCA53009F2584 /* Frameworks */, + 4D5594AD153DCA53009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fstyp_udf; + productName = fstyp_udf; + productReference = 4D5594AF153DCA53009F2584 /* fstyp_udf */; + productType = "com.apple.product-type.tool"; + }; + 4D5594C1153DCAFC009F2584 /* setclass */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5594C9153DCAFC009F2584 /* Build configuration list for PBXNativeTarget "setclass" */; + buildPhases = ( + 4D5594BE153DCAFC009F2584 /* Sources */, + 4D5594BF153DCAFC009F2584 /* Frameworks */, + 4D5594C0153DCAFC009F2584 /* Copy man8 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = setclass; + productName = setclass; + productReference = 4D5594C2153DCAFC009F2584 /* setclass */; + productType = "com.apple.product-type.tool"; + }; + 4D5594D4153DCC66009F2584 /* fuser */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4D5594DC153DCC66009F2584 /* Build configuration list for PBXNativeTarget "fuser" */; + buildPhases = ( + 4D5594D1153DCC66009F2584 /* Sources */, + 4D5594D2153DCC66009F2584 /* Frameworks */, + 4D5594E4153DCCD3009F2584 /* Copy fuser */, + 4D5594D3153DCC66009F2584 /* Copy man1 */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = fuser; + productName = fuser; + productReference = 4D5594D5153DCC66009F2584 /* fuser */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4D07DD2B153CA616002B57CB /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0440; + ORGANIZATIONNAME = "Apple Inc."; + }; + buildConfigurationList = 4D07DD2E153CA616002B57CB /* Build configuration list for PBXProject "diskdev_cmds" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + ); + mainGroup = 4D07DD29153CA616002B57CB; + productRefGroup = 4D07DD35153CA616002B57CB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4D559440153DC57D009F2584 /* All_MacOSX */, + 4D559443153DC587009F2584 /* All_iOS */, + 4D55934F153CE4CC009F2584 /* Common */, + 4D07DD48153CA9A0002B57CB /* libdisk */, + 4D559463153DC808009F2584 /* dev_mkdb */, + 4D5593A5153CEA90009F2584 /* edquota */, + 4D559314153CE198009F2584 /* fdisk */, + 4D559340153CE41E009F2584 /* fsck */, + 4D559476153DC8FC009F2584 /* fstyp */, + 4D559489153DC98D009F2584 /* fstyp_msdos */, + 4D55949C153DC9FB009F2584 /* fstyp_ntfs */, + 4D5594AE153DCA53009F2584 /* fstyp_udf */, + 4D5594D4153DCC66009F2584 /* fuser */, + 4D55935F153CE561009F2584 /* mount */, + 4D55941B153DC383009F2584 /* mount_devfs */, + 4D55942F153DC49A009F2584 /* mount_fdesc */, + 4D5593B8153CEB7E009F2584 /* quota */, + 4D5593CC153CED29009F2584 /* quotacheck */, + 4D5593E3153CEE4A009F2584 /* quotaon */, + 4D559514153DE116009F2584 /* quotaoff */, + 4D5593F7153DC0DE009F2584 /* repquota */, + 4D5594C1153DCAFC009F2584 /* setclass */, + 4D55938D153CE7FD009F2584 /* umount */, + 4D55940A153DC27A009F2584 /* vndevice */, + 4D55944D153DC634009F2584 /* vsdbutil */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4D5594E4153DCCD3009F2584 /* Copy fuser */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/fuser.tproj/fuser.pl", + ); + name = "Copy fuser"; + outputPaths = ( + "$(DSTROOT)$(INSTALL_PATH)/fuser", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "set -x\nset -e\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\nchmod 555 ${SCRIPT_OUTPUT_FILE_0}\n"; + showEnvVarsInLog = 0; + }; + 4D55951B153DE1EF009F2584 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(DSTROOT)/usr/sbin/quotaon", + "$(DSTROOT)/usr/share/man/man8/quotaon.8", + ); + outputPaths = ( + "$(DSTROOT)/usr/sbin/quotaoff", + "$(DSTROOT)/usr/share/man/man8/quotaoff.8", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "set -x\nset -e\n\nln -fhv \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\nmkdir -p \"${DSTROOT}/usr/share/man/man8\"\nln -fhv \"${SCRIPT_INPUT_FILE_1}\" \"${SCRIPT_OUTPUT_FILE_1}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4D07DD45153CA9A0002B57CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D07DD57153CA9DC002B57CB /* dkcksum.c in Sources */, + 4D07DD5B153CA9DC002B57CB /* dksecsize.c in Sources */, + 4D07DD5F153CA9DC002B57CB /* preen.c in Sources */, + 4D07DD60153CA9DC002B57CB /* vfslist.c in Sources */, + 4D07DD58153CA9DC002B57CB /* dkdisklabel.c in Sources */, + 4D07DD59153CA9DC002B57CB /* dkopen.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559311153CE198009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559333153CE1D9009F2584 /* cmd.c in Sources */, + 4D559334153CE1D9009F2584 /* disk.c in Sources */, + 4D559335153CE1D9009F2584 /* fdisk.c in Sources */, + 4D559336153CE1D9009F2584 /* getrawpartition.c in Sources */, + 4D559337153CE1D9009F2584 /* mbr.c in Sources */, + 4D559338153CE1D9009F2584 /* misc.c in Sources */, + 4D559339153CE1D9009F2584 /* opendev.c in Sources */, + 4D55933A153CE1D9009F2584 /* part.c in Sources */, + 4D55933B153CE1D9009F2584 /* user.c in Sources */, + 4D559332153CE1D9009F2584 /* auto.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55933D153CE41E009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B19B239C21C8DF660001F35C /* edt_fstab.c in Sources */, + 4D55934D153CE44E009F2584 /* fsck.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55935C153CE561009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B19B23A021C8DFA40001F35C /* edt_fstab.c in Sources */, + 07CE4C1821906BB800BF11C0 /* mount.c in Sources */, + 072AAAA62167CE8F004ED4E2 /* mount_flags.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55938A153CE7FD009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B19B23A221C8DFC30001F35C /* edt_fstab.c in Sources */, + 4D559399153CE826009F2584 /* umount.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593A2153CEA90009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5593B2153CEABD009F2584 /* edquota.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593B5153CEB7E009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5593C4153CEB9A009F2584 /* quota.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593C9153CED29009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5593DD153CED51009F2584 /* quotacheck.c in Sources */, + 4D5593DC153CED51009F2584 /* hfs_quotacheck.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593E0153CEE4A009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5593EF153CEE66009F2584 /* quotaon.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5593F4153DC0DE009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559403153DC13D009F2584 /* repquota.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559407153DC27A009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559417153DC2AB009F2584 /* vndevice.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559418153DC383009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559428153DC3A6009F2584 /* mount_devfs.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55942C153DC49A009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D55943D153DC4DE009F2584 /* mount_fdesc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D55944A153DC634009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 078B970D2190682600674625 /* mount_flags.c in Sources */, + 4D55945A153DC650009F2584 /* vsdbutil_main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559460153DC808009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D55946F153DC839009F2584 /* dev_mkdb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559473153DC8FC009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559482153DC912009F2584 /* fstyp.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559486153DC98D009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D559495153DC9AE009F2584 /* fstyp_msdos.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D559499153DC9FB009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5594AA153DCA19009F2584 /* fstyp_ntfs.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594AB153DCA53009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5594BC153DCA74009F2584 /* fstyp_udf.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594BE153DCAFC009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D5594CD153DCB72009F2584 /* setclass.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D5594D1153DCC66009F2584 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 071077D92488A09C003B97C7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5594C1153DCAFC009F2584 /* setclass */; + targetProxy = 071077D82488A09C003B97C7 /* PBXContainerItemProxy */; + }; + 07747AA21DA8511D00ACE020 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559476153DC8FC009F2584 /* fstyp */; + targetProxy = 07747AA11DA8511D00ACE020 /* PBXContainerItemProxy */; + }; + 4D559357153CE4EA009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D07DD48153CA9A0002B57CB /* libdisk */; + targetProxy = 4D559356153CE4EA009F2584 /* PBXContainerItemProxy */; + }; + 4D559359153CE4EC009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559314153CE198009F2584 /* fdisk */; + targetProxy = 4D559358153CE4EC009F2584 /* PBXContainerItemProxy */; + }; + 4D55935B153CE4ED009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559340153CE41E009F2584 /* fsck */; + targetProxy = 4D55935A153CE4ED009F2584 /* PBXContainerItemProxy */; + }; + 4D559373153CE5F8009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55935F153CE561009F2584 /* mount */; + targetProxy = 4D559372153CE5F8009F2584 /* PBXContainerItemProxy */; + }; + 4D55939C153CE83A009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55938D153CE7FD009F2584 /* umount */; + targetProxy = 4D55939B153CE83A009F2584 /* PBXContainerItemProxy */; + }; + 4D55939F153CE8B6009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D07DD48153CA9A0002B57CB /* libdisk */; + targetProxy = 4D55939E153CE8B6009F2584 /* PBXContainerItemProxy */; + }; + 4D5593A1153CE8BC009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D07DD48153CA9A0002B57CB /* libdisk */; + targetProxy = 4D5593A0153CE8BC009F2584 /* PBXContainerItemProxy */; + }; + 4D559415153DC282009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55940A153DC27A009F2584 /* vndevice */; + targetProxy = 4D559414153DC282009F2584 /* PBXContainerItemProxy */; + }; + 4D559426153DC38F009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55941B153DC383009F2584 /* mount_devfs */; + targetProxy = 4D559425153DC38F009F2584 /* PBXContainerItemProxy */; + }; + 4D55943A153DC4C0009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55942F153DC49A009F2584 /* mount_fdesc */; + targetProxy = 4D559439153DC4C0009F2584 /* PBXContainerItemProxy */; + }; + 4D559447153DC597009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55934F153CE4CC009F2584 /* Common */; + targetProxy = 4D559446153DC597009F2584 /* PBXContainerItemProxy */; + }; + 4D559449153DC599009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55934F153CE4CC009F2584 /* Common */; + targetProxy = 4D559448153DC599009F2584 /* PBXContainerItemProxy */; + }; + 4D55945C153DC665009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55944D153DC634009F2584 /* vsdbutil */; + targetProxy = 4D55945B153DC665009F2584 /* PBXContainerItemProxy */; + }; + 4D559472153DC87B009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559463153DC808009F2584 /* dev_mkdb */; + targetProxy = 4D559471153DC87B009F2584 /* PBXContainerItemProxy */; + }; + 4D559498153DC9E8009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559489153DC98D009F2584 /* fstyp_msdos */; + targetProxy = 4D559497153DC9E8009F2584 /* PBXContainerItemProxy */; + }; + 4D5594A7153DCA04009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D55949C153DC9FB009F2584 /* fstyp_ntfs */; + targetProxy = 4D5594A6153DCA04009F2584 /* PBXContainerItemProxy */; + }; + 4D5594B9153DCA5E009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5594AE153DCA53009F2584 /* fstyp_udf */; + targetProxy = 4D5594B8153DCA5E009F2584 /* PBXContainerItemProxy */; + }; + 4D5594DF153DCC73009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5594D4153DCC66009F2584 /* fuser */; + targetProxy = 4D5594DE153DCC73009F2584 /* PBXContainerItemProxy */; + }; + 4D55951A153DE1CB009F2584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593E3153CEE4A009F2584 /* quotaon */; + targetProxy = 4D559519153DE1CB009F2584 /* PBXContainerItemProxy */; + }; + B12C9C9222A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593A5153CEA90009F2584 /* edquota */; + targetProxy = B12C9C9122A7CDE300B9F497 /* PBXContainerItemProxy */; + }; + B12C9C9422A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593B8153CEB7E009F2584 /* quota */; + targetProxy = B12C9C9322A7CDE300B9F497 /* PBXContainerItemProxy */; + }; + B12C9C9622A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593CC153CED29009F2584 /* quotacheck */; + targetProxy = B12C9C9522A7CDE300B9F497 /* PBXContainerItemProxy */; + }; + B12C9C9822A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593E3153CEE4A009F2584 /* quotaon */; + targetProxy = B12C9C9722A7CDE300B9F497 /* PBXContainerItemProxy */; + }; + B12C9C9A22A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D559514153DE116009F2584 /* quotaoff */; + targetProxy = B12C9C9922A7CDE300B9F497 /* PBXContainerItemProxy */; + }; + B12C9C9C22A7CDE300B9F497 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D5593F7153DC0DE009F2584 /* repquota */; + targetProxy = B12C9C9B22A7CDE300B9F497 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 4D07DD3D153CA616002B57CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + INSTALL_MODE_FLAG = "ugo-w,a+rX"; + OTHER_CFLAGS = ""; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos"; + WARNING_CFLAGS = "-Wall"; + }; + name = Release; + }; + 4D07DD4B153CA9A0002B57CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; + PRODUCT_NAME = disk; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 4D55931D153CE199009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559349153CE41E009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + }; + name = Release; + }; + 4D559351153CE4CC009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559368153CE561009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = mount.tproj/mount.entitlements; + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks"; + }; + name = Release; + }; + 4D559396153CE7FE009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + }; + name = Release; + }; + 4D5593AE153CEA90009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5593C1153CEB7E009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_MODE_FLAG = 04555; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5593D5153CED29009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5593EC153CEE4A009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559400153DC0DE009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559413153DC27A009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/libexec; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559424153DC384009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559438153DC49A009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559442153DC57D009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559445153DC587009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559456153DC634009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D55946C153DC808009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D55947F153DC8FC009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559492153DC98D009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5594A5153DC9FB009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5594B7153DCA53009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /sbin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5594CA153DCAFC009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D5594DD153DCC66009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 4D559516153DE116009F2584 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4D07DD2E153CA616002B57CB /* Build configuration list for PBXProject "diskdev_cmds" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D07DD3D153CA616002B57CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D07DD4A153CA9A0002B57CB /* Build configuration list for PBXNativeTarget "libdisk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D07DD4B153CA9A0002B57CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D55931C153CE199009F2584 /* Build configuration list for PBXNativeTarget "fdisk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D55931D153CE199009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559348153CE41E009F2584 /* Build configuration list for PBXNativeTarget "fsck" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559349153CE41E009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559350153CE4CC009F2584 /* Build configuration list for PBXAggregateTarget "Common" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559351153CE4CC009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559367153CE561009F2584 /* Build configuration list for PBXNativeTarget "mount" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559368153CE561009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559395153CE7FE009F2584 /* Build configuration list for PBXNativeTarget "umount" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559396153CE7FE009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5593AD153CEA90009F2584 /* Build configuration list for PBXNativeTarget "edquota" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5593AE153CEA90009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5593C0153CEB7E009F2584 /* Build configuration list for PBXNativeTarget "quota" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5593C1153CEB7E009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5593D4153CED29009F2584 /* Build configuration list for PBXNativeTarget "quotacheck" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5593D5153CED29009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5593EB153CEE4A009F2584 /* Build configuration list for PBXNativeTarget "quotaon" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5593EC153CEE4A009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5593FF153DC0DE009F2584 /* Build configuration list for PBXNativeTarget "repquota" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559400153DC0DE009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559412153DC27A009F2584 /* Build configuration list for PBXNativeTarget "vndevice" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559413153DC27A009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559423153DC384009F2584 /* Build configuration list for PBXNativeTarget "mount_devfs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559424153DC384009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559437153DC49A009F2584 /* Build configuration list for PBXNativeTarget "mount_fdesc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559438153DC49A009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559441153DC57D009F2584 /* Build configuration list for PBXAggregateTarget "All_MacOSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559442153DC57D009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559444153DC587009F2584 /* Build configuration list for PBXAggregateTarget "All_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559445153DC587009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559455153DC634009F2584 /* Build configuration list for PBXNativeTarget "vsdbutil" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559456153DC634009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D55946B153DC808009F2584 /* Build configuration list for PBXNativeTarget "dev_mkdb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D55946C153DC808009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D55947E153DC8FC009F2584 /* Build configuration list for PBXNativeTarget "fstyp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D55947F153DC8FC009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559491153DC98D009F2584 /* Build configuration list for PBXNativeTarget "fstyp_msdos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559492153DC98D009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5594A4153DC9FB009F2584 /* Build configuration list for PBXNativeTarget "fstyp_ntfs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5594A5153DC9FB009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5594B6153DCA53009F2584 /* Build configuration list for PBXNativeTarget "fstyp_udf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5594B7153DCA53009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5594C9153DCAFC009F2584 /* Build configuration list for PBXNativeTarget "setclass" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5594CA153DCAFC009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D5594DC153DCC66009F2584 /* Build configuration list for PBXNativeTarget "fuser" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D5594DD153DCC66009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4D559515153DE116009F2584 /* Build configuration list for PBXAggregateTarget "quotaoff" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D559516153DE116009F2584 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4D07DD2B153CA616002B57CB /* Project object */; +} diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..e0c148d --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..08de0be --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme new file mode 100644 index 0000000..844c24e --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme new file mode 100644 index 0000000..1b41173 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme new file mode 100644 index 0000000..d077a0a --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme new file mode 100644 index 0000000..da3f116 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme new file mode 100644 index 0000000..aac4a1c --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme new file mode 100644 index 0000000..23af6d2 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme new file mode 100644 index 0000000..5405e97 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme new file mode 100644 index 0000000..7e5ae37 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme new file mode 100644 index 0000000..7135b78 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme new file mode 100644 index 0000000..144c15c --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme new file mode 100644 index 0000000..8cb1245 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme new file mode 100644 index 0000000..db85539 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme new file mode 100644 index 0000000..0f60716 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme new file mode 100644 index 0000000..6a53cec --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme new file mode 100644 index 0000000..246cbba --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme new file mode 100644 index 0000000..dad5f9a --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme new file mode 100644 index 0000000..df303b9 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme new file mode 100644 index 0000000..48bf0e6 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme new file mode 100644 index 0000000..1a5fcda --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme new file mode 100644 index 0000000..75149cf --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme new file mode 100644 index 0000000..b249cf1 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme new file mode 100644 index 0000000..51ffb5d --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme new file mode 100644 index 0000000..5bb5059 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme new file mode 100644 index 0000000..6e7d1c4 --- /dev/null +++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/diskdev_cmds/disklib/dkcksum.c b/diskdev_cmds/disklib/dkcksum.c new file mode 100644 index 0000000..e275cb2 --- /dev/null +++ b/diskdev_cmds/disklib/dkcksum.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * 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. + */ + + +#include + +#if defined (linux) && defined (__powerpc__) +#define __ppc__ +#endif + +#include + +u_short +dkcksum(lp) + register struct disklabel *lp; +{ + register u_short *start, *end; + register u_short sum = 0; + + start = (u_short *)lp; + end = (u_short *)&lp->d_partitions[lp->d_npartitions]; + while (start < end) + sum ^= *start++; + return (sum); +} diff --git a/diskdev_cmds/disklib/dkdisklabel.c b/diskdev_cmds/disklib/dkdisklabel.c new file mode 100644 index 0000000..3fffce5 --- /dev/null +++ b/diskdev_cmds/disklib/dkdisklabel.c @@ -0,0 +1,193 @@ +/* Copyright 1999 Apple Computer, Inc. + * + * Generate a bsd disk label routine. + * Input: open file descriptor to the device node, and + * pointer to a disk label structure to fill in + * Return: errno status + * + * HISTORY + * + * 24 Feb 1999 D. Markarian at Apple + * Created. + */ + +#include /* memset */ +#include /* sys/disklabel.h */ +#include /* NBPG */ + +#include /* DKIOCGETBLOCKSIZE ioctl */ + +#include /* struct disklabel */ + +u_short dkcksum __P((register struct disklabel *lp)); +int dkdisklabelregenerate __P((int fd, struct disklabel * lp, int newblksize)); + +/* + * The following two constants set the default block and fragment sizes. + * Both constants must be a power of 2 and meet the following constraints: + * MINBSIZE <= GENBLKSIZE <= MAXBSIZE + * sectorsize <= GENFRAGSIZE <= GENBLKSIZE + * GENBLKSIZE / GENFRAGSIZE <= 8 + */ +#define GENFRAGSIZE 1024 +#define GENBLKSIZE NBPG /* 4096 */ + +/* + * Cylinder groups may have up to many cylinders. The actual + * number used depends upon how much information can be stored + * on a single cylinder. The default is to use 16 cylinders + * per group. + */ +#define GENCPG 16 + +/* + * Interleave is physical sector interleave, set up by the + * formatter or controller when formatting. When interleaving is + * in use, logically adjacent sectors are not physically + * contiguous, but instead are separated by some number of + * sectors. It is specified as the ratio of physical sectors + * traversed per logical sector. Thus an interleave of 1:1 + * implies contiguous layout, while 2:1 implies that logical + * sector 0 is separated by one sector from logical sector 1. + */ +#define GENINTERLEAVE 1 + +/* + * Rotational speed; # of data sectors per track. + */ +#define GENRPM 3600 +#define GENNSECTORS 32 + +int dkdisklabel(int fd, struct disklabel * lp) +{ + return dkdisklabelregenerate(fd, lp, 0); +} + +int dkdisklabelregenerate(int fd, struct disklabel * lp, int newblksize) +{ + /* + * Generate a bsd-style disk label for the specified device node. + */ + + int blksize; + int error; + int index; + int64_t numblks; + + /* obtain the size of the media (in blocks) */ + if ( (error = ioctl(fd, DKIOCGETBLOCKCOUNT, &numblks)) < 0 ) + return(error); + + /* obtain the block size of the media */ + if ( (error = ioctl(fd, DKIOCGETBLOCKSIZE, &blksize)) < 0 ) + return(error); + + /* adjust the size of the media with newblksize should it be specified */ + if (newblksize) + { + numblks = ((numblks * blksize) / newblksize); + blksize = newblksize; + } + + /* + * clear the disk label structure and then fill in the appropriate fields; + * we comment out lines that are initializations to zero with //, since it + * is redundant work + */ + memset(lp, 0, sizeof(struct disklabel)); + + lp->d_magic = DISKMAGIC; /* the magic number */ +// lp->d_type = 0; /* drive type */ +// lp->d_subtype = 0; /* controller/d_type specific */ +// lp->d_typename[0] = 0; /* type name, e.g. "eagle" */ + /* + * d_packname contains the pack identifier and is returned when + * the disklabel is read off the disk or in-core copy. + * d_boot0 and d_boot1 are the (optional) names of the + * primary (block 0) and secondary (block 1-15) bootstraps + * as found in /usr/mdec. These are returned when using + * getdiskbyname(3) to retrieve the values from /etc/disktab. + */ +// lp->d_packname[0] = 0; /* pack identifier */ + + /* disk geometry: */ + lp->d_secsize = blksize; /* # of bytes per sector */ + lp->d_nsectors = GENNSECTORS; /* # of data sectors per track */ + /* # of tracks per cylinder */ + if (numblks < 8*32*1024) /* <=528.4 MB */ + lp->d_ntracks = 16; + else if (numblks < 16*32*1024) /* <=1.057 GB */ + lp->d_ntracks = 32; + else if (numblks < 32*32*1024) /* <=2.114 GB */ + lp->d_ntracks = 54; + else if (numblks < 64*32*1024) /* <=4.228 GB */ + lp->d_ntracks = 128; + else /* > 4.228 GB */ + lp->d_ntracks = 255; + /* # of data cylinders per unit */ + lp->d_ncylinders = numblks / lp->d_ntracks / lp->d_nsectors; + /* # of data sectors per cylinder */ + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; + lp->d_secperunit = numblks; /* # of data sectors per unit */ + /* + * Spares (bad sector replacements) below are not counted in + * d_nsectors or d_secpercyl. Spare sectors are assumed to + * be physical sectors which occupy space at the end of each + * track and/or cylinder. + */ +// lp->d_sparespertrack = 0; /* # of spare sectors per track */ +// lp->d_sparespercyl = 0; /* # of data sectors per unit */ + /* + * Alternate cylinders include maintenance, replacement, configuration + * description areas, etc. + */ +// lp->d_acylinders = 0; /* # of alt. cylinders per unit */ + + /* hardware characteristics: */ + /* + * d_interleave, d_trackskew and d_cylskew describe perturbations + * in the media format used to compensate for a slow controller. + * Interleave is physical sector interleave, set up by the + * formatter or controller when formatting. When interleaving is + * in use, logically adjacent sectors are not physically + * contiguous, but instead are separated by some number of + * sectors. It is specified as the ratio of physical sectors + * traversed per logical sector. Thus an interleave of 1:1 + * implies contiguous layout, while 2:1 implies that logical + * sector 0 is separated by one sector from logical sector 1. + * d_trackskew is the offset of sector 0 on track N relative to + * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew + * is the offset of sector 0 on cylinder N relative to sector 0 + * on cylinder N-1. + */ + lp->d_rpm = GENRPM; /* rotational speed */ + lp->d_interleave = GENINTERLEAVE; /* hardware sector interleave */ +// lp->d_trackskew = 0; /* sector 0 skew, per track */ +// lp->d_cylskew = 0; /* sector 0 skew, per cylinder */ +// lp->d_headswitch = 0; /* head switch time, usec */ +// lp->d_trkseek = 0; /* track-to-track seek, usec */ +// lp->d_flags = 0; /* generic flags */ +// lp->d_drivedata[0-4] = 0; /* drive-type specific information */ +// lp->d_spare[0-4] = 0; /* reserved for future use */ + lp->d_magic2 = DISKMAGIC; /* the magic number (again) */ +// lp->d_checksum = 0; /* xor of data incl. partitions */ + + /* filesystem and partition information: */ + lp->d_npartitions = MAXPARTITIONS; /* number of partitions */ + + for (index = 0; index < MAXPARTITIONS; index++) + { + struct partition * pp = &(lp->d_partitions[index]); + pp->p_size = numblks; /* number of sectors */ +// pp->p_offset = 0; /* starting sector */ + pp->p_fsize = MAX(GENFRAGSIZE, blksize); /* fs fragment size */ + pp->p_fstype = FS_BSDFFS; /* fs type */ + pp->p_frag = MIN(8, GENBLKSIZE / pp->p_fsize);/* fs fragments/block */ + pp->p_cpg = GENCPG; /* fs cylinders/group */ + } + + /* compute a checksum on the resulting structure */ + lp->d_checksum = dkcksum(lp); + + return 0; /* success */ +} diff --git a/diskdev_cmds/disklib/dkopen.c b/diskdev_cmds/disklib/dkopen.c new file mode 100644 index 0000000..7a94561 --- /dev/null +++ b/diskdev_cmds/disklib/dkopen.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "dkopen.h" + +#include +#include +#include +#include + +int dkopen (const char *path, int flags, int mode) +{ +#if defined (linux) + return (open64 (path, flags, mode)); +#elif defined (__APPLE__) + return (open (path, flags, mode)); +#endif +} + +int dkclose (int filedes) +{ +#if defined (linux) + return (close (filedes)); +#elif defined (__APPLE__) + return (close (filedes)); +#endif +} + +off64_t dklseek (int filedes, off64_t offset, int whence) +{ +#if defined (linux) + return (lseek64 (filedes, offset, whence)); +#elif defined (__APPLE__) + return (lseek (filedes, offset, whence)); +#endif +} + diff --git a/diskdev_cmds/disklib/dkopen.h b/diskdev_cmds/disklib/dkopen.h new file mode 100644 index 0000000..eb0bdeb --- /dev/null +++ b/diskdev_cmds/disklib/dkopen.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * File I/O stubs + * + * Linux and other OSs may use open64, lseek64 instead of defaulting off_t to + * 64-bits like OSX does. This file provides cover functions to always perform + * 64-bit file I/O. + */ + +#ifndef _DKOPEN_H_ +#define _DKOPEN_H_ + +/* Must predefine the large file flags before including sys/types.h */ +#if defined (linux) +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#elif defined (__APPLE__) +#else +#error Platform not recognized +#endif + +#include + +/* Typedef off64_t for platforms that don't have it declared */ +#if defined (__APPLE__) && !defined (linux) +typedef u_int64_t off64_t; +#endif + +int dkopen (const char *path, int flags, int mode); +int dkclose (int filedes); + +off64_t dklseek (int fileds, off64_t offset, int whence); + +#endif diff --git a/diskdev_cmds/disklib/dksecsize.c b/diskdev_cmds/disklib/dksecsize.c new file mode 100644 index 0000000..0cfad82 --- /dev/null +++ b/diskdev_cmds/disklib/dksecsize.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* Copyright 1998 Apple Computer, Inc. + * + * Get disk label's sector size routine. + * Input: pointer to a block device string ie: "/dev/disk1s1" + * Return: sector size from the disk label + * + * HISTORY + * + * 27 May 1998 K. Crippes at Apple + * Rhapsody version created. + * 18 Feb 1999 D. Markarian at Apple + * DKIOCGLABEL deprecated; using DKIOCBLKSIZE instead, which now returns + * the appropriate size for ufs partitions created with wierd block sizes. + */ + +#include +#include +#include +#include +#include +#include +#include + +char *blockcheck __P((char *)); + +long dksecsize (dev) + char *dev; +{ + int fd; /* file descriptor for reading device label */ + char *cdev; + int devblklen; + extern int errno; + + /* Convert block device into a character device string */ + if ((cdev = blockcheck(dev))) { + if ((fd = open(cdev, O_RDONLY)) < 0) { + fprintf(stderr, "Can't open %s, %s\n", cdev, strerror(errno)); + return (0); + } + } + else + return (0); + + if (ioctl(fd, DKIOCGETBLOCKSIZE, &devblklen) < 0) { + (void)close(fd); + return (0); + } + else { + (void)close(fd); + return (devblklen); + } +} + diff --git a/diskdev_cmds/disklib/pathnames.h b/diskdev_cmds/disklib/pathnames.h new file mode 100644 index 0000000..59cd945 --- /dev/null +++ b/diskdev_cmds/disklib/pathnames.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/5/93 + */ + +#include + +#define _PATH_DTMP "/etc/dtmp" +#define _PATH_DUMPDATES "/etc/dumpdates" +#define _PATH_LOCK "/tmp/dumplockXXXXXX" +#define _PATH_RMT "rmt" diff --git a/diskdev_cmds/disklib/preen.c b/diskdev_cmds/disklib/preen.c new file mode 100644 index 0000000..f7128e0 --- /dev/null +++ b/diskdev_cmds/disklib/preen.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_OS_OSX +struct part { + struct part *next; /* forward link of partitions on disk */ + char *name; /* device name */ + char *fsname; /* mounted filesystem name */ + long auxdata; /* auxillary data for application */ +} *badlist, **badnext = &badlist; + +struct disk { + char *name; /* disk base name */ + struct disk *next; /* forward link for list of disks */ + struct part *part; /* head of list of partitions on disk */ + int pid; /* If != 0, pid of proc working on */ +} *disks; + +int nrun, ndisks; +char hotroot; + +static void addpart (char *name, char *fsname, long auxdata); +static struct disk *finddisk (char *name); +static char *rawname (char *name); +static int startdisk (struct disk *dk, + int (*checkit)(char *, char *, long, int)); +static char *unrawname (char *name); +char* blockcheck (char *name); + +int +checkfstab(preen, maxrun, docheck, chkit) + int preen; + int maxrun; + int (*docheck)(struct fstab *); + int (*chkit)(char *, char *, long, int); +{ + register struct fstab *fsp; + register struct disk *dk, *nextdisk; + register struct part *pt; + int ret, pid, retcode, passno, sumstatus, status; + long auxdata; + char *name; + + sumstatus = 0; + for (passno = 1; passno <= 2; passno++) { + if (setfsent() == 0) { + fprintf(stderr, "Can't open checklist file: %s\n", + _PATH_FSTAB); + return (8); + } + while ((fsp = getfsent()) != 0) { + if ((auxdata = (*docheck)(fsp)) == 0) + continue; + if (preen == 0 || + (passno == 1 && fsp->fs_passno == 1)) { + if ((name = blockcheck(fsp->fs_spec)) != 0) { + if ((sumstatus = (*chkit)(name, + fsp->fs_file, auxdata, 0)) != 0) + return (sumstatus); + } else if (preen) + return (8); + } else if (passno == 2 && fsp->fs_passno > 1) { + if ((name = blockcheck(fsp->fs_spec)) == NULL) { + fprintf(stderr, "BAD DISK NAME %s\n", + fsp->fs_spec); + sumstatus |= 8; + continue; + } + addpart(name, fsp->fs_file, auxdata); + } + } + if (preen == 0) + return (0); + } + if (preen) { + if (maxrun == 0) + maxrun = ndisks; + if (maxrun > ndisks) + maxrun = ndisks; + nextdisk = disks; + for (passno = 0; passno < maxrun; ++passno) { + while ((ret = startdisk(nextdisk, chkit)) && nrun > 0) + sleep(10); + if (ret) + return (ret); + nextdisk = nextdisk->next; + } + while ((pid = wait(&status)) != -1) { + for (dk = disks; dk; dk = dk->next) + if (dk->pid == pid) + break; + if (dk == 0) { + printf("Unknown pid %d\n", pid); + continue; + } + if (WIFEXITED(status)) + retcode = WEXITSTATUS(status); + else + retcode = 0; + if (WIFSIGNALED(status)) { + printf("%s (%s): EXITED WITH SIGNAL %d\n", + dk->part->name, dk->part->fsname, + WTERMSIG(status)); + retcode = 8; + } + if (retcode != 0) { + sumstatus |= retcode; + *badnext = dk->part; + badnext = &dk->part->next; + dk->part = dk->part->next; + *badnext = NULL; + } else + dk->part = dk->part->next; + dk->pid = 0; + nrun--; + if (dk->part == NULL) + ndisks--; + + if (nextdisk == NULL) { + if (dk->part) { + while ((ret = startdisk(dk, chkit)) && + nrun > 0) + sleep(10); + if (ret) + return (ret); + } + } else if (nrun < maxrun && nrun < ndisks) { + for ( ;; ) { + if ((nextdisk = nextdisk->next) == NULL) + nextdisk = disks; + if (nextdisk->part != NULL && + nextdisk->pid == 0) + break; + } + while ((ret = startdisk(nextdisk, chkit)) && + nrun > 0) + sleep(10); + if (ret) + return (ret); + } + } + } + if (sumstatus) { + if (badlist == 0) + return (sumstatus); + fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", + badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); + for (pt = badlist; pt; pt = pt->next) + fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, + pt->next ? ", " : "\n"); + return (sumstatus); + } + (void)endfsent(); + return (0); +} + +static struct disk * +finddisk(name) + char *name; +{ + register struct disk *dk, **dkp; + register char *p; + size_t len; + + for (len = strlen(name), p = name + len - 1; p >= name; --p) + if (isdigit(*p)) { + len = p - name + 1; + break; + } + + for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { + if (strncmp(dk->name, name, len) == 0 && + dk->name[len] == 0) + return (dk); + } + if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + dk = *dkp; + if ((dk->name = malloc(len + 1)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + (void)strncpy(dk->name, name, len); + dk->name[len] = '\0'; + dk->part = NULL; + dk->next = NULL; + dk->pid = 0; + ndisks++; + return (dk); +} + +static void +addpart(name, fsname, auxdata) + char *name, *fsname; + long auxdata; +{ + struct disk *dk = finddisk(name); + register struct part *pt, **ppt = &dk->part; + + for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) + if (strcmp(pt->name, name) == 0) { + printf("%s in fstab more than once!\n", name); + return; + } + if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + pt = *ppt; + if ((pt->name = strdup(name)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + if ((pt->fsname = strdup(fsname)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + pt->next = NULL; + pt->auxdata = auxdata; +} + +static int +startdisk(dk, checkit) + register struct disk *dk; + int (*checkit)(char *, char *, long, int); +{ + register struct part *pt = dk->part; + + dk->pid = fork(); + if (dk->pid < 0) { + perror("fork"); + return (8); + } + if (dk->pid == 0) + exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); + nrun++; + return (0); +} + +char * +blockcheck(char* origname) { + struct stat stslash, stblock, stchar; + char *newname, *raw; + int retried = 0; + + hotroot = 0; + if (stat("/", &stslash) < 0) { + perror("/"); + printf("Can't stat root\n"); + return (origname); + } + newname = origname; +retry: + if (stat(newname, &stblock) < 0) { + perror(newname); + printf("Can't stat %s\n", newname); + return (origname); + } + if ((stblock.st_mode & S_IFMT) == S_IFBLK) { + if (stslash.st_dev == stblock.st_rdev) + hotroot++; + raw = rawname(newname); + if (stat(raw, &stchar) < 0) { + perror(raw); + printf("Can't stat %s\n", raw); + return (origname); + } + if ((stchar.st_mode & S_IFMT) == S_IFCHR) { + return (raw); + } else { + printf("%s is not a character device\n", raw); + return (origname); + } + } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { + newname = unrawname(newname); + retried++; + goto retry; + } + /* + * Not a block or character device, just return name and + * let the user decide whether to use it. + */ + return (origname); +} + +static char * +unrawname(name) + char *name; +{ + char *dp; + struct stat stb; + size_t dp_len; + + if ((dp = strrchr(name, '/')) == 0) + return (name); + if (stat(name, &stb) < 0) + return (name); + if ((stb.st_mode & S_IFMT) != S_IFCHR) + return (name); + if (dp[1] != 'r') + return (name); + dp_len = strlen(&dp[2]) + 1; + (void)memmove(&dp[1], &dp[2], dp_len); + return (name); +} + +static char * +rawname(name) + char *name; +{ + static char rawbuf[32]; + char *dp; + + if ((dp = strrchr(name, '/')) == 0) + return (0); + *dp = 0; + (void)strncpy(rawbuf, name, sizeof(rawbuf)); + *dp = '/'; + (void)strlcat(rawbuf, "/r", sizeof(rawbuf)); + (void)strlcat(rawbuf, &dp[1], sizeof(rawbuf)); + return (rawbuf); +} + +#endif /* TARGET_OS_OSX */ + diff --git a/diskdev_cmds/disklib/vfslist.c b/diskdev_cmds/disklib/vfslist.c new file mode 100644 index 0000000..6ecafcd --- /dev/null +++ b/diskdev_cmds/disklib/vfslist.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * 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. + */ + + +#include +#include +#include +#include + +int checkvfsname __P((const char *, const char **)); +const char **makevfslist __P((char *)); +static int skipvfs; + +int +checkvfsname(vfsname, vfslist) + const char *vfsname; + const char **vfslist; +{ + + if (vfslist == NULL) + return (0); + while (*vfslist != NULL) { + if (strcmp(vfsname, *vfslist) == 0) + return (skipvfs); + ++vfslist; + } + return (!skipvfs); +} + +const char ** +makevfslist(fslist) + char *fslist; +{ + const char **av; + int i; + char *nextcp; + + if (fslist == NULL) + return (NULL); + if (fslist[0] == 'n' && fslist[1] == 'o') { + fslist += 2; + skipvfs = 1; + } + for (i = 0, nextcp = fslist; *nextcp; nextcp++) + if (*nextcp == ',') + i++; + if ((av = malloc((size_t)(i + 2) * sizeof(char *))) == NULL) { + warn(NULL); + return (NULL); + } + nextcp = fslist; + i = 0; + av[i++] = nextcp; + while ((nextcp = strchr(nextcp, ',')) != NULL) { + *nextcp++ = '\0'; + av[i++] = nextcp; + } + av[i++] = NULL; + return (av); +} diff --git a/diskdev_cmds/edquota.tproj/edquota.8 b/diskdev_cmds/edquota.tproj/edquota.8 new file mode 100644 index 0000000..fd52b56 --- /dev/null +++ b/diskdev_cmds/edquota.tproj/edquota.8 @@ -0,0 +1,184 @@ +.\" Copyright (c) 1983, 1990, 1993, 2002 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Robert Elz at The University of Melbourne. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with 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. +.\" +.\" @(#)edquota.8 8.2 (Berkeley) 4/27/95 +.\" +.Dd "March 28, 2002" +.Dt EDQUOTA 8 +.Os +.Sh NAME +.Nm edquota +.Nd edit user quotas +.Sh SYNOPSIS +.Nm edquota +.Op Fl u +.Op Fl p Ar proto-username +.Ar username ... +.Nm edquota +.Fl g +.Op Fl p Ar proto-groupname +.Ar groupname ... +.Nm edquota +.Fl t +.Op Fl u +.Nm edquota +.Fl t +.Fl g +.Sh DESCRIPTION +.Nm Edquota +is a quota editor. +By default, or if the +.Fl u +flag is specified, +one or more users may be specified on the command line. +For each user a temporary file is created +with an ASCII representation of the current +disk quotas for that user. +The list of filesystems with user quotas is determined by +scanning the mounted filesystems for a +.Pa .quota.ops.user +file located at its root. +An editor is invoked on the ASCII file. +The editor invoked is +.Xr vi 1 +unless the environment variable +.Ev EDITOR +specifies otherwise. +.Pp +The quotas may then be modified, new quotas added, etc. +Setting a quota to zero indicates that no quota should be imposed. +Setting a hard limit to one indicates that no allocations should +be permitted. +Setting a soft limit to one with a hard limit of zero +indicates that allocations should be permitted on +only a temporary basis (see +.Fl t +below). +The current usage information in the file is for informational purposes; +only the hard and soft limits can be changed. +.Pp +On leaving the editor, +.Nm edquota +reads the temporary file and modifies the binary +quota files to reflect the changes made. +The binary quota file, +.Pa .quota.user +is stored at the root of the filesystem. +The default filename and root location for the user +quotas cannot be overridden. +.Pp +If the +.Fl p +flag is specified, +.Nm edquota +will duplicate the quotas of the prototypical user +specified for each user specified. +This is the normal mechanism used to +initialize quotas for groups of users. +.Pp +If the +.Fl g +flag is specified, +.Nm edquota +is invoked to edit the quotas of +one or more groups specified on the command line. +The list of filesystems with group quotas is determined by +scanning the mounted filesystems for a +.Pa .quota.ops.group +file located at its root. +Similarly, the binary quota file, +.Pa .quota.group +is stored at the root of the filesystem. +The default filename and root location for group +quotas cannot be overridden. +The +.Fl p +flag can be specified in conjunction with +the +.Fl g +flag to specify a prototypical group +to be duplicated among the listed set of groups. +.Pp +Users are permitted to exceed their soft limits +for a grace period that may be specified per filesystem. +Once the grace period has expired, +the soft limit is enforced as a hard limit. +The default grace period for a filesystem is specified in +.Pa /usr/include/sys/quota.h . +The +.Fl t +flag can be used to change the grace period. +By default, or when invoked with the +.Fl u +flag, the grace period is set for each filesystem with a +.Pa .quota.ops.user +file located at its root. +When invoked with the +.Fl g +flag, the grace period is +set for each filesystem with a +.Pa .quota.ops.group +file located at its root. +The grace period may be specified in days, hours, minutes, or seconds. +Setting a grace period to zero indicates that the default +grace period should be imposed. +Setting a grace period to one second indicates that no +grace period should be granted. +.Pp +Only the super-user may edit quotas. +.Sh FILES +Each of the following quota files is located at the root of the +mounted filesystem. The mount option files are empty files +whose existence indicates that quotas are to be enabled +for that filesystem. The binary data files will be +created by edquota, if they don't already exist. +.Pp +.Bl -tag -width .quota.ops.group -compact +.It Pa .quota.user +data file containing user quotas +.It Pa .quota.group +data file containing group quotas +.It Pa .quota.ops.user +mount option file used to enable user quotas +.It Pa .quota.ops.group +mount option file used to enable group quotas +.El +.Sh SEE ALSO +.Xr quota 1 , +.Xr quotactl 2 , +.Xr quotacheck 8 , +.Xr quotaon 8 , +.Xr repquota 8 +.Sh DIAGNOSTICS +Various messages about inaccessible files; self-explanatory. diff --git a/diskdev_cmds/edquota.tproj/edquota.c b/diskdev_cmds/edquota.tproj/edquota.c new file mode 100644 index 0000000..6dad1cb --- /dev/null +++ b/diskdev_cmds/edquota.tproj/edquota.c @@ -0,0 +1,1228 @@ +/* + * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1980, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 + +#ifndef lint +__unused static char copyright[] = +"@(#) Copyright (c) 1980, 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +__unused static char sccsid[] = "@(#)edquota.c 8.3 (Berkeley) 4/27/95"; +#endif /* not lint */ + +/* + * Disk quota editor. + */ +#include +#include +#include +#ifdef __APPLE__ +#include +#endif /* __APPLE__ */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +#ifdef __APPLE__ +#include +#endif /* __APPLE__ */ + +char *qfname = QUOTAFILENAME; +char *qfextension[] = INITQFNAMES; +char *quotagroup = QUOTAGROUP; +char tmpfil[] = _PATH_TMP; + +#ifdef __APPLE__ +u_int32_t quotamagic[MAXQUOTAS] = INITQMAGICS; +#endif /* __APPLE__ */ + +struct quotause { + struct quotause *next; + long flags; + struct dqblk dqblk; + char fsname[MAXPATHLEN + 1]; + char qfname[1]; /* actually longer */ +} *getprivs(); +#define FOUND 0x01 + +int alldigits __P((char *)); +int cvtatos __P((time_t, char *, time_t *)); +int editit __P((char *)); +void freeprivs __P((struct quotause *)); +int getentry __P((char *, int)); +int hasquota __P((struct statfs *, int, char **)); +void putprivs __P((uid_t, int, struct quotause *)); +int readprivs __P((struct quotause *, int)); +int readtimes __P((struct quotause *, int)); +void usage __P((void)); +int writeprivs __P((struct quotause *, int, char *, int)); +int writetimes __P((struct quotause *, int, int)); + +#ifdef __APPLE__ +int qfinit(int, struct statfs *, int); +int qflookup(int, uid_t, int, struct dqblk *); +int qfupdate(int, uid_t, int, struct dqblk *); +#endif /* __APPLE__ */ + + +int +main(argc, argv) + register char **argv; + int argc; +{ + register struct quotause *qup, *protoprivs, *curprivs; + extern char *optarg; + extern int optind; + register uid_t id, protoid; + register int quotatype, tmpfd; + char *protoname = NULL, ch; + int tflag = 0, pflag = 0; + + if (argc < 2) + usage(); + if (getuid()) { + fprintf(stderr, "edquota: permission denied\n"); + exit(1); + } + quotatype = USRQUOTA; + + while ((ch = getopt(argc, argv, "ugtp:")) != EOF) { + switch(ch) { + case 'p': + protoname = optarg; + pflag++; + break; + case 'g': + quotatype = GRPQUOTA; + break; + case 'u': + quotatype = USRQUOTA; + break; + case 't': + tflag++; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (pflag) { + if ((protoid = getentry(protoname, quotatype)) == -1) + exit(1); + protoprivs = getprivs(protoid, quotatype); +#ifdef __APPLE__ + if (protoprivs == (struct quotause *) NULL) + exit(0); +#endif /* __APPLE__ */ + for (qup = protoprivs; qup; qup = qup->next) { + qup->dqblk.dqb_btime = 0; + qup->dqblk.dqb_itime = 0; + } + while (argc-- > 0) { + if ((id = getentry(*argv++, quotatype)) == -1) + continue; + /* + * Set the ID in each disk quota block to match + * the ID it's supposed to go with. + */ + for (qup = protoprivs; qup; qup = qup->next) { + qup->dqblk.dqb_id = id; + } + putprivs(id, quotatype, protoprivs); + } + exit(0); + } + tmpfd = mkstemp(tmpfil); + fchown(tmpfd, getuid(), getgid()); + if (tflag) { + protoprivs = getprivs(0, quotatype); +#ifdef __APPLE__ + if (protoprivs == (struct quotause *) NULL) + exit(0); +#endif /* __APPLE__ */ + if (writetimes(protoprivs, tmpfd, quotatype) == 0) + exit(1); + if (editit(tmpfil)) { + /* + * Re-open tmpfil to be editor independent. + */ + close(tmpfd); + tmpfd = open(tmpfil, O_RDWR, 0); + if (tmpfd < 0) { + freeprivs(protoprivs); + unlink(tmpfil); + exit(1); + } + if (readtimes(protoprivs, tmpfd)) + putprivs(0, quotatype, protoprivs); + } + freeprivs(protoprivs); + exit(0); + } + for ( ; argc > 0; argc--, argv++) { + if ((id = getentry(*argv, quotatype)) == -1) + continue; + curprivs = getprivs(id, quotatype); +#ifdef __APPLE__ + if (curprivs == (struct quotause *) NULL) + exit(0); +#endif /* __APPLE__ */ + + + if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) { + freeprivs(curprivs); + continue; + } + if (editit(tmpfil)) { + /* + * Re-open tmpfil to be editor independent. + */ + close(tmpfd); + tmpfd = open(tmpfil, O_RDWR, 0); + if (tmpfd < 0) { + freeprivs(curprivs); + unlink(tmpfil); + exit(1); + } + if (readprivs(curprivs, tmpfd)) + putprivs(id, quotatype, curprivs); + } + freeprivs(curprivs); + } + close(tmpfd); + unlink(tmpfil); + exit(0); +} + +void +usage() +{ + fprintf(stderr, "%s%s%s%s", + "Usage: edquota [-u] [-p username] username ...\n", + "\tedquota -g [-p groupname] groupname ...\n", + "\tedquota [-u] -t\n", "\tedquota -g -t\n"); +#ifdef __APPLE__ + fprintf(stderr, "\nQuota file editing triggers only on filesystems with a\n"); + fprintf(stderr, "%s.%s or %s.%s file located at its root.\n", + QUOTAOPSNAME, qfextension[USRQUOTA], + QUOTAOPSNAME, qfextension[GRPQUOTA]); +#endif /* __APPLE__ */ + exit(1); +} + +/* + * This routine converts a name for a particular quota type to + * an identifier. This routine must agree with the kernel routine + * getinoquota as to the interpretation of quota types. + */ +int +getentry(name, quotatype) + char *name; + int quotatype; +{ + struct passwd *pw; + struct group *gr; + + if (alldigits(name)) + return (atoi(name)); + switch(quotatype) { + case USRQUOTA: + if ((pw = getpwnam(name)) != NULL) + return (pw->pw_uid); + fprintf(stderr, "%s: no such user\n", name); + break; + case GRPQUOTA: + if ((gr = getgrnam(name))) + return (gr->gr_gid); + fprintf(stderr, "%s: no such group\n", name); + break; + default: + fprintf(stderr, "%d: unknown quota type\n", quotatype); + break; + } + sleep(1); + return (-1); +} + +/* + * Collect the requested quota information. + */ +#ifdef __APPLE__ +struct quotause * +getprivs(id, quotatype) + register uid_t id; + int quotatype; +{ + struct statfs *fst; + register struct quotause *qup, *quptail; + struct quotause *quphead; + int qcmd, fd; + size_t qupsize; + char *qfpathname; + size_t qfpathname_len; + static int warned = 0; + int nfst, i; + extern int errno; + + + quptail = quphead = (struct quotause *)0; + qcmd = QCMD(Q_GETQUOTA, quotatype); + + nfst = getmntinfo(&fst, MNT_WAIT); + if (nfst==0) { + fprintf(stderr, "edquota: no mounted filesystems\n"); + exit(1); + } + + for (i=0; idqblk) != 0) { + if (errno == ENOTSUP && !warned) { + warned++; + fprintf(stderr, "Warning: %s\n", + "Quotas are not compiled into this kernel"); + sleep(3); + } + if ((fd = open(qfpathname, O_RDONLY)) < 0) { + fd = open(qfpathname, O_RDWR|O_CREAT, 0640); + if (fd < 0 && errno != ENOENT) { + perror(qfpathname); + free(qup); + continue; + } + fprintf(stderr, "Creating quota file %s\n", + qfpathname); + sleep(3); + (void) fchown(fd, getuid(), + getentry(quotagroup, GRPQUOTA)); + (void) fchmod(fd, 0640); + if (qfinit(fd, &fst[i], quotatype)) { + perror(qfpathname); + close(fd); + free(qup); + continue; + } + } + if (qflookup(fd, id, quotatype, &qup->dqblk) != 0) { + fprintf(stderr, "edquota: lookup error in "); + perror(qfpathname); + close(fd); + free(qup); + continue; + } + close(fd); + } + strlcpy(qup->qfname, qfpathname, qfpathname_len); // malloc'd size is correct for this + strlcpy(qup->fsname, fst[i].f_mntonname, sizeof(qup->fsname)); + + if (quphead == NULL) + quphead = qup; + else + quptail->next = qup; + quptail = qup; + qup->next = 0; + } + return (quphead); +} +#else +struct quotause * +getprivs(id, quotatype) + register long id; + int quotatype; +{ + register struct fstab *fs; + register struct quotause *qup, *quptail; + struct quotause *quphead; + int qcmd, fd; + size_t qupsize; + char *qfpathname; + size_t qfpathname_len; + static int warned = 0; + extern int errno; + + setfsent(); + quphead = (struct quotause *)0; + qcmd = QCMD(Q_GETQUOTA, quotatype); + while (fs = getfsent()) { + if (!hasquota(fs, quotatype, &qfpathname)) + continue; + qfpathname_len = strlen(qfpathname); + qupsize = sizeof(*qup) + qfpathname_len; + if ((qup = (struct quotause *)malloc(qupsize)) == NULL) { + fprintf(stderr, "edquota: out of memory\n"); + exit(2); + } + if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { + if (errno == ENOTSUP && !warned) { + warned++; + fprintf(stderr, "Warning: %s\n", + "Quotas are not compiled into this kernel"); + sleep(3); + } + if ((fd = open(qfpathname, O_RDONLY)) < 0) { + fd = open(qfpathname, O_RDWR|O_CREAT, 0640); + if (fd < 0 && errno != ENOENT) { + perror(qfpathname); + free(qup); + continue; + } + fprintf(stderr, "Creating quota file %s\n", + qfpathname); + sleep(3); + (void) fchown(fd, getuid(), + getentry(quotagroup, GRPQUOTA)); + (void) fchmod(fd, 0640); + } + lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET); + switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { + case 0: /* EOF */ + /* + * Convert implicit 0 quota (EOF) + * into an explicit one (zero'ed dqblk) + */ + bzero((caddr_t)&qup->dqblk, + sizeof(struct dqblk)); + break; + + case sizeof(struct dqblk): /* OK */ + break; + + default: /* ERROR */ + fprintf(stderr, "edquota: read error in "); + perror(qfpathname); + close(fd); + free(qup); + continue; + } + close(fd); + } + strlcpy(qup->qfname, qfpathname, qfpathname_len); // malloc'd size is correct for this + strlcpy(qup->fsname, fs->fs_file, sizeof(qup->fsname)); + + if (quphead == NULL) + quphead = qup; + else + quptail->next = qup; + quptail = qup; + qup->next = 0; + } + endfsent(); + return (quphead); +} +#endif /* __APPLE */ + +#ifdef __APPLE__ +#define ONEGIGABYTE (1024*1024*1024) +/* + * Initialize a new quota file. + */ +int +qfinit(fd, fst, type) + int fd; + struct statfs *fst; + int type; +{ + struct dqfilehdr dqhdr = {0}; + u_int64_t fs_size; + int64_t max = 0; + + /* + * Calculate the size of the hash table from the size of + * the file system. Note that the open addressing hashing + * used by the quota file assumes that this table will not + * be more than 90% full. + */ + fs_size = (u_int64_t)fst->f_blocks * (u_int64_t)fst->f_bsize; + + if (type == USRQUOTA) { + max = QF_USERS_PER_GB * (fs_size / ONEGIGABYTE); + + if (max < QF_MIN_USERS) + max = QF_MIN_USERS; + else if (max > QF_MAX_USERS) + max = QF_MAX_USERS; + } else if (type == GRPQUOTA) { + max = QF_GROUPS_PER_GB * (fs_size / ONEGIGABYTE); + + if (max < QF_MIN_GROUPS) + max = QF_MIN_GROUPS; + else if (max > QF_MAX_GROUPS) + max = QF_MAX_GROUPS; + } + /* Round up to a power of 2 */ + if (max && !powerof2(max)) { + int64_t x = max; + max = 4; + while (x>>1 != 1) { + x = x >> 1; + max = max << 1; + } + } + + (void) ftruncate(fd, (off_t)((max + 1) * sizeof(struct dqblk))); + dqhdr.dqh_magic = OSSwapHostToBigInt32(quotamagic[type]); + dqhdr.dqh_version = OSSwapHostToBigConstInt32(QF_VERSION); + dqhdr.dqh_maxentries = OSSwapHostToBigInt32((int32_t)max); + dqhdr.dqh_btime = OSSwapHostToBigConstInt32(MAX_DQ_TIME); + dqhdr.dqh_itime = OSSwapHostToBigConstInt32(MAX_IQ_TIME); + memmove(dqhdr.dqh_string, QF_STRING_TAG, strlen(QF_STRING_TAG)); + (void) lseek(fd, 0, L_SET); + (void) write(fd, &dqhdr, sizeof(dqhdr)); + + return (0); +} + +/* + * Lookup an entry in a quota file. + */ +int +qflookup(fd, id, type, dqbp) + int fd; + uid_t id; + int type; + struct dqblk *dqbp; +{ + struct dqfilehdr dqhdr; + int i, skip, last, m; + int mask; + + bzero(dqbp, sizeof(struct dqblk)); + + if (id == 0) + return (0); + + lseek(fd, 0, L_SET); + if (read(fd, &dqhdr, sizeof(struct dqfilehdr)) != sizeof(struct dqfilehdr)) + return (-1); + + /* Sanity check the quota file header. */ + if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) || + (OSSwapBigToHostInt32(dqhdr.dqh_version) > 1) || + (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) { + fprintf(stderr, "quota: invalid quota file header\n"); + return (-1); + } + + m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries); + mask = m - 1; + i = dqhash1(id, dqhashshift(m), mask); + skip = dqhash2(id, mask); + + for (last = (i + (m-1) * skip) & mask; + i != last; + i = (i + skip) & mask) { + lseek(fd, dqoffset(i), L_SET); + if (read(fd, dqbp, sizeof(struct dqblk)) < sizeof(struct dqblk)) + return (-1); + /* + * Stop when an empty entry is found + * or we encounter a matching id. + */ + if (dqbp->dqb_id == 0 || OSSwapBigToHostInt32(dqbp->dqb_id) == id) + break; + } + /* Put data in host native byte order. */ + dqbp->dqb_bhardlimit = OSSwapBigToHostInt64(dqbp->dqb_bhardlimit); + dqbp->dqb_bsoftlimit = OSSwapBigToHostInt64(dqbp->dqb_bsoftlimit); + dqbp->dqb_curbytes = OSSwapBigToHostInt64(dqbp->dqb_curbytes); + dqbp->dqb_ihardlimit = OSSwapBigToHostInt32(dqbp->dqb_ihardlimit); + dqbp->dqb_isoftlimit = OSSwapBigToHostInt32(dqbp->dqb_isoftlimit); + dqbp->dqb_curinodes = OSSwapBigToHostInt32(dqbp->dqb_curinodes); + dqbp->dqb_btime = OSSwapBigToHostInt32(dqbp->dqb_btime); + dqbp->dqb_itime = OSSwapBigToHostInt32(dqbp->dqb_itime); + dqbp->dqb_id = OSSwapBigToHostInt32(dqbp->dqb_id); + + return (0); +} +#endif /* __APPLE */ + + +/* + * Store the requested quota information. + */ +void +putprivs(id, quotatype, quplist) + uid_t id; + int quotatype; + struct quotause *quplist; +{ + register struct quotause *qup; + int qcmd, fd; + + qcmd = QCMD(Q_SETQUOTA, quotatype); + for (qup = quplist; qup; qup = qup->next) { + if (quotactl(qup->fsname, qcmd, id, (char *)&qup->dqblk) == 0) + continue; +#ifdef __APPLE__ + if ((fd = open(qup->qfname, O_RDWR)) < 0) { + perror(qup->qfname); + } else { + if (qfupdate(fd, id, quotatype, &qup->dqblk) != 0) { + fprintf(stderr, "edquota: "); + perror(qup->qfname); + } +#else + if ((fd = open(qup->qfname, O_WRONLY)) < 0) { + perror(qup->qfname); + } else { + lseek(fd, + (off_t)(id * (long)sizeof (struct dqblk)), L_SET); + if (write(fd, &qup->dqblk, sizeof (struct dqblk)) != + sizeof (struct dqblk)) { + fprintf(stderr, "edquota: "); + perror(qup->qfname); + } +#endif /* __APPLE */ + close(fd); + } + } +} + +#ifdef __APPLE__ +/* + * Update an entry in a quota file. + */ +int +qfupdate(fd, id, type, dqbp) + int fd; + uid_t id; + int type; + struct dqblk *dqbp; +{ + struct dqblk dqbuf; + struct dqfilehdr dqhdr; + int i, skip, last, m; + unsigned int mask; + + if (id == 0) + return (0); + + lseek(fd, 0, L_SET); + if (read(fd, &dqhdr, sizeof(struct dqfilehdr)) != sizeof(struct dqfilehdr)) + return (-1); + + /* Sanity check the quota file header. */ + if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) || + (OSSwapBigToHostInt32(dqhdr.dqh_version) > QF_VERSION) || + (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) { + fprintf(stderr, "quota: invalid quota file header\n"); + return (EINVAL); + } + + m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries); + mask = m - 1; + i = dqhash1(id, dqhashshift(m), mask); + skip = dqhash2(id, mask); + + for (last = (i + (m-1) * skip) & mask; + i != last; + i = (i + skip) & mask) { + lseek(fd, dqoffset(i), L_SET); + if (read(fd, &dqbuf, sizeof(struct dqblk)) < sizeof(struct dqblk)) + return (-1); + /* + * Stop when an empty entry is found + * or we encounter a matching id. + */ + if (dqbuf.dqb_id == 0 || OSSwapBigToHostInt32(dqbuf.dqb_id) == id) { + /* Convert buffer to big endian before writing. */ + struct dqblk tblk; + + tblk.dqb_bhardlimit = OSSwapHostToBigInt64(dqbp->dqb_bhardlimit); + tblk.dqb_bsoftlimit = OSSwapHostToBigInt64(dqbp->dqb_bsoftlimit); + tblk.dqb_curbytes = OSSwapHostToBigInt64(dqbp->dqb_curbytes); + tblk.dqb_ihardlimit = OSSwapHostToBigInt32(dqbp->dqb_ihardlimit); + tblk.dqb_isoftlimit = OSSwapHostToBigInt32(dqbp->dqb_isoftlimit); + tblk.dqb_curinodes = OSSwapHostToBigInt32(dqbp->dqb_curinodes); + tblk.dqb_btime = OSSwapHostToBigInt32((int)dqbp->dqb_btime); + tblk.dqb_itime = OSSwapHostToBigInt32((int)dqbp->dqb_itime); + tblk.dqb_id = OSSwapHostToBigInt32(id); + + lseek(fd, dqoffset(i), L_SET); + if (write(fd, &tblk, sizeof (struct dqblk)) != + sizeof (struct dqblk)) { + return (-1); + } + return (0); + } + } + errno = ENOSPC; + return (-1); +} +#endif /* __APPLE__ */ + +/* + * Take a list of priviledges and get it edited. + */ +int +editit(tmpfile) + char *tmpfile; +{ + int omask; + int pid, stat; + extern char *getenv(); + + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); + top: + if ((pid = fork()) < 0) { + extern int errno; + + if (errno == EPROCLIM) { + fprintf(stderr, "You have too many processes\n"); + return(0); + } + if (errno == EAGAIN) { + sleep(1); + goto top; + } + perror("fork"); + return (0); + } + if (pid == 0) { + register char *ed; + struct passwd *pwd = getpwuid(getuid()); + gid_t newgid = getgid(); + + setgid(newgid); + if (pwd) initgroups(pwd->pw_name, newgid); + setuid(getuid()); + sigsetmask(omask); + + if ((ed = getenv("EDITOR")) == (char *)0) + ed = _PATH_VI; + execlp(ed, ed, tmpfile, NULL); + perror(ed); + exit(1); + } + waitpid(pid, &stat, 0); + sigsetmask(omask); + if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) + return (0); + return (1); +} + +/* + * Convert a quotause list to an ASCII file. + */ +int +writeprivs(quplist, outfd, name, quotatype) + struct quotause *quplist; + int outfd; + char *name; + int quotatype; +{ + register struct quotause *qup; + FILE *fd; + + ftruncate(outfd, 0); + lseek(outfd, 0, L_SET); + if ((fd = fdopen(dup(outfd), "w")) == NULL) { + fprintf(stderr, "edquota: "); + perror(tmpfil); + exit(1); + } + fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name); + for (qup = quplist; qup; qup = qup->next) { +#ifdef __APPLE__ + fprintf(fd, "%s: %s %qd, limits (soft = %qd, hard = %qd)\n", + qup->fsname, "1K blocks in use:", + qup->dqblk.dqb_curbytes / 1024, + qup->dqblk.dqb_bsoftlimit / 1024, + qup->dqblk.dqb_bhardlimit / 1024); +#else + fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n", + qup->fsname, "blocks in use:", + dbtob(qup->dqblk.dqb_curblocks) / 1024, + dbtob(qup->dqblk.dqb_bsoftlimit) / 1024, + dbtob(qup->dqblk.dqb_bhardlimit) / 1024); +#endif /* __APPLE__ */ + + fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n", + "\tinodes in use:", qup->dqblk.dqb_curinodes, + qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit); + } + fclose(fd); + return (1); +} + +/* + * Merge changes to an ASCII file into a quotause list. + */ +int +readprivs(quplist, infd) + struct quotause *quplist; + int infd; +{ + register struct quotause *qup; + FILE *fd; + int cnt; + register char *cp; + struct dqblk dqblk; + char fsp[BUFSIZ], line1[BUFSIZ], line2[BUFSIZ]; + + lseek(infd, 0, L_SET); + fd = fdopen(dup(infd), "r"); + if (fd == NULL) { + fprintf(stderr, "Can't re-read temp file!!\n"); + return (0); + } + /* + * Discard title line, then read pairs of lines to process. + */ + (void) fgets(line1, sizeof (line1), fd); + while (fgets(line1, sizeof (line1), fd) != NULL && + fgets(line2, sizeof (line2), fd) != NULL) { + cp = strstr(line1, ": 1K blocks in use:"); + if (cp == NULL) { + fprintf(stderr, "%s: bad format for line\n", line1); + return 0; + } + /* Copy up to the template text */ + strlcpy(fsp, line1, cp - line1 + 1); + /* And point cp right after it. */ + cp = line1 + strlen(fsp) + 1; +#ifdef __APPLE__ + /* We expect input to be in 1K blocks */ + cnt = sscanf(cp, + " 1K blocks in use: %qd, limits (soft = %qd, hard = %qd)", + &dqblk.dqb_curbytes, &dqblk.dqb_bsoftlimit, + &dqblk.dqb_bhardlimit); + if (cnt != 3) { + fprintf(stderr, "%s:%s: bad format\n", fsp, cp); + return (0); + } + + /* convert default 1K blocks to byte count */ + dqblk.dqb_curbytes = dqblk.dqb_curbytes * 1024; + dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit * 1024; + dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit * 1024; +#else + cnt = sscanf(cp, + " blocks in use: %d, limits (soft = %d, hard = %d)", + &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit, + &dqblk.dqb_bhardlimit); + if (cnt != 3) { + fprintf(stderr, "%s:%s: bad format\n", fsp, cp); + return (0); + } + dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024); + dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024); + dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024); +#endif /* __APPLE__ */ + + if ((cp = strtok(line2, "\n")) == NULL) { + fprintf(stderr, "%s: %s: bad format\n", fsp, line2); + return (0); + } + cnt = sscanf(cp, + "\tinodes in use: %d, limits (soft = %d, hard = %d)", + &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit, + &dqblk.dqb_ihardlimit); + if (cnt != 3) { + fprintf(stderr, "%s: %s: bad format\n", fsp, line2); + return (0); + } + for (qup = quplist; qup; qup = qup->next) { + if (strcmp(fsp, qup->fsname)) + continue; + /* + * Cause time limit to be reset when the quota + * is next used if previously had no soft limit + * or were under it, but now have a soft limit + * and are over it. + */ +#ifdef __APPLE__ + if (dqblk.dqb_bsoftlimit && + qup->dqblk.dqb_curbytes >= dqblk.dqb_bsoftlimit && + (qup->dqblk.dqb_bsoftlimit == 0 || + qup->dqblk.dqb_curbytes < + qup->dqblk.dqb_bsoftlimit)) + qup->dqblk.dqb_btime = 0; +#else + if (dqblk.dqb_bsoftlimit && + qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit && + (qup->dqblk.dqb_bsoftlimit == 0 || + qup->dqblk.dqb_curblocks < + qup->dqblk.dqb_bsoftlimit)) + qup->dqblk.dqb_btime = 0; +#endif /* __APPLE__ */ + if (dqblk.dqb_isoftlimit && + qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit && + (qup->dqblk.dqb_isoftlimit == 0 || + qup->dqblk.dqb_curinodes < + qup->dqblk.dqb_isoftlimit)) + qup->dqblk.dqb_itime = 0; + qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit; + qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit; + qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; + qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; + qup->flags |= FOUND; +#ifdef __APPLE__ + if (dqblk.dqb_curbytes == qup->dqblk.dqb_curbytes && + dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) + break; +#else + if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && + dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) + break; +#endif /* __APPLE__ */ + fprintf(stderr, + "%s: cannot change current allocation\n", fsp); + break; + } + } + fclose(fd); + /* + * Disable quotas for any filesystems that have not been found. + */ + for (qup = quplist; qup; qup = qup->next) { + if (qup->flags & FOUND) { + qup->flags &= ~FOUND; + continue; + } + qup->dqblk.dqb_bsoftlimit = 0; + qup->dqblk.dqb_bhardlimit = 0; + qup->dqblk.dqb_isoftlimit = 0; + qup->dqblk.dqb_ihardlimit = 0; + } + return (1); +} + +/* + * Convert a quotause list to an ASCII file of grace times. + */ +int +writetimes(quplist, outfd, quotatype) + struct quotause *quplist; + int outfd; + int quotatype; +{ + register struct quotause *qup; + char *cvtstoa(); + FILE *fd; + + ftruncate(outfd, 0); + lseek(outfd, 0, L_SET); + if ((fd = fdopen(dup(outfd), "w")) == NULL) { + fprintf(stderr, "edquota: "); + perror(tmpfil); + exit(1); + } + fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n"); + fprintf(fd, "Grace period before enforcing soft limits for %ss:\n", + qfextension[quotatype]); + for (qup = quplist; qup; qup = qup->next) { + fprintf(fd, "%s: block grace period: %s, ", + qup->fsname, cvtstoa(qup->dqblk.dqb_btime)); + fprintf(fd, "file grace period: %s\n", + cvtstoa(qup->dqblk.dqb_itime)); + } + fclose(fd); + return (1); +} + +/* + * Merge changes of grace times in an ASCII file into a quotause list. + */ +int +readtimes(quplist, infd) + struct quotause *quplist; + int infd; +{ + register struct quotause *qup; + FILE *fd; + int cnt; + register char *cp; + time_t itime, btime, iseconds, bseconds; + char *fsp, bunits[10], iunits[10], line1[BUFSIZ]; + + lseek(infd, 0, L_SET); + fd = fdopen(dup(infd), "r"); + if (fd == NULL) { + fprintf(stderr, "Can't re-read temp file!!\n"); + return (0); + } + /* + * Discard two title lines, then read lines to process. + */ + (void) fgets(line1, sizeof (line1), fd); + (void) fgets(line1, sizeof (line1), fd); + while (fgets(line1, sizeof (line1), fd) != NULL) { + if ((fsp = strtok(line1, " \t:")) == NULL) { + fprintf(stderr, "%s: bad format\n", line1); + return (0); + } + if ((cp = strtok((char *)0, "\n")) == NULL) { + fprintf(stderr, "%s: %s: bad format\n", fsp, + &fsp[strlen(fsp) + 1]); + return (0); + } + cnt = sscanf(cp, + " block grace period: %ld %s file grace period: %ld %s", + &btime, bunits, &itime, iunits); + if (cnt != 4) { + fprintf(stderr, "%s:%s: bad format\n", fsp, cp); + return (0); + } + if (cvtatos(btime, bunits, &bseconds) == 0) + return (0); + if (cvtatos(itime, iunits, &iseconds) == 0) + return (0); + for (qup = quplist; qup; qup = qup->next) { + if (strcmp(fsp, qup->fsname)) + continue; + qup->dqblk.dqb_btime = (uint32_t) bseconds; + qup->dqblk.dqb_itime = (uint32_t) iseconds; + qup->flags |= FOUND; + break; + } + } + fclose(fd); + /* + * reset default grace periods for any filesystems + * that have not been found. + */ + for (qup = quplist; qup; qup = qup->next) { + if (qup->flags & FOUND) { + qup->flags &= ~FOUND; + continue; + } + qup->dqblk.dqb_btime = 0; + qup->dqblk.dqb_itime = 0; + } + return (1); +} + +/* + * Convert seconds to ASCII times. + */ +char * +cvtstoa(time) + time_t time; +{ + static char buf[20]; + + if (time % (24 * 60 * 60) == 0) { + time /= 24 * 60 * 60; + snprintf(buf, sizeof(buf), "%d day%s", (int)time, time == 1 ? "" : "s"); + } else if (time % (60 * 60) == 0) { + time /= 60 * 60; + snprintf(buf, sizeof(buf), "%d hour%s", (int)time, time == 1 ? "" : "s"); + } else if (time % 60 == 0) { + time /= 60; + snprintf(buf, sizeof(buf), "%d minute%s", (int)time, time == 1 ? "" : "s"); + } else + snprintf(buf, sizeof(buf), "%d second%s", (int)time, time == 1 ? "" : "s"); + return (buf); +} + +/* + * Convert ASCII input times to seconds. + */ +int +cvtatos(time, units, seconds) + time_t time; + char *units; + time_t *seconds; +{ + + if (bcmp(units, "second", 6) == 0) + *seconds = time; + else if (bcmp(units, "minute", 6) == 0) + *seconds = time * 60; + else if (bcmp(units, "hour", 4) == 0) + *seconds = time * 60 * 60; + else if (bcmp(units, "day", 3) == 0) + *seconds = time * 24 * 60 * 60; + else { + printf("%s: bad units, specify %s\n", units, + "days, hours, minutes, or seconds"); + return (0); + } + return (1); +} + +/* + * Free a list of quotause structures. + */ +void +freeprivs(quplist) + struct quotause *quplist; +{ + register struct quotause *qup, *nextqup; + + for (qup = quplist; qup; qup = nextqup) { + nextqup = qup->next; + free(qup); + } +} + +/* + * Check whether a string is completely composed of digits. + */ +int +alldigits(s) + register char *s; +{ + register int c; + + c = *s++; + do { + if (!isdigit(c)) + return (0); + } while ((c = *s++)); + return (1); +} + +/* + * Check to see if a particular quota is to be enabled. + */ +#ifdef __APPLE__ +int +hasquota(fst, type, qfnamep) + register struct statfs *fst; + int type; + char **qfnamep; +{ + struct stat sb; + static char initname, usrname[100], grpname[100]; + static char buf[BUFSIZ]; + + if (!initname) { + snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname); + snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname); + initname = 1; + } + + /* + We only support the default path to the + on disk quota files. + */ + + (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, + QUOTAOPSNAME, qfextension[type] ); + if (stat(buf, &sb) != 0) { + /* There appears to be no mount option file */ + return(0); + } + + (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]); + *qfnamep = buf; + return (1); +} +#else +hasquota(fs, type, qfnamep) + register struct fstab *fs; + int type; + char **qfnamep; +{ + register char *opt; + char *cp, *index(), *strtok(); + static char initname, usrname[100], grpname[100]; + static char buf[BUFSIZ]; + + if (!initname) { + snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname); + snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname); + initname = 1; + } + strlcpy(buf, fs->fs_mntops, sizeof(buf)); + for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { + if (cp = index(opt, '=')) + *cp++ = '\0'; + if (type == USRQUOTA && strcmp(opt, usrname) == 0) + break; + if (type == GRPQUOTA && strcmp(opt, grpname) == 0) + break; + } + if (!opt) + return (0); + if (cp) { + *qfnamep = cp; + return (1); + } + (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); + *qfnamep = buf; + return (1); +} +#endif /* __APPLE */ diff --git a/diskdev_cmds/edquota.tproj/pathnames.h b/diskdev_cmds/edquota.tproj/pathnames.h new file mode 100644 index 0000000..f1aef1c --- /dev/null +++ b/diskdev_cmds/edquota.tproj/pathnames.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#undef _PATH_TMP +#define _PATH_TMP "/tmp/EdP.aXXXXX" diff --git a/diskdev_cmds/edt_fstab/edt_fstab.c b/diskdev_cmds/edt_fstab/edt_fstab.c new file mode 100644 index 0000000..42a53fe --- /dev/null +++ b/diskdev_cmds/edt_fstab/edt_fstab.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018-2020 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// edt_fstab.c +// +// Created on 12/11/2018. +// + +#include + +#include "edt_fstab.h" + +#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) + +/* Some APFS specific goop */ +#include +#include +#include +#include +#include +#include + +char boot_container[EDTVolumePropertySize] = {}; +char data_volume[EDTVolumePropertySize] = {}; + +static uint32_t edt_os_environment = EDT_OS_ENV_MAIN; + +const char * +get_boot_container(uint32_t *os_envp) +{ + kern_return_t err; + CFMutableDictionaryRef fs_info = NULL; + CFStringRef container = NULL; + CFDataRef os_env = NULL; + + // already got the boot container + if (strnlen(boot_container, sizeof(boot_container)) > 0) { + *os_envp = edt_os_environment; + return boot_container; + } + + fs_info = IORegistryEntryFromPath(kIOMasterPortDefault, kEDTFilesystemEntry); + if (fs_info == IO_OBJECT_NULL) { + fprintf(stderr, "failed to get filesystem info\n"); + return NULL; + } + + // lookup the OS environment being booted, assumes main OS upon failure + os_env = IORegistryEntryCreateCFProperty(fs_info, kEDTOSEnvironment, kCFAllocatorDefault, 0); + if (os_env) { + CFDataGetBytes(os_env, CFRangeMake(0, CFDataGetLength(os_env)), (UInt8*)(&edt_os_environment)); + CFRelease(os_env); + } + IOObjectRelease(fs_info); + *os_envp = edt_os_environment; + + // lookup the boot container + err = APFSContainerGetBootDevice(&container); + if (!err) { + strcpy(boot_container, _PATH_DEV); + CFStringGetCString(container, + boot_container + strlen(_PATH_DEV), + EDTVolumePropertySize - strlen(_PATH_DEV), + kCFStringEncodingUTF8); + CFRelease(container); + return boot_container; + } else { + // just a warning if not booting the main OS (rdar://48693021) + fprintf(stderr, "%sfailed to get boot device - %s\n", + (edt_os_environment == EDT_OS_ENV_MAIN) ? "" : "warning: ", + strerror(err_get_code(err))); + return NULL; + } +} + +const char * +get_data_volume(void) +{ + const char *container = NULL; + CFMutableArrayRef matches = NULL; + OSStatus status; + + // already got the data volume + if (strnlen(data_volume, sizeof(data_volume)) > 0) { + return data_volume; + } + + // get the boot container + if (strlen(boot_container) > 0) { + container = boot_container; + } else { + uint32_t os_env; + container = get_boot_container(&os_env); + } + if (!container) { + return NULL; + } + + // lookup the data volume + status = APFSVolumeRoleFind(container, APFS_VOL_ROLE_DATA, &matches); + if (status) { + // just a warning if not booting the main OS + fprintf(stderr, "%sfailed to lookup data volume - %s\n", + (edt_os_environment == EDT_OS_ENV_MAIN) ? "" : "warning: ", + strerror(err_get_code(status))); + return NULL; + } else if (CFArrayGetCount(matches) > 1) { + fprintf(stderr, "found multiple data volumes\n"); + CFRelease(matches); + return NULL; + } else { + CFStringGetCString(CFArrayGetValueAtIndex(matches, 0), + data_volume, + EDTVolumePropertySize, + kCFStringEncodingUTF8); + CFRelease(matches); + return data_volume; + } +} + +int +get_boot_manifest_hash(char *boot_manifest_hash, size_t boot_manifest_hash_len) +{ + kern_return_t err = 0; + io_registry_entry_t chosen; + CFDataRef bm_hash = NULL; + size_t bm_hash_size; + uint8_t bm_hash_buf[EDTVolumePropertyMaxSize] = {}; + const char *hexmap = "0123456789ABCDEF"; + + chosen = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/chosen"); + if (chosen == IO_OBJECT_NULL) { + fprintf(stderr, "failed to get chosen info\n"); + return ENOENT; + } + + bm_hash = IORegistryEntryCreateCFProperty(chosen, CFSTR("boot-manifest-hash"), kCFAllocatorDefault, 0); + if (!bm_hash) { + fprintf(stderr, "failed to get boot-manifest-hash\n"); + IOObjectRelease(chosen); + return ENOENT; + } else { + bm_hash_size = CFDataGetLength(bm_hash); + CFDataGetBytes(bm_hash, CFRangeMake(0, bm_hash_size), bm_hash_buf); + + if (boot_manifest_hash_len < (bm_hash_size * 2 + 1)) { + err = EINVAL; + } else { + // hexdump the hash into input buffer + for (size_t i = 0; i < (2 * bm_hash_size); i++) + *boot_manifest_hash++ = hexmap[(bm_hash_buf[i / 2] >> ((i % 2) ? 0 : 4)) & 0xf]; + *boot_manifest_hash = '\0'; + } + CFRelease(bm_hash); + IOObjectRelease(chosen); + } + + return err; +} +#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */ diff --git a/diskdev_cmds/edt_fstab/edt_fstab.h b/diskdev_cmds/edt_fstab/edt_fstab.h new file mode 100644 index 0000000..1fd4926 --- /dev/null +++ b/diskdev_cmds/edt_fstab/edt_fstab.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2020 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// edt_fstab.h +// +// Created on 12/11/2018. +// + +#ifndef edt_fstab_h +#define edt_fstab_h + +#include + +#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) +#define RAMDISK_FS_SPEC "ramdisk" + +/* + * get_boot_container, get_data_volume - return the bsd name of the requested + * device upon success. Null otherwise. + */ +const char *get_boot_container(uint32_t *os_env); +const char *get_data_volume(void); + +int get_boot_manifest_hash(char *boot_manifest_hash, size_t boot_manifest_hash_len); +#endif + +#endif /* edt_fstab_h */ diff --git a/diskdev_cmds/fdisk.tproj/auto.c b/diskdev_cmds/fdisk.tproj/auto.c new file mode 100644 index 0000000..155f7ab --- /dev/null +++ b/diskdev_cmds/fdisk.tproj/auto.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Auto partitioning code. + */ + +#include +#include +#include +#include +#include +#include +#include "disk.h" +#include "mbr.h" +#include "auto.h" + +int AUTO_boothfs __P((disk_t *, mbr_t *)); +int AUTO_hfs __P((disk_t *, mbr_t *)); +int AUTO_dos __P((disk_t *, mbr_t *)); +int AUTO_raid __P((disk_t *, mbr_t *)); + +/* The default style is the first one in the list */ +struct _auto_style { + char *style_name; + int (*style_fn)(disk_t *, mbr_t *); + char *description; +} style_fns[] = { + {"boothfs", AUTO_boothfs, "8Mb boot plus HFS+ root partition"}, + {"hfs", AUTO_hfs, "Entire disk as one HFS+ partition"}, + {"dos", AUTO_dos, "Entire disk as one DOS partition"}, + {"raid", AUTO_raid, "Entire disk as one 0xAC partition"}, + {0,0} +}; + +void +AUTO_print_styles(FILE *f) +{ + struct _auto_style *fp; + int i; + + for (i=0, fp = &style_fns[0]; fp->style_name != NULL; i++, fp++) { + fprintf(f, " %-10s %s%s\n", fp->style_name, fp->description, (i==0) ? " (default)" : ""); + } +} + + +int +AUTO_init(disk_t *disk, char *style, mbr_t *mbr) +{ + struct _auto_style *fp; + + for (fp = &style_fns[0]; fp->style_name != NULL; fp++) { + /* If style is NULL, use the first (default) style */ + if (style == NULL || strcasecmp(style, fp->style_name) == 0) { + return (*fp->style_fn)(disk, mbr); + } + } + warnx("No such auto-partition style %s", style); + return AUTO_ERR; +} + + +static int +use_whole_disk(disk_t *disk, unsigned char id, mbr_t *mbr) +{ + MBR_clear(mbr); + mbr->part[0].id = id; + mbr->part[0].bs = 63; + mbr->part[0].ns = disk->real->size - 63; + PRT_fix_CHS(disk, &mbr->part[0], 0); + return AUTO_OK; +} + +/* DOS style: one partition for the whole disk */ +int +AUTO_dos(disk_t *disk, mbr_t *mbr) +{ + int cc; + cc = use_whole_disk(disk, 0x0C, mbr); + if (cc == AUTO_OK) { + mbr->part[0].flag = DOSACTIVE; + } + return cc; +} + +/* HFS style: one partition for the whole disk */ +int +AUTO_hfs(disk_t *disk, mbr_t *mbr) +{ + int cc; + cc = use_whole_disk(disk, 0xAF, mbr); + if (cc == AUTO_OK) { + mbr->part[0].flag = DOSACTIVE; + } + return cc; +} + +/* One boot partition, one HFS+ root partition */ +int +AUTO_boothfs (disk_t *disk, mbr_t *mbr) +{ + /* Check disk size. */ + if (disk->real->size < 16 * 2048) { + errx(1, "Disk size must be greater than 16Mb"); + return AUTO_ERR; + } + + MBR_clear(mbr); + + /* 8MB boot partition */ + mbr->part[0].id = 0xAB; + mbr->part[0].bs = 63; + mbr->part[0].ns = 8 * 1024 * 2; + mbr->part[0].flag = DOSACTIVE; + PRT_fix_CHS(disk, &mbr->part[0], 0); + + /* Rest of the disk for rooting */ + mbr->part[1].id = 0xAF; + mbr->part[1].bs = (mbr->part[0].bs + mbr->part[0].ns); + mbr->part[1].ns = disk->real->size - mbr->part[0].ns - 63; + PRT_fix_CHS(disk, &mbr->part[1], 1); + + return AUTO_OK; +} + + + +/* RAID style: one 0xAC partition for the whole disk */ +int +AUTO_raid(disk_t *disk, mbr_t *mbr) +{ + return use_whole_disk(disk, 0xAC, mbr); +} + diff --git a/diskdev_cmds/fdisk.tproj/auto.h b/diskdev_cmds/fdisk.tproj/auto.h new file mode 100644 index 0000000..c9259d4 --- /dev/null +++ b/diskdev_cmds/fdisk.tproj/auto.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "mbr.h" + +/* Prototypes */ +void AUTO_print_styles __P((FILE *)); +int AUTO_init __P((disk_t *, char *, mbr_t *)); + +#define AUTO_OK 0 +#define AUTO_ERR -1 diff --git a/diskdev_cmds/fdisk.tproj/cmd.c b/diskdev_cmds/fdisk.tproj/cmd.c new file mode 100644 index 0000000..41cee77 --- /dev/null +++ b/diskdev_cmds/fdisk.tproj/cmd.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "disk.h" +#include "misc.h" +#include "user.h" +#include "part.h" +#include "cmd.h" +#include "auto.h" +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) + +int +Xerase(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + bzero(mbr->part, sizeof(mbr->part)); + mbr->signature = MBR_SIGNATURE; + return (CMD_DIRTY); +} + +int +Xreinit(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + /* Copy template MBR */ + MBR_make(tt); + MBR_parse(disk, offset, 0, mbr); + + MBR_init(disk, mbr); + + /* Tell em we did something */ + printf("In memory copy is initialized to:\n"); + printf("Offset: %d\t", offset); + MBR_print(mbr); + printf("Use 'write' to update disk.\n"); + + return (CMD_DIRTY); +} + +int +Xauto(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + if (cmd->args[0] == '\0') { + printf("usage: auto

\120 + \121 + \122 + \123 + \124 + \125 + \126 + \127 + \130 + \131 + \132 + \133 + \134 + \134 + \135 + \136 + \136 + \137 + \137 + \137 + \140 + \141 + \142 + \143 + \144 + \145 + \146 + \147 + \150 + \151 + \152 + \153 + \154 + \155 + \156 + \157 +