From ef8ad44b9b5d9c6d8c0fa5b5494f449fb6717387 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 22 Jun 2009 22:51:34 +0000 Subject: [PATCH] system_cmds-496.tar.gz --- Makefile | 29 +- Makefile.include | 5 - README.rtf | 32 - ac.tproj/Makefile | 3 + accton.tproj/Makefile | 5 +- accton.tproj/accton.8 | 75 +- accton.tproj/accton.c | 68 +- arch.tproj/Makefile | 7 +- arch.tproj/arch.1 | 6 +- arch.tproj/arch.m | 9 + arch.tproj/machine.1 | 5 - at.tproj/Makefile | 4 +- atrun.tproj/Makefile | 4 +- audit.tproj/Makefile | 10 - audit.tproj/audit.1 | 43 - audit.tproj/audit.c | 91 - audit.tproj/auditd_control.defs | 25 - auditd.tproj/Makefile | 17 - auditd.tproj/audit_triggers.defs | 1 - auditd.tproj/audit_warn.c | 208 -- auditd.tproj/auditd.8 | 48 - auditd.tproj/auditd.c | 792 ------ auditd.tproj/auditd.h | 51 - auditd.tproj/auditd_control.defs | 43 - auditd.tproj/rc.audit | 25 - bootlog.tproj/Makefile | 6 + bootlog.tproj/bootlog.c | 2 +- chkpasswd.tproj/Makefile | 14 +- chkpasswd.tproj/chkpasswd.8 | 9 +- chkpasswd.tproj/chkpasswd.pam | 5 + chkpasswd.tproj/ds_passwd.c | 302 -- chkpasswd.tproj/netinfo_passwd.c | 354 --- chkpasswd.tproj/od_passwd.c | 108 + chkpasswd.tproj/pam_passwd.c | 78 + chkpasswd.tproj/passwd.c | 126 +- chpass.tproj/Makefile | 10 +- chpass.tproj/chpass.c | 2 +- chpass.tproj/chpass.h | 2 +- chpass.tproj/edit.c | 6 +- chpass.tproj/open_directory.c | 22 +- chpass.tproj/table.c | 24 +- dirhelper.tproj/Makefile | 7 +- dirhelper.tproj/dirhelper.c | 86 +- dmesg.tproj/Makefile | 4 +- dp_notify_lib/Makefile | 2 +- dpkg/control | 4 - dynamic_pager.tproj/Makefile | 12 +- .../com.apple.dynamic_pager.plist | 4 + dynamic_pager.tproj/dynamic_pager.8 | 17 +- dynamic_pager.tproj/dynamic_pager.c | 117 +- fs_usage.tproj/Makefile | 5 +- fs_usage.tproj/fs_usage.c | 866 ++++-- getconf.tproj/Makefile | 4 +- getconf.tproj/getconf.1 | 33 +- getconf.tproj/getconf.c | 10 +- getconf.tproj/progenv.gperf | 2 +- getty.tproj/Makefile | 8 + getty.tproj/extern.h | 2 +- getty.tproj/main.c | 6 +- getty.tproj/subr.c | 5 +- hostinfo.tproj/Makefile | 3 + hostinfo.tproj/hostinfo.8 | 7 +- iostat.tproj/Makefile | 4 + iostat.tproj/iostat.c | 6 +- kgmon.tproj/Makefile | 48 - kgmon.tproj/kgmon.8 | 128 - kgmon.tproj/kgmon.c | 591 ---- kmodload.tproj/Makefile | 51 - kmodload.tproj/c++rem3.c | 2209 --------------- kmodload.tproj/c++rem3.h | 45 - kmodload.tproj/kld_patch.c | 2478 ----------------- kmodload.tproj/kld_patch.h | 56 - kmodload.tproj/kmodload.8 | 103 - kmodload.tproj/kmodload.c | 756 ----- kmodload.tproj/kmodsyms.8 | 119 - kmodload.tproj/vers_rsrc.c | 425 --- kmodload.tproj/vers_rsrc.h | 40 - kmodstat.tproj/Makefile | 48 - kmodstat.tproj/kmodstat.8 | 71 - kmodstat.tproj/kmodstat.c | 206 -- kmodunload.tproj/Makefile | 48 - kmodunload.tproj/kmodunload.8 | 77 - kmodunload.tproj/kmodunload.c | 212 -- kvm_mkdb.tproj/Makefile | 44 - kvm_mkdb.tproj/extern.h | 61 - kvm_mkdb.tproj/kvm_mkdb.c | 144 - kvm_mkdb.tproj/nlist.c | 215 -- kvm_mkdb.tproj/testdb.c | 136 - latency.tproj/Makefile | 5 +- latency.tproj/latency.c | 63 +- login.tproj/Makefile | 22 +- login.tproj/login.1 | 87 +- login.tproj/login.c | 1722 +++++++----- login.tproj/login.h | 37 + login.tproj/login.pam | 11 + login.tproj/login_audit.c | 204 ++ login.tproj/pathnames.h | 61 +- makekey.tproj/Makefile | 3 + mkfile.tproj/Makefile | 3 + mkfile.tproj/mkfile.c | 9 +- newgrp.tproj/Makefile | 4 +- newgrp.tproj/newgrp.1 | 43 +- newgrp.tproj/newgrp.c | 13 +- nologin.tproj/Makefile | 10 +- .../kvm_mkdb.8 => nologin.tproj/nologin.5 | 98 +- nologin.tproj/nologin.8 | 34 +- nologin.tproj/nologin.c | 51 + nologin.tproj/nologin.sh | 38 - nvram.tproj/Makefile | 3 + nvram.tproj/nvram.c | 100 +- pagesize.tproj/pagesize.1 | 16 +- pagesize.tproj/pagesize.sh | 6 +- passwd.tproj/Makefile | 12 +- passwd.tproj/file_passwd.c | 3 +- passwd.tproj/od_passwd.c | 13 +- passwd.tproj/pam_passwd.c | 75 + passwd.tproj/passwd.1 | 61 +- passwd.tproj/passwd.c | 35 +- passwd.tproj/passwd.pam | 5 + pwd_mkdb.tproj/Makefile | 5 +- reboot.tproj/Makefile | 5 +- reboot.tproj/boot_hp300.8 | 117 - reboot.tproj/boot_i386.8 | 126 - reboot.tproj/boot_sparc.8 | 89 - reboot.tproj/boot_tahoe.8 | 152 - reboot.tproj/boot_vax.8 | 322 --- reboot.tproj/reboot.c | 24 +- sa.tproj/Makefile | 7 +- sa.tproj/db.c | 211 ++ sa.tproj/extern.h | 36 +- sa.tproj/main.c | 166 +- sa.tproj/pdb.c | 267 +- sa.tproj/sa.8 | 121 +- sa.tproj/usrdb.c | 195 +- sadc.tproj/Makefile | 5 +- sadc.tproj/sadc.h | 81 +- sar.tproj/Makefile | 5 +- sar.tproj/sar.c | 4 +- sar.tproj/sar.h | 160 +- sc_usage.tproj/Makefile | 6 +- sc_usage.tproj/sc_usage.c | 147 +- sc_usage.tproj/trace.codes | 929 +++--- shutdown.tproj/Makefile | 5 +- shutdown.tproj/shutdown.c | 39 +- sync.tproj/Makefile | 4 + sync.tproj/sync.8 | 41 +- sync.tproj/sync.c | 47 +- sysctl.tproj/Makefile | 3 + sysctl.tproj/pathconf.c | 252 -- sysctl.tproj/sysctl.c | 22 +- update.tproj/Makefile | 9 - update.tproj/com.apple.update.plist | 14 - update.tproj/update.8 | 25 +- update.tproj/update.c | 44 - update.tproj/update.sb | 18 - vifs.tproj/Makefile | 3 + vipw.tproj/Makefile | 3 + vm_stat.tproj/Makefile | 3 + vm_stat.tproj/vm_stat.c | 144 +- zdump.tproj/Makefile | 3 + zdump.tproj/zdump.8 | 23 +- zdump.tproj/zdump.c | 29 +- zic.tproj/Makefile | 7 +- zic.tproj/zic.8 | 50 +- zic.tproj/zic.c | 7 +- zprint.tproj/Makefile | 3 + zprint.tproj/zprint.c | 7 + 167 files changed, 4709 insertions(+), 14324 deletions(-) delete mode 100644 Makefile.include delete mode 100644 README.rtf delete mode 100644 audit.tproj/Makefile delete mode 100644 audit.tproj/audit.1 delete mode 100644 audit.tproj/audit.c delete mode 100644 audit.tproj/auditd_control.defs delete mode 100644 auditd.tproj/Makefile delete mode 100644 auditd.tproj/audit_triggers.defs delete mode 100644 auditd.tproj/audit_warn.c delete mode 100644 auditd.tproj/auditd.8 delete mode 100644 auditd.tproj/auditd.c delete mode 100644 auditd.tproj/auditd.h delete mode 100644 auditd.tproj/auditd_control.defs delete mode 100644 auditd.tproj/rc.audit create mode 100644 chkpasswd.tproj/chkpasswd.pam delete mode 100644 chkpasswd.tproj/ds_passwd.c delete mode 100644 chkpasswd.tproj/netinfo_passwd.c create mode 100644 chkpasswd.tproj/od_passwd.c create mode 100644 chkpasswd.tproj/pam_passwd.c delete mode 100644 dpkg/control delete mode 100644 kgmon.tproj/Makefile delete mode 100644 kgmon.tproj/kgmon.8 delete mode 100644 kgmon.tproj/kgmon.c delete mode 100644 kmodload.tproj/Makefile delete mode 100644 kmodload.tproj/c++rem3.c delete mode 100644 kmodload.tproj/c++rem3.h delete mode 100644 kmodload.tproj/kld_patch.c delete mode 100644 kmodload.tproj/kld_patch.h delete mode 100644 kmodload.tproj/kmodload.8 delete mode 100644 kmodload.tproj/kmodload.c delete mode 100644 kmodload.tproj/kmodsyms.8 delete mode 100644 kmodload.tproj/vers_rsrc.c delete mode 100644 kmodload.tproj/vers_rsrc.h delete mode 100644 kmodstat.tproj/Makefile delete mode 100644 kmodstat.tproj/kmodstat.8 delete mode 100644 kmodstat.tproj/kmodstat.c delete mode 100644 kmodunload.tproj/Makefile delete mode 100644 kmodunload.tproj/kmodunload.8 delete mode 100644 kmodunload.tproj/kmodunload.c delete mode 100644 kvm_mkdb.tproj/Makefile delete mode 100644 kvm_mkdb.tproj/extern.h delete mode 100644 kvm_mkdb.tproj/kvm_mkdb.c delete mode 100644 kvm_mkdb.tproj/nlist.c delete mode 100644 kvm_mkdb.tproj/testdb.c create mode 100644 login.tproj/login.h create mode 100644 login.tproj/login.pam create mode 100644 login.tproj/login_audit.c rename kvm_mkdb.tproj/kvm_mkdb.8 => nologin.tproj/nologin.5 (55%) create mode 100644 nologin.tproj/nologin.c delete mode 100644 nologin.tproj/nologin.sh create mode 100644 passwd.tproj/pam_passwd.c create mode 100644 passwd.tproj/passwd.pam delete mode 100644 reboot.tproj/boot_hp300.8 delete mode 100644 reboot.tproj/boot_i386.8 delete mode 100644 reboot.tproj/boot_sparc.8 delete mode 100644 reboot.tproj/boot_tahoe.8 delete mode 100644 reboot.tproj/boot_vax.8 create mode 100644 sa.tproj/db.c delete mode 100644 sysctl.tproj/pathconf.c diff --git a/Makefile b/Makefile index e370300..67d0eba 100644 --- a/Makefile +++ b/Makefile @@ -2,24 +2,21 @@ Project = system_cmds Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) -SubProjects = dynamic_pager.tproj ac.tproj accton.tproj arch.tproj\ - bootlog.tproj\ - dmesg.tproj\ - getconf.tproj getty.tproj hostinfo.tproj iostat.tproj\ - login.tproj makekey.tproj\ - mkfile.tproj newgrp.tproj nvram.tproj passwd.tproj pwd_mkdb.tproj\ - reboot.tproj sync.tproj sysctl.tproj\ - update.tproj vipw.tproj vifs.tproj zic.tproj zdump.tproj vm_stat.tproj\ - zprint.tproj latency.tproj sc_usage.tproj fs_usage.tproj\ - sadc.tproj sar.tproj sa.tproj \ - dp_notify_lib nologin.tproj pagesize.tproj +SubProjects = ac.tproj accton.tproj arch.tproj bootlog.tproj \ + dmesg.tproj dp_notify_lib dynamic_pager.tproj fs_usage.tproj \ + getconf.tproj getty.tproj hostinfo.tproj iostat.tproj \ + latency.tproj login.tproj makekey.tproj mkfile.tproj \ + newgrp.tproj nologin.tproj nvram.tproj pagesize.tproj \ + passwd.tproj pwd_mkdb.tproj reboot.tproj sa.tproj sadc.tproj \ + sar.tproj sc_usage.tproj sync.tproj sysctl.tproj update.tproj \ + vipw.tproj vifs.tproj vm_stat.tproj zdump.tproj zic.tproj \ + zprint.tproj ifeq "$(Embedded)" "NO" -SubProjects += at.tproj atrun.tproj\ - auditd.tproj audit.tproj\ - chkpasswd.tproj chpass.tproj\ - dirhelper.tproj\ - shutdown.tproj +SubProjects += at.tproj atrun.tproj \ + chkpasswd.tproj chpass.tproj dirhelper.tproj shutdown.tproj endif +Extra_LD_Flags += -lcurses -lutil + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/Makefile.include b/Makefile.include deleted file mode 100644 index 4d583ef..0000000 --- a/Makefile.include +++ /dev/null @@ -1,5 +0,0 @@ -## -## Temporary flags for static Teflon builds -## - -CHFLAGS = true # until we really have chflags on our system diff --git a/README.rtf b/README.rtf deleted file mode 100644 index ee40118..0000000 --- a/README.rtf +++ /dev/null @@ -1,32 +0,0 @@ -{\rtf1\mac\ansicpg10000\cocoartf100 -{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;\f2\fswiss\fcharset77 Helvetica-Oblique; -} -{\colortbl;\red255\green255\blue255;} -\margl120\margr120\vieww4640\viewh7420\viewkind0 -\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\ql\qnatural - -\f0\b\fs24 \cf0 system_cmds failures\ - -\f1\b0 \ -cgore\ - \ -\ -iostat\ - names.c missing\ - \ -kdump\ - /sys/kern/syscalls.c missing\ -\ -kvm_mkdb\ - KERNBASE undeclared\ -\ -mach_swapon\ - not found\ - \ -savecore\ - KERNBASE undeclared\ -\ -vmstat\ - -\f2\i not found\ -} diff --git a/ac.tproj/Makefile b/ac.tproj/Makefile index 9147142..3977061 100644 --- a/ac.tproj/Makefile +++ b/ac.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/sbin CFILES = ac.c MANPAGES = ac.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/accton.tproj/Makefile b/accton.tproj/Makefile index 36aed17..6a0e9a1 100644 --- a/accton.tproj/Makefile +++ b/accton.tproj/Makefile @@ -4,5 +4,8 @@ Install_Dir = /usr/sbin CFILES = accton.c MANPAGES = accton.8 -include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID +Extra_LD_Flags = -dead_strip +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/accton.tproj/accton.8 b/accton.tproj/accton.8 index 17841a3..039b257 100644 --- a/accton.tproj/accton.8 +++ b/accton.tproj/accton.8 @@ -1,51 +1,42 @@ -.\" Copyright (c) 1993 Christopher G. Demetriou -.\" All rights reserved. +.\" $FreeBSD: src/usr.sbin/accton/accton.8,v 1.13 2004/04/16 09:31:17 brueffer Exp $ .\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $Id: accton.8,v 1.2 2005/11/03 05:42:25 lindak Exp $ -.\" -.Dd October 18, 1993 +.Dd May 21, 1993 .Dt ACCTON 8 -.Os BSD 4 +.Os .Sh NAME .Nm accton .Nd enable/disable system accounting .Sh SYNOPSIS -.Nm accton -.Op Ar file +.Nm +.Op Ar acctfile .Sh DESCRIPTION -With an argument naming an existing -.Ar file , -.Nm accton -causes system accounting information for every process executed -to be placed at the end of the file. If no argument is given, -accounting is turned off. +The +.Nm +utility is used +for switching system accounting on or off. +If called with the argument +.Ar acctfile , +system accounting is enabled. +The +.Ar acctfile +specified must exist prior to starting system accounting, or +.Nm +will return an error. +A record of every process that is started by the +.Xr execve 2 +system call and then later exits the system is stored in +.Ar acctfile . +The +.Xr sa 8 +command may be used to examine the accounting records. +If no arguments are given, system accounting is disabled. +.Sh FILES +.Bl -tag -width /var/account/acct +.It Pa /var/account/acct +default accounting file +.El .Sh SEE ALSO .Xr lastcomm 1 , -.Xr acct 5 -.Sh HISTORY -The -.Nm accton -command has existed nearly forever, but this man page is new. +.Xr acct 2 , +.Xr acct 5 , +.Xr sa 8 diff --git a/accton.tproj/accton.c b/accton.tproj/accton.c index 5cb2456..1fb83ff 100644 --- a/accton.tproj/accton.c +++ b/accton.tproj/accton.c @@ -1,26 +1,3 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. @@ -33,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with 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. @@ -54,34 +27,35 @@ * SUCH DAMAGE. */ -#include +#if 0 #ifndef lint -__unused static char copyright[] = +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 -__unused static char sccsid[] = "@(#)accton.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)accton.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/usr.sbin/accton/accton.c,v 1.8 2004/08/07 04:19:37 imp Exp $"); #include -#include -#include -#include +#include #include +#include #include +#include -void usage __P((void)); +static void usage(void); int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { int ch; - while ((ch = getopt(argc, argv, "")) != EOF) + while ((ch = getopt(argc, argv, "")) != -1) switch(ch) { case '?': default: @@ -91,19 +65,13 @@ main(argc, argv) argv += optind; switch(argc) { - case 0: - if (acct(NULL)) { - (void)fprintf(stderr, - "accton: %s\n", strerror(errno)); - exit(1); - } + case 0: + if (acct(NULL)) + err(1, NULL); break; case 1: - if (acct(*argv)) { - (void)fprintf(stderr, - "accton: %s: %s\n", *argv, strerror(errno)); - exit(1); - } + if (acct(*argv)) + err(1, "%s", *argv); break; default: usage(); @@ -111,7 +79,7 @@ main(argc, argv) exit(0); } -void +static void usage() { (void)fprintf(stderr, "usage: accton [file]\n"); diff --git a/arch.tproj/Makefile b/arch.tproj/Makefile index 7f48b66..7b0f0ea 100644 --- a/arch.tproj/Makefile +++ b/arch.tproj/Makefile @@ -6,13 +6,16 @@ Extra_Frameworks = -framework Foundation MANPAGES = arch.1 machine.1 -Extra_CC_Flags = -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\" +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\" include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make HELPERDIR = /AppleInternal/Developer/Tools after_install: @-$(RM) -f $(DSTROOT)$(INSTALLDIR)/machine - $(LN) -h $(DSTROOT)$(Install_Dir)/arch $(DSTROOT)$(Install_Dir)/machine + $(LN) -fh $(DSTROOT)$(Install_Dir)/arch $(DSTROOT)$(Install_Dir)/machine $(INSTALL_DIRECTORY) -d $(DSTROOT)$(HELPERDIR) $(INSTALL_SCRIPT) arch_helper.pl $(DSTROOT)$(HELPERDIR) diff --git a/arch.tproj/arch.1 b/arch.tproj/arch.1 index dcae9ef..2d12478 100644 --- a/arch.tproj/arch.1 +++ b/arch.tproj/arch.1 @@ -59,7 +59,7 @@ By default, the operating system will select the architecture that most closely matches the processor type. This means that an intel architecture is selected on intel processors and a powerpc architecture is selected on powerpc processors. -A 64-bit architecuture is preferred over a 32-bit architecture on a 64-bit +A 64-bit architecture is preferred over a 32-bit architecture on a 64-bit processor, while only 32-bit architectures can run on a 32-bit processor. .Pp When the most natural architecture is unavailable, the operating system will @@ -71,7 +71,7 @@ Otherwise, no architecture is run, and an error results. .Pp The .Nm arch -command can be use to alter the operating system's normal selection order. +command can be used to alter the operating system's normal selection order. The most common use is to select the 32-bit architecture on a 64-bit processor, even if a 64-bit architecture is available. .Pp @@ -106,7 +106,7 @@ The .Ar prog argument is the command to run, followed by any arguments to pass to the command. -It can be a full or partial path, while a lone name will be lookup in the user's +It can be a full or partial path, while a lone name will be looked up in the user's command search path. .Pp If no architectures are specified on the command line, the diff --git a/arch.tproj/arch.m b/arch.tproj/arch.m index eeeece6..68ffa9b 100644 --- a/arch.tproj/arch.m +++ b/arch.tproj/arch.m @@ -36,6 +36,7 @@ #include #include #include +#include #ifndef ARCH_PROG #define ARCH_PROG "arch" @@ -47,6 +48,7 @@ #define CPUCOUNT(c) ((c)->ptr - (c)->buf) +#if !TARGET_OS_EMBEDDED static NSMutableDictionary *ArchDict; static NSString *KeyExecPath = @"ExecutablePath"; static NSString *KeyPlistVersion = @"PropertyListVersion"; @@ -75,6 +77,7 @@ static StrInt initArches[] = { {"x86_64", CPU_TYPE_X86_64}, {NULL, 0} }; +#endif /* !TARGET_OS_EMBEDDED */ /* * arch - perform the original behavior of the arch and machine commands. @@ -97,6 +100,7 @@ arch(int archcmd) exit(0); } +#if !TARGET_OS_EMBEDDED /* * spawnIt - run the posix_spawn command. count is the number of CPU types * in the prefs array. pflag is non-zero to call posix_spawnp; zero means to @@ -544,6 +548,7 @@ init(CPU *cpu) } initCPU(cpu); } +#endif /* !TARGET_OS_EMBEDDED */ /* the main() routine */ int @@ -551,7 +556,9 @@ main(int argc, char **argv, char **environ) { const char *prog = getprogname(); int my_name_is_arch; +#if !TARGET_OS_EMBEDDED CPU cpu; +#endif if(strcmp(prog, MACHINE_PROG) == 0) { if(argc > 1) @@ -562,6 +569,7 @@ main(int argc, char **argv, char **environ) arch(1); /* the "arch" command with no arguments was called */ } +#if !TARGET_OS_EMBEDDED /* set up Objective C autorelease pool */ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; init(&cpu); /* initialize */ @@ -573,4 +581,5 @@ main(int argc, char **argv, char **environ) /* should never get here */ [pool release]; errx(1, "returned from spawn"); +#endif /* !TARGET_OS_EMBEDDED */ } diff --git a/arch.tproj/machine.1 b/arch.tproj/machine.1 index 0a81d22..139c2ec 100644 --- a/arch.tproj/machine.1 +++ b/arch.tproj/machine.1 @@ -47,8 +47,3 @@ command displays the machine type. .Sh SEE ALSO .Xr arch 1 , .Xr make 1 -.Sh HISTORY -The -.Nm machine -command is -.Ud . diff --git a/at.tproj/Makefile b/at.tproj/Makefile index cf7e3f7..2704d3a 100644 --- a/at.tproj/Makefile +++ b/at.tproj/Makefile @@ -7,10 +7,12 @@ MANPAGES = at.1 PROJECT_HEADERS = privs.h pathnames.h -Extra_CC_Flags = -D__FBSDID=__RCSID -DDAEMON_UID=1 -DDAEMON_GID=1 \ +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID -DDAEMON_UID=1 -DDAEMON_GID=1 \ -DDEFAULT_AT_QUEUE='a' -DDEFAULT_BATCH_QUEUE='b' \ -DPERM_PATH=\"/usr/lib/cron/\" \ -I/System/Library/Frameworks/System.framework/PrivateHeaders +Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/atrun.tproj/Makefile b/atrun.tproj/Makefile index e364249..2d9ea9d 100644 --- a/atrun.tproj/Makefile +++ b/atrun.tproj/Makefile @@ -6,6 +6,8 @@ CFILES = atrun.c MANPAGES = atrun.8 LAUNCHD_PLISTS = com.apple.atrun.plist -Extra_CC_Flags = -DDAEMON_UID=1 -DDAEMON_GID=1 -I../at.tproj +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -DDAEMON_UID=1 -DDAEMON_GID=1 -I../at.tproj +Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/audit.tproj/Makefile b/audit.tproj/Makefile deleted file mode 100644 index 109ff57..0000000 --- a/audit.tproj/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -Project = audit -Install_Dir = /usr/sbin - -CFILES = audit.c -MANPAGES = audit.1 -USERDEFS = auditd_control.defs - -Extra_CC_Flags = -I../auditd.tproj - -include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/audit.tproj/audit.1 b/audit.tproj/audit.1 deleted file mode 100644 index 61e5949..0000000 --- a/audit.tproj/audit.1 +++ /dev/null @@ -1,43 +0,0 @@ -.\" Copyright (c) 2004, Apple Computer, Inc. All rights reserved. -.\" -.Dd Jan 24, 2004 -.Dt AUDIT 1 -.Os "Mac OS X" -.Sh NAME -.Nm audit -.Nd audit management utility -.Sh SYNOPSIS -.Nm audit -.Op Fl nst -.Op Ar file -.Sh DESCRIPTION -The -.Nm -utility controls the state of auditing system. The optional -.Ar file -operand specifies the location of the audit control input file (default -/etc/security/audit_control). -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl n -Forces the audit system to close the existing audit log file and rotate to -a new log file in a location specified in the audit control file. -.It Fl s -Specifies that the audit system should [re]synchronize its -configuration from the audit control file. A new log file will be -created. -.It Fl t -Specifies that the audit system should terminate. Log files are closed -and renamed to indicate the time of the shutdown. -.El -.Sh NOTES -The auditd(8) daemon must already be running. -.Sh FILES -.Bl -tag -width "/etc/security/audit_control" -compact -.It Pa /etc/security/audit_control -Default audit policy file used to configure the auditing system. -.El -.Sh SEE ALSO -.Xr audit_control 5 , -.Xr auditd 8 diff --git a/audit.tproj/audit.c b/audit.tproj/audit.c deleted file mode 100644 index 54b251f..0000000 --- a/audit.tproj/audit.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Program to trigger the audit daemon with a message that is either: - * - Open a new audit log file - * - Read the audit control file and take action on it - * - Close the audit log file and exit - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -mach_port_t serverPort; -mach_port_t bootstrapPort; - -void init(); -void process(int flags); - -/* - * Main routine to process command line options. - */ -int main(int argc, char **argv) -{ - char ch; - int flags = 0; - while ((ch = getopt(argc, argv, "nst")) != -1) { - switch(ch) { - - case 'n': - flags = OPEN_NEW; - break; - - case 's': - flags = READ_FILE; - break; - - case 't': - flags = CLOSE_AND_DIE; - break; - - case '?': - default: - (void)fprintf(stderr, - "usage: audit -n | -s | -t \n"); - exit(1); - } - } - init(); - process(flags); - return 0; -} - -/* - * Program initialization: - * Look up the server port and store it away. - */ -void init() -{ - if(host_get_audit_control_port(mach_host_self(), &serverPort) != KERN_SUCCESS) { - fprintf(stderr, "Cannot get auditd_control\n"); - exit(1); - } - - printf("Server port is %d\n", serverPort); -} - -/* - * Do all the real work. - * Send a message to the audit daemon and check the return code. - */ -void process(int flags) -{ - kern_return_t retcode; - retcode = auditd_control(serverPort, flags); - if(retcode != KERN_SUCCESS) { - mach_error("error doing IPC: ", retcode); - exit(1); - } - printf("Client call successful\n"); -} diff --git a/audit.tproj/auditd_control.defs b/audit.tproj/auditd_control.defs deleted file mode 100644 index a4267ee..0000000 --- a/audit.tproj/auditd_control.defs +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 2004 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 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@ - */ - -#include "../auditd.tproj/auditd_control.defs" diff --git a/auditd.tproj/Makefile b/auditd.tproj/Makefile deleted file mode 100644 index 0ef56fb..0000000 --- a/auditd.tproj/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -Project = auditd -Install_Dir = /usr/sbin - -HFILES = auditd.h -CFILES = audit_warn.c auditd.c -MANPAGES = auditd.8 -SERVERDEFS = auditd_control.defs audit_triggers.defs - -Extra_CC_Flags = -I. -Extra_LD_Flags = -lbsm -Extra_MIG_Flags = -no-cpp-precomp -R -untyped -DNO_DIRECT_RPC - -include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make - -after_install: - $(INSTALL_DIRECTORY) $(DSTROOT)/private/etc/security - install -c -m 400 rc.audit $(DSTROOT)/private/etc/security diff --git a/auditd.tproj/audit_triggers.defs b/auditd.tproj/audit_triggers.defs deleted file mode 100644 index 9fe2c35..0000000 --- a/auditd.tproj/audit_triggers.defs +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/auditd.tproj/audit_warn.c b/auditd.tproj/audit_warn.c deleted file mode 100644 index 67383be..0000000 --- a/auditd.tproj/audit_warn.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 2004 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 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@ - */ - -#include -#include -#include -#include - -#include - -/* Write to the audit log. */ -static int auditwarnlog(char *args[]) -{ - char *loc_args[9]; - int i; - pid_t pid; - loc_args[0] = AUDITWARN_SCRIPT; - for (i = 0; args[i] != NULL && i < 8; i++) { - loc_args[i+1] = args[i]; - } - loc_args[i+1] = NULL; - - pid = fork(); - if (pid == 0) { - return execv(AUDITWARN_SCRIPT, loc_args); - /* not reached */ - exit(1); - } else if (pid == -1) { - return -1; - } else { - return 0; - } -} - -/* - * Indicates that the hard limit for all filesystems - * has been exceeded count times - */ -int audit_warn_allhard(int count) -{ - char intstr[12]; - char *args[3]; - - snprintf(intstr, 12, "%d", count); - - args[0] = HARDLIM_ALL_WARN; - args[1] = intstr; - args[2] = NULL; - - return auditwarnlog(args); -} - -/* - * Indicates that the soft limit for all filesystems - * has been exceeded - */ -int audit_warn_allsoft() -{ - char *args[2]; - - args[0] = SOFTLIM_ALL_WARN; - args[1] = NULL; - - return auditwarnlog(args); -} - -/* - * Indicates that someone other than the audit daemon - * turned off auditing - * XXX Its not clear at this point how this function will - * XXX be invoked - */ -int audit_warn_auditoff() -{ - char *args[2]; - - args[0] = AUDITOFF_WARN; - args[1] = NULL; - - return auditwarnlog(args); -} - -/* - * Indicates that the audit deammn is already running - */ -int audit_warn_ebusy() -{ - char *args[2]; - - args[0] = EBUSY_WARN; - args[1] = NULL; - - return auditwarnlog(args); - -} - -/* - * Indicates that there is a problem getting the directory - * from audit_control - * - * XXX Note that we take the filename instead of a count - * XXX as the argument here (different from BSM) - */ -int audit_warn_getacdir(char *filename) -{ - char *args[3]; - - args[0] = GETACDIR_WARN; - args[1] = filename; - args[2] = NULL; - - return auditwarnlog(args); -} - - -/* - * Indicates that the hard limit for this file has been - * exceeded - */ -int audit_warn_hard(char *filename) -{ - char *args[3]; - - args[0] = HARDLIM_WARN; - args[1] = filename; - args[2] = NULL; - - return auditwarnlog(args); - -} - -/* - * Indicates that auditing could not be started - */ -int audit_warn_nostart() -{ - char *args[2]; - - args[0] = NOSTART_WARN; - args[1] = NULL; - - return auditwarnlog(args); -} - -/* - * Indicaes that an error occrred during the orderly shutdown - * of the audit daemon - */ -int audit_warn_postsigterm() -{ - char *args[2]; - - args[0] = POSTSIGTERM_WARN; - args[1] = NULL; - - return auditwarnlog(args); -} - -/* - * Indicates that the soft limit for this file has been - * exceeded - */ -int audit_warn_soft(char *filename) -{ - char *args[3]; - - args[0] = SOFTLIM_WARN; - args[1] = filename; - args[2] = NULL; - - return auditwarnlog(args); - -} - -/* - * Indicates that the temporary audit file already exists - * indicating a fatal error - */ -int audit_warn_tmpfile() -{ - char *args[2]; - - args[0] = TMPFILE_WARN; - args[1] = NULL; - - return auditwarnlog(args); -} diff --git a/auditd.tproj/auditd.8 b/auditd.tproj/auditd.8 deleted file mode 100644 index c5a9b15..0000000 --- a/auditd.tproj/auditd.8 +++ /dev/null @@ -1,48 +0,0 @@ -.\" Copyright (c) 2004, Apple Computer, Inc. All rights reserved. -.\" -.Dd Jan 24, 2004 -.Dt AUDITD 8 -.Os "Mac OS X" -.Sh NAME -.Nm auditd -.Nd audit log management daemon -.Sh SYNOPSIS -.Nm auditd -.Op Fl dhs -.Sh DESCRIPTION -The -.Nm -daemon responds to requests from the audit(1) utility and notifications -from the kernel. It manages the resulting audit log files and specified -log file locations. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl d -Starts the daemon in debug mode - it will not daemonize. -.It Fl h -Specifies that if auditing cannot be performed as specified, the system should -halt (panic). Normally, the system will attempt to proceed - although individual -processes may be stopped (see the -s option). -.It Fl s -Specifies that individual processes should stop rather than perform operations -that may cause audit records to be lost due to log file full conditions -.El -.Sh NOTE -.Pp -To assure uninterrupted audit support, the -.Nm auditd -daemon should not be started and stopped manually. Instead, the audit(1) command -should be used to inform the daemon to change state/configuration after altering -the audit_control file. -.Pp -Sending a SIGHUP to a running -.Nm auditd -daemon will force it to exit. -.Sh FILES -.Bl -tag -width "/var/audit" -compact -.It Pa /var/audit -Default directory for storing audit log files. -.El -.Sh SEE ALSO -.Xr audit 1 diff --git a/auditd.tproj/auditd.c b/auditd.tproj/auditd.c deleted file mode 100644 index 2d73e1e..0000000 --- a/auditd.tproj/auditd.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 2004 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 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@ - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "auditd_control_server.h" -#include "audit_triggers_server.h" -#define NA_EVENT_STR_SIZE 25 - -static int ret, minval; -static char *lastfile = NULL; - -static int allhardcount = 0; - -mach_port_t bp = MACH_PORT_NULL; -mach_port_t control_port = MACH_PORT_NULL; -mach_port_t signal_port = MACH_PORT_NULL; -mach_port_t port_set = MACH_PORT_NULL; - -#ifndef __BSM_INTERNAL_NOTIFY_KEY -#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" -#endif /* __BSM_INTERNAL_NOTIFY_KEY */ - -TAILQ_HEAD(, dir_ent) dir_q; - - -/* Error starting auditd */ -void fail_exit() -{ - audit_warn_nostart(); - exit(1); -} - -/* - * Free our local list of directory names - */ -void free_dir_q() -{ - struct dir_ent *dirent; - - while ((dirent = TAILQ_FIRST(&dir_q))) { - TAILQ_REMOVE(&dir_q, dirent, dirs); - free(dirent->dirname); - free(dirent); - } -} - -/* - * generate the timestamp string - */ -int getTSstr(char *buf, int len) -{ - struct timeval ts; - struct timezone tzp; - time_t tt; - - if(gettimeofday(&ts, &tzp) != 0) { - return -1; - } - tt = (time_t)ts.tv_sec; - if(!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt))) { - return -1; - } - - return 0; -} - -/* - * Concat the directory name to the given file name - * XXX We should affix the hostname also - */ -char *affixdir(char *name, struct dir_ent *dirent) -{ - char *fn; - char *curdir; - const char *sep = "/"; - - curdir = dirent->dirname; - syslog(LOG_INFO, "dir = %s\n", dirent->dirname); - - fn = (char *) malloc (strlen(curdir) + strlen(sep) - + (2 * POSTFIX_LEN) + 1); - if(fn == NULL) { - return NULL; - } - strcpy(fn, curdir); - strcat(fn, sep); - strcat(fn, name); - - return fn; -} - -/* Close the previous audit trail file */ -int close_lastfile(char *TS) -{ - char *ptr; - char *oldname; - - if(lastfile != NULL) { - oldname = (char *)malloc(strlen(lastfile) + 1); - if(oldname == NULL) { - return -1; - } - strcpy(oldname, lastfile); - - /* rename the last file -- append timestamp */ - - if((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { - *ptr = '.'; - strcpy(ptr+1, TS); - if(rename(oldname, lastfile) != 0) { - syslog(LOG_ERR, "Could not rename %s to %s \n", - oldname, lastfile); - } - else { - syslog(LOG_INFO, "renamed %s to %s \n", - oldname, lastfile); - } - } - - free(lastfile); - free(oldname); - - lastfile = NULL; - } - - return 0; -} - -/* - * Create the new file name, swap with existing audit file - */ -int swap_audit_file() -{ - char timestr[2 * POSTFIX_LEN]; - char *fn; - char TS[POSTFIX_LEN]; - struct dir_ent *dirent; - - if(getTSstr(TS, POSTFIX_LEN) != 0) { - return -1; - } - - strcpy(timestr, TS); - strcat(timestr, NOT_TERMINATED); - - /* try until we succeed */ - while((dirent = TAILQ_FIRST(&dir_q))) { - if((fn = affixdir(timestr, dirent)) == NULL) { - return -1; - } - - syslog(LOG_INFO, "New audit file is %s\n", fn); - if (open(fn, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP) < 0) { - perror("File open"); - } - else if (auditctl(fn) != 0) { - syslog(LOG_ERR, "auditctl failed! : %s\n", - strerror(errno)); - } - else { - /* Success */ - close_lastfile(TS); - lastfile = fn; - return 0; - } - - /* Tell the administrator about lack of permissions for dirent */ - audit_warn_getacdir(dirent->dirname); - - /* Try again with a different directory */ - TAILQ_REMOVE(&dir_q, dirent, dirs); - free(dirent->dirname); - free(dirent); - } - return -1; -} - -/* - * Read the audit_control file contents - */ -int read_control_file() -{ - char cur_dir[MAX_DIR_SIZE]; - struct dir_ent *dirent; - au_qctrl_t qctrl; - - /* Clear old values */ - free_dir_q(); - endac(); // force a re-read of the file the next time - - /* Post that the audit config changed */ - notify_post(__BSM_INTERNAL_NOTIFY_KEY); - - /* Read the list of directories into a local linked list */ - /* XXX We should use the reentrant interfaces once they are available */ - while(getacdir(cur_dir, MAX_DIR_SIZE) >= 0) { - dirent = (struct dir_ent *) malloc (sizeof(struct dir_ent)); - if(dirent == NULL) { - return -1; - } - - dirent->softlim = 0; - dirent->dirname = (char *) malloc (MAX_DIR_SIZE); - if(dirent->dirname == NULL) { - free(dirent); - return -1; - } - - strcpy(dirent->dirname, cur_dir); - TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); - } - - allhardcount = 0; - - if(swap_audit_file() == -1) { - syslog(LOG_ERR, "Could not swap audit file\n"); - /* - * XXX Faulty directory listing? - user should be given - * XXX an opportunity to change the audit_control file - * XXX switch to a reduced mode of auditing? - */ - return -1; - } - - /* - * XXX There are synchronization problems here - * XXX what should we do if a trigger for the earlier limit - * XXX is generated here? - */ - if(0 == (ret = getacmin(&minval))) { - - syslog(LOG_INFO, "min free = %d\n", minval); - - if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { - syslog(LOG_ERR, - "could not get audit queue settings\n"); - return -1; - } - qctrl.aq_minfree = minval; - if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { - syslog(LOG_ERR, - "could not set audit queue settings\n"); - return -1; - } - } - - return 0; -} - -/* - * Close all log files, control files, and tell the audit system. - */ -int close_all() -{ - int err_ret = 0; - char TS[POSTFIX_LEN]; - int aufd; - token_t *tok; - - /* Generate an audit record */ - if((aufd = au_open()) == -1) { - syslog(LOG_ERR, "Could not create audit shutdown event.\n"); - } else { - - if((tok = au_to_text("auditd::Audit shutdown")) != NULL) { - au_write(aufd, tok); - } - - if(au_close(aufd, 1, AUE_audit_shutdown) == -1) { - syslog(LOG_ERR, "Could not close audit shutdown event.\n"); - } - } - - /* flush contents */ - err_ret = auditctl(NULL); - if (err_ret != 0) { - syslog(LOG_ERR, "auditctl failed! : %s\n", - strerror(errno)); - err_ret = 1; - } - if(getTSstr(TS, POSTFIX_LEN) == 0) { - close_lastfile(TS); - } - if(lastfile != NULL) - free(lastfile); - - free_dir_q(); - if((remove(AUDITD_PIDFILE) == -1) || err_ret) { - syslog(LOG_ERR, "Could not unregister\n"); - audit_warn_postsigterm(); - return (1); - } - endac(); - syslog(LOG_INFO, "Finished.\n"); - return (0); -} - -/* - * When we get a signal, we are often not at a clean point. - * So, little can be done in the signal handler itself. Instead, - * we send a message to the main servicing loop to do proper - * handling from a non-signal-handler context. - */ -static void -relay_signal(int signal) -{ - mach_msg_empty_send_t msg; - - msg.header.msgh_id = signal; - msg.header.msgh_remote_port = signal_port; - msg.header.msgh_local_port = MACH_PORT_NULL; - msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); - mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), - 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); -} - -/* registering the daemon */ -int register_daemon() -{ - FILE * pidfile; - int fd; - pid_t pid; - - /* Set up the signal hander */ - if (signal(SIGTERM, relay_signal) == SIG_ERR) { - fail_exit(); - } - if (signal(SIGCHLD, relay_signal) == SIG_ERR) { - fail_exit(); - } - - if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { - audit_warn_tmpfile(); - return -1; - } - - /* attempt to lock the pid file; if a lock is present, exit */ - fd = fileno(pidfile); - if(flock(fd, LOCK_EX | LOCK_NB) < 0) { - syslog(LOG_ERR, "PID file is locked (is another auditd running?).\n"); - audit_warn_ebusy(); - return -1; - } - - pid = getpid(); - ftruncate(fd, 0); - if(fprintf(pidfile, "%u\n", pid) < 0) { - /* should not start the daemon */ - fail_exit(); - } - - fflush(pidfile); - return 0; -} - -/* - * React to input from the audit tool - */ -kern_return_t auditd_control(auditd_port, flags) - mach_port_t auditd_port; - int flags; -{ - int err_ret = 0; - - switch(flags) { - - case OPEN_NEW : - /* create a new file and swap with the one being used in kernel */ - if(swap_audit_file() == -1) { - syslog(LOG_ERR, "Error swapping audit file\n"); - } - break; - - case READ_FILE : - if(read_control_file() == -1) { - syslog(LOG_ERR, "Error in audit control file\n"); - } - break; - - case CLOSE_AND_DIE : - err_ret = close_all(); - exit (err_ret); - break; - - default : - break; - } - - return KERN_SUCCESS; -} - -/* - * Suppress duplicate messages within a 30 second interval. - * This should be enough to time to rotate log files without - * thrashing from soft warnings generated before the log is - * actually rotated. - */ -#define DUPLICATE_INTERVAL 30 -/* - * Implementation of the audit_triggers() MIG routine. - */ -kern_return_t audit_triggers(audit_port, flags) - mach_port_t audit_port; - int flags; -{ - static int last_flags; - static time_t last_time; - struct dir_ent *dirent; - - /* - * Suppres duplicate messages from the kernel within the specified interval - */ - struct timeval ts; - struct timezone tzp; - time_t tt; - - if(gettimeofday(&ts, &tzp) == 0) { - tt = (time_t)ts.tv_sec; - if ((flags == last_flags) && (tt < (last_time + DUPLICATE_INTERVAL))) { - return KERN_SUCCESS; - } - last_flags = flags; - last_time = tt; - } - - syslog(LOG_INFO, - "audit_triggers() called within auditd with flags = %d\n", - flags); - /* - * XXX Message processing is done here - */ - dirent = TAILQ_FIRST(&dir_q); - if(flags == AUDIT_TRIGGER_LOW_SPACE) { - if(dirent && (dirent->softlim != 1)) { - TAILQ_REMOVE(&dir_q, dirent, dirs); - /* add this node to the end of the list */ - TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); - audit_warn_soft(dirent->dirname); - dirent->softlim = 1; - - if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && swap_audit_file() == -1) { - syslog(LOG_ERR, "Error swapping audit file\n"); - } - - /* - * check if the next dir has already reached its - * soft limit - */ - dirent = TAILQ_FIRST(&dir_q); - if(dirent->softlim == 1) { - /* all dirs have reached their soft limit */ - audit_warn_allsoft(); - } - } - else { - /* - * Continue auditing to the current file - * Also generate an allsoft warning - * XXX do we want to do this ? - */ - audit_warn_allsoft(); - } - } - else if (flags == AUDIT_TRIGGER_FILE_FULL) { - - /* delete current dir, go on to next */ - TAILQ_REMOVE(&dir_q, dirent, dirs); - audit_warn_hard(dirent->dirname); - free(dirent->dirname); - free(dirent); - - if(swap_audit_file() == -1) { - syslog(LOG_ERR, "Error swapping audit file in response to AUDIT_TRIGGER_FILE_FULL message\n"); - - /* Nowhere to write to */ - audit_warn_allhard(++allhardcount); - } - } - return KERN_SUCCESS; -} - -/* - * Reap our children. - */ -static void -reap_children(void) -{ - pid_t child; - int wstatus; - - while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { - if (wstatus) { - syslog(LOG_INFO, "warn process [pid=%d] %s %d.\n", child, - ((WIFEXITED(wstatus)) ? - "exited with non-zero status" : - "exited as a result of signal"), - ((WIFEXITED(wstatus)) ? - WEXITSTATUS(wstatus) : - WTERMSIG(wstatus))); - } - } -} - -/* - * Handle an RPC call - */ -boolean_t auditd_combined_server( - mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP) -{ - mach_port_t local_port = InHeadP->msgh_local_port; - - if (local_port == signal_port) { - int signo = InHeadP->msgh_id; - int ret; - - if (SIGTERM == signo) { - ret = close_all(); - exit (ret); - } else if (SIGCHLD == signo) { - reap_children(); - return TRUE; - } else { - syslog(LOG_INFO, "Recevied signal %d.\n", signo); - return TRUE; - } - } else if (local_port == control_port) { - boolean_t result; - - result = audit_triggers_server(InHeadP, OutHeadP); - if (!result) - result = auditd_control_server(InHeadP, OutHeadP); - return result; - } - syslog(LOG_INFO, "Recevied msg on bad port 0x%x.\n", local_port); - return FALSE; -} - -void wait_on_audit_trigger(port_set) - mach_port_t port_set; -{ - kern_return_t result; - result = mach_msg_server(auditd_combined_server, 4096, port_set, MACH_MSG_OPTION_NONE); - syslog(LOG_ERR, "abnormal exit\n"); -} - -/* - * Configure the audit controls in the kernel: the event to class mapping, - * kernel preselection mask, etc. - */ -int config_audit_controls(long flags) -{ - au_event_ent_t *ev; - au_evclass_map_t evc_map; - au_mask_t aumask; - int ctr = 0; - char naeventstr[NA_EVENT_STR_SIZE]; - - /* Process the audit event file, obtaining a class mapping for each - * event, and send that mapping into the kernel. - * XXX There's a risk here that the BSM library will return NULL - * for an event when it can't properly map it to a class. In that - * case, we will not process any events beyond the one that failed, - * but should. We need a way to get a count of the events. - */ - - setauevent(); - while((ev = getauevent()) != NULL) { - evc_map.ec_number = ev->ae_number; - evc_map.ec_class = ev->ae_class; - if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) != 0) { - syslog(LOG_ERR, - "Failed to register class mapping for event %s", - ev->ae_name); - } else { - ctr++; - } - free(ev->ae_name); - free(ev->ae_desc); - free(ev); - } - endauevent(); - if (ctr == 0) - syslog(LOG_ERR, "No events to class mappings registered."); - else - syslog(LOG_INFO, "Registered %d event to class mappings.", ctr); - - /* Get the non-attributable event string and set the kernel mask - * from that. - */ - if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) - && ( getauditflagsbin(naeventstr, &aumask) == 0)) { - - if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))){ - syslog(LOG_ERR, - "Failed to register non-attributable event mask."); - } else { - syslog(LOG_INFO, "Registered non-attributable event mask."); - } - - } else { - syslog(LOG_ERR,"Failed to obtain non-attributable event mask."); - } - - /* - * Set the audit policy flags based on passed in parameter values. - */ - if (auditon(A_SETPOLICY, &flags, sizeof(flags))) { - syslog(LOG_ERR, - "Failed to set audit policy."); - } - - return 0; -} - -void setup(long flags) -{ - mach_msg_type_name_t poly; - int aufd; - token_t *tok; - - /* Allocate a port set */ - if (mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_PORT_SET, - &port_set) != KERN_SUCCESS) { - syslog(LOG_ERR, "allocation of port set failed\n"); - fail_exit(); - } - - /* Allocate a signal reflection port */ - if (mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &signal_port) != KERN_SUCCESS || - mach_port_move_member(mach_task_self(), - signal_port, - port_set) != KERN_SUCCESS) { - syslog(LOG_ERR, "allocation of signal port failed\n"); - fail_exit(); - } - - /* Allocate a trigger port */ - if (mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &control_port) != KERN_SUCCESS || - mach_port_move_member(mach_task_self(), - control_port, - port_set) != KERN_SUCCESS) { - syslog(LOG_ERR, "allocation of trigger port failed\n"); - fail_exit(); - } - - /* create a send right on our trigger port */ - mach_port_extract_right(mach_task_self(), control_port, - MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); - - TAILQ_INIT(&dir_q); - - /* register the trigger port with the kernel */ - if(host_set_audit_control_port(mach_host_self(), control_port) != KERN_SUCCESS) { - syslog(LOG_ERR, "Cannot set Mach control port\n"); - fail_exit(); - } - else { - syslog(LOG_ERR, "Mach control port registered\n"); - } - - if(read_control_file() == -1) { - syslog(LOG_ERR, "Error reading control file\n"); - fail_exit(); - } - - /* Generate an audit record */ - if((aufd = au_open()) == -1) { - syslog(LOG_ERR, "Could not create audit startup event.\n"); - } else { - - if((tok = au_to_text("auditd::Audit startup")) != NULL) { - au_write(aufd, tok); - } - - if(au_close(aufd, 1, AUE_audit_startup) == -1) { - syslog(LOG_ERR, "Could not close audit startup event.\n"); - } - } - - if (config_audit_controls(flags) == 0) - syslog(LOG_INFO, "Initialization successful\n"); - else - syslog(LOG_INFO, "Initialization failed\n"); -} - - -int main(int argc, char **argv) -{ - char ch; - long flags = AUDIT_CNT; - int debug = 0; - - while ((ch = getopt(argc, argv, "dhs")) != -1) { - switch(ch) { - - /* debug option */ - case 'd': - debug = 1; - break; - - /* fail-stop option */ - case 's': - flags &= ~(AUDIT_CNT); - break; - - /* halt-stop option */ - case 'h': - flags |= AUDIT_AHLT; - break; - - case '?': - default: - (void)fprintf(stderr, - "usage: auditd [-h | -s]\n"); - exit(1); - } - } - - openlog("auditd", LOG_CONS | LOG_PID, LOG_DAEMON); - syslog(LOG_INFO, "starting...\n"); - - if (debug == 0 && daemon(0, 0) == -1) { - syslog(LOG_ERR, "Failed to daemonize\n"); - exit(1); - } - - if(register_daemon() == -1) { - syslog(LOG_ERR, "Could not register as daemon\n"); - exit(1); - } - - setup(flags); - wait_on_audit_trigger(port_set); - syslog(LOG_INFO, "exiting.\n"); - - exit(1); -} diff --git a/auditd.tproj/auditd.h b/auditd.tproj/auditd.h deleted file mode 100644 index 5866377..0000000 --- a/auditd.tproj/auditd.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _AUDITD_H_ -#define _AUDITD_H_ - -#include -#include -#include - -#define MAX_DIR_SIZE 255 -#define AUDITD_NAME "auditd" - -#define POSTFIX_LEN 16 -#define NOT_TERMINATED ".not_terminated" - -struct dir_ent { - char *dirname; - char softlim; - TAILQ_ENTRY(dir_ent) dirs; -}; - -/* audit utility flags */ -#define OPEN_NEW 0x1 -#define READ_FILE 0x2 -#define CLOSE_AND_DIE 0x4 - -#define HARDLIM_ALL_WARN "allhard" -#define SOFTLIM_ALL_WARN "allsoft" -#define AUDITOFF_WARN "aditoff" -#define EBUSY_WARN "ebusy" -#define GETACDIR_WARN "getacdir" -#define HARDLIM_WARN "hard" -#define NOSTART_WARN "nostart" -#define POSTSIGTERM_WARN "postsigterm" -#define SOFTLIM_WARN "soft" -#define TMPFILE_WARN "tmpfile" - -#define AUDITWARN_SCRIPT "/etc/security/audit_warn" -#define AUDITD_PIDFILE "/var/run/auditd.pid" - -int audit_warn_allhard(int count); -int audit_warn_allsoft(); -int audit_warn_auditoff(); -int audit_warn_ebusy(); -int audit_warn_getacdir(char *filename); -int audit_warn_hard(char *filename); -int audit_warn_nostart(); -int audit_warn_postsigterm(); -int audit_warn_soft(char *filename); -int audit_warn_tmpfile(); - -#endif /* !_AUDITD_H_ */ - diff --git a/auditd.tproj/auditd_control.defs b/auditd.tproj/auditd_control.defs deleted file mode 100644 index 0aad081..0000000 --- a/auditd.tproj/auditd_control.defs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 2004 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 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@ - */ - -/* - * Exported client calls to the auditd facility. - */ - -subsystem - KernelUser - auditd_control 456; - -#ifndef __MigTypeCheck -#define __MigTypeCheck 1 -#endif - -#include -#include - -simpleroutine auditd_control( - auditd_port : mach_port_t; - in flags : int); - diff --git a/auditd.tproj/rc.audit b/auditd.tproj/rc.audit deleted file mode 100644 index 799dc3c..0000000 --- a/auditd.tproj/rc.audit +++ /dev/null @@ -1,25 +0,0 @@ -## -# Startup script for Common Criteria Auditing function. -## -# Copyright 2004 Apple Computer, Inc. -## - -. /etc/rc.common - -## -# Start the audit daemon (if present) -## -if [ "${AUDIT:=-NO-}" == "-YES-" ]; then - if [ -f /usr/sbin/auditd ]; then - /usr/sbin/auditd - fi -elif [ "${AUDIT:=-NO-}" == "-FAILSTOP-" ]; then - if [ -f /usr/sbin/auditd ]; then - /usr/sbin/auditd -s - fi -elif [ "${AUDIT:=-NO-}" == "-FAILHALT-" ]; then - if [ -f /usr/sbin/auditd ]; then - /usr/sbin/auditd -h - fi - -fi diff --git a/bootlog.tproj/Makefile b/bootlog.tproj/Makefile index 2799354..2cb67d9 100644 --- a/bootlog.tproj/Makefile +++ b/bootlog.tproj/Makefile @@ -5,4 +5,10 @@ CFILES = bootlog.c MANPAGES = bootlog.8 LAUNCHD_PLISTS = com.apple.bootlog.plist +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +after_install: + plutil -convert binary1 "$(DSTROOT)/System/Library/LaunchDaemons/$(LAUNCHD_PLISTS)" diff --git a/bootlog.tproj/bootlog.c b/bootlog.tproj/bootlog.c index 5f735a3..b7ab68d 100644 --- a/bootlog.tproj/bootlog.c +++ b/bootlog.tproj/bootlog.c @@ -78,7 +78,7 @@ main() bzero(&utx, sizeof(utx)); utx.ut_type = BOOT_TIME; - utx.ut_pid = 1; // on behave of launchd + utx.ut_pid = 1; // on behalf of launchd /* get the boot time */ len = sizeof(struct timeval); diff --git a/chkpasswd.tproj/Makefile b/chkpasswd.tproj/Makefile index f16cc43..6c8926e 100644 --- a/chkpasswd.tproj/Makefile +++ b/chkpasswd.tproj/Makefile @@ -1,13 +1,19 @@ Project = chkpasswd Install_Dir = /usr/libexec -HFILES = stringops.h -CFILES = ds_passwd.c nis_passwd.c file_passwd.c passwd.c\ - stringops.c +CFILES = od_passwd.c nis_passwd.c file_passwd.c pam_passwd.c passwd.c\ + stringops.c MANPAGES = chkpasswd.8 -Extra_Frameworks = -framework DirectoryService +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_Frameworks = -framework CoreFoundation -framework OpenDirectory -lpam include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make Install_Program_Mode = 04555 + +after_install: + $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d + $(INSTALL_FILE) chkpasswd.pam "$(DSTROOT)"/private/etc/pam.d/chkpasswd diff --git a/chkpasswd.tproj/chkpasswd.8 b/chkpasswd.tproj/chkpasswd.8 index 1f488a4..fd6c4f2 100644 --- a/chkpasswd.tproj/chkpasswd.8 +++ b/chkpasswd.tproj/chkpasswd.8 @@ -6,8 +6,7 @@ .Nd verifies user password against various systems .Sh SYNOPSIS .Nm chkpasswd -.Op Fl i Ar infosystem -.Op Fl l Ar location +.Op Fl i Ar infosystem Op Fl l Ar location .Op Fl c .Op Ar name .Sh DESCRIPTION @@ -23,7 +22,7 @@ The supplied password is compared verbatim without first being encrypted. .\" ========== .It Fl i Ar infosystem Specify the system against which to check the password -(default is OpenDirectory). Valid systems: +(default is PAM). Valid systems: .Bl -tag -width "opendirectory" .It Ar file File-based passwords @@ -34,6 +33,8 @@ OpenDirectory (Directory Services) authentication. If no .Fl l option is specified, the search node is used. +.It Ar PAM +Pluggable Authentication Modules .El .Pp .\" ========== @@ -46,6 +47,8 @@ Filename (default: /etc/master.passwd). NIS domainname. .It for opendirectory A directory node name such as /Local/Default. +.It for PAM +Unused. .El .Pp .El diff --git a/chkpasswd.tproj/chkpasswd.pam b/chkpasswd.tproj/chkpasswd.pam new file mode 100644 index 0000000..18404e6 --- /dev/null +++ b/chkpasswd.tproj/chkpasswd.pam @@ -0,0 +1,5 @@ +# chkpasswd: auth account +auth required pam_opendirectory.so +account required pam_opendirectory.so +password required pam_permit.so +session required pam_permit.so diff --git a/chkpasswd.tproj/ds_passwd.c b/chkpasswd.tproj/ds_passwd.c deleted file mode 100644 index 908e69b..0000000 --- a/chkpasswd.tproj/ds_passwd.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* - * Copyright (c) 1998 by Apple Computer, Inc. - * Portions Copyright (c) 1988 by Sun Microsystems, Inc. - * Portions Copyright (c) 1988 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -// password server can store 511 characters + a terminator. -#define kMaxPassword 512 - -#define SaySorryAndBail() {status = -1; break;} - -//------------------------------------------------------------------------------------- -// ds_check_passwd -//------------------------------------------------------------------------------------- - -int ds_check_passwd(char *uname, char *domain) -{ - char *p = NULL; - tDirReference dsRef = 0; - tDataBuffer *tDataBuff = NULL; - tDirNodeReference nodeRef = 0; - long status = eDSNoErr; - tContextData context = NULL; - unsigned long nodeCount = 0; - unsigned long attrIndex = 0; - tDataList *nodeName = NULL; - tAttributeEntryPtr pAttrEntry = NULL; - tDataList *pRecName = NULL; - tDataList *pRecType = NULL; - tDataList *pAttrType = NULL; - unsigned long recCount = 0; - tRecordEntry *pRecEntry = NULL; - tAttributeListRef attrListRef = 0; - char *pUserLocation = NULL; - char *pUserName = NULL; - tAttributeValueListRef valueRef = 0; - tAttributeValueEntry *pValueEntry = NULL; - tDataList *pUserNode = NULL; - tDirNodeReference userNodeRef = 0; - tDataBuffer *pStepBuff = NULL; - tDataNode *pAuthType = NULL; - unsigned long uiCurr = 0; - unsigned long uiLen = 0; - - do - { - if (uname == NULL) - SaySorryAndBail(); - - printf("Checking password for %s.\n", uname); - p = getpass("Password:"); - if ( p == NULL ) - SaySorryAndBail(); - - status = dsOpenDirService( &dsRef ); - if ( status != eDSNoErr ) - SaySorryAndBail(); - - tDataBuff = dsDataBufferAllocate( dsRef, 4096 ); - if (tDataBuff == NULL) - SaySorryAndBail(); - - if ( domain != NULL ) - { - nodeName = dsBuildFromPath( dsRef, domain, "/" ); - if ( nodeName == NULL ) break; - - // find - status = dsFindDirNodes( dsRef, tDataBuff, nodeName, eDSiExact, &nodeCount, &context ); - } - else - { - // find on search node - status = dsFindDirNodes( dsRef, tDataBuff, NULL, eDSSearchNodeName, &nodeCount, &context ); - } - - if ( status != eDSNoErr ) - SaySorryAndBail(); - - if ( nodeCount < 1 ) - SaySorryAndBail(); - - status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName ); - if (status != eDSNoErr) - SaySorryAndBail(); - - status = dsOpenDirNode( dsRef, nodeName, &nodeRef ); - dsDataListDeallocate( dsRef, nodeName ); - free( nodeName ); - nodeName = NULL; - if (status != eDSNoErr) - SaySorryAndBail(); - - pRecName = dsBuildListFromStrings( dsRef, uname, NULL ); - pRecType = dsBuildListFromStrings( dsRef, kDSStdRecordTypeUsers, NULL ); - pAttrType = dsBuildListFromStrings( dsRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, NULL ); - - recCount = 1; - status = dsGetRecordList( nodeRef, tDataBuff, pRecName, eDSExact, pRecType, - pAttrType, 0, &recCount, &context ); - if ( status != eDSNoErr || recCount == 0 ) - SaySorryAndBail(); - - status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry ); - if ( status != eDSNoErr ) - SaySorryAndBail(); - - for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ ) - { - status = dsGetAttributeEntry( nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry ); - if ( status == eDSNoErr && pAttrEntry != NULL ) - { - if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 ) - { - status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); - if ( status == eDSNoErr && pValueEntry != NULL ) - { - pUserLocation = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); - memcpy( pUserLocation, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); - } - } - else - if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName ) == 0 ) - { - status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); - if ( status == eDSNoErr && pValueEntry != NULL ) - { - pUserName = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); - memcpy( pUserName, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); - } - } - - if ( pValueEntry != NULL ) - dsDeallocAttributeValueEntry( dsRef, pValueEntry ); - pValueEntry = NULL; - - dsDeallocAttributeEntry( dsRef, pAttrEntry ); - pAttrEntry = NULL; - dsCloseAttributeValueList( valueRef ); - valueRef = 0; - } - } - - pUserNode = dsBuildFromPath( dsRef, pUserLocation, "/" ); - status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef ); - if ( status != eDSNoErr ) - SaySorryAndBail(); - - pStepBuff = dsDataBufferAllocate( dsRef, 128 ); - - pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeClearTextOK ); - uiCurr = 0; - - // User name - uiLen = strlen( pUserName ); - memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); - uiCurr += sizeof( unsigned long ); - memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen ); - uiCurr += uiLen; - - // pw - uiLen = strlen( p ); - memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); - uiCurr += sizeof( unsigned long ); - memcpy( &(tDataBuff->fBufferData[ uiCurr ]), p, uiLen ); - uiCurr += uiLen; - - tDataBuff->fBufferLength = uiCurr; - - status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL ); - - } - while ( 0 ); - - // clean up - if (tDataBuff != NULL) { - memset(tDataBuff, 0, tDataBuff->fBufferSize); - dsDataBufferDeAllocate( dsRef, tDataBuff ); - tDataBuff = NULL; - } - - if (pStepBuff != NULL) { - dsDataBufferDeAllocate( dsRef, pStepBuff ); - pStepBuff = NULL; - } - if (pUserLocation != NULL ) { - free(pUserLocation); - pUserLocation = NULL; - } - if (pRecName != NULL) { - dsDataListDeallocate( dsRef, pRecName ); - free( pRecName ); - pRecName = NULL; - } - if (pRecType != NULL) { - dsDataListDeallocate( dsRef, pRecType ); - free( pRecType ); - pRecType = NULL; - } - if (pAttrType != NULL) { - dsDataListDeallocate( dsRef, pAttrType ); - free( pAttrType ); - pAttrType = NULL; - } - if (nodeRef != 0) { - dsCloseDirNode(nodeRef); - nodeRef = 0; - } - if (dsRef != 0) { - dsCloseDirService(dsRef); - dsRef = 0; - } - - if ( status != eDSNoErr ) - { - errno = EACCES; - fprintf(stderr, "Sorry\n"); - exit(1); - } - - return 0; -} - - - - - - diff --git a/chkpasswd.tproj/netinfo_passwd.c b/chkpasswd.tproj/netinfo_passwd.c deleted file mode 100644 index a666acb..0000000 --- a/chkpasswd.tproj/netinfo_passwd.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern void checkpasswd(char *, char *); - -#if 0 -static int -sys_ismyaddress(unsigned long addr) -{ - struct ifconf ifc; - struct ifreq *ifr; - char buf[1024]; /* XXX */ - int offset; - int sock; - struct sockaddr_in *sin; - - if (addr == htonl(INADDR_LOOPBACK)) return 1; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (sock < 0) return 0; - - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - - if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) - { - close(sock); - return 0; - } - - offset = 0; - - while (offset <= ifc.ifc_len) - { - ifr = (struct ifreq *)(ifc.ifc_buf + offset); - offset += IFNAMSIZ + ifr->ifr_addr.sa_len; - - if (ifr->ifr_addr.sa_family != AF_INET) continue; - if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue; - - sin = (struct sockaddr_in *)&ifr->ifr_addr; - if ((ifr->ifr_flags & IFF_UP) && - (!(ifr->ifr_flags & IFF_LOOPBACK)) && - (sin->sin_addr.s_addr == addr)) - { - close(sock); - return 1; - } - } - - close(sock); - return 0; -} - -static int -is_root_on_master(void *d) -{ - int uid; - char myhostname[MAXHOSTNAMELEN + 1]; - char *p; - ni_index where; - ni_proplist pl; - int status; - ni_id dir; - struct sockaddr_in addr; - char *tag; - - uid = getuid(); - if (uid != 0) return 0; - - gethostname(myhostname, MAXHOSTNAMELEN); - p = strchr(myhostname, '.'); - if (p != NULL) *p = '\0'; - - status = ni_root(d, &dir); - if (status != NI_OK) return 0; - - status = ni_read(d, &dir, &pl); - if (status != NI_OK) return 0; - - where = ni_proplist_match(pl, "master", NULL); - if (where == NI_INDEX_NULL) - { - ni_proplist_free(&pl); - return 0; - } - - if (pl.ni_proplist_val[where].nip_val.ni_namelist_len == 0) - { - ni_proplist_free(&pl); - fprintf(stderr, "No value for NetInfo master property\n"); - return 0; - } - - p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '/'); - if (p != NULL) *p = '\0'; - - p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '.'); - if (p != NULL) *p = '\0'; - - if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], myhostname)) - { - ni_proplist_free(&pl); - return 1; - } - - if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "localhost")) - { - ni_proplist_free(&pl); - ni_addrtag(d, &addr, &tag); - if (sys_ismyaddress(addr.sin_addr.s_addr)) return 1; - } - - ni_proplist_free(&pl); - return 0; -} - -static int -secure_passwords() -{ - void *d, *d1; - int status; - ni_index where; - ni_id dir; - ni_namelist nl; - - status = ni_open(NULL, ".", &d); - while (status == NI_OK) - { - dir.nii_object = 0; - status = ni_lookupprop(d, &dir, "security_options", &nl); - if (status == NI_OK) - { - where = ni_namelist_match(nl, "secure_passwords"); - if (where != NI_INDEX_NULL) - { - ni_free(d); - return 1; - } - } - - d1 = d; - status = ni_open(d1, "..", &d); - ni_free(d1); - } - - return 0; -} -#endif /* 0 */ - -static void -parse_server_tag(char *str, struct sockaddr_in *server, char **t) -{ - /* utility to parse a server/tag string */ - - int len, i; - char *host, *tag, *slash; - struct hostent *hent; - - len = strlen(str); - - /* find the "/" character */ - slash = index(str, '/'); - - /* check to see if the "/" is missing */ - if (slash == NULL) - { - fprintf(stderr, "incorrect format \"%s\" for domain name\n", str); - exit(1); - } - - /* find the location of the '/' */ - i = slash - str; - - /* check if host string is empty */ - if (i == 0) - { - fprintf(stderr, "incorrect format \"%s\" for domain name\n", str); - fprintf(stderr, "no server name specified\n"); - exit(1); - } - - /* check if tag string is empty */ - if (i == (len - 1)) - { - fprintf(stderr, "incorrect format \"%s\" for domain name\n", str); - fprintf(stderr, "no tag specified\n"); - exit(1); - } - - /* allocate some space for the host and tag */ - host = (char *)malloc(i + 1); - *t = (char *)malloc(len - i); - tag = *t; - - /* copy out the host */ - strncpy(host, str, i); - host[i] = '\0'; - - /* copy out the tag */ - strcpy(tag, slash + 1); - - /* try interpreting the host portion as an address */ - server->sin_addr.s_addr = inet_addr(host); - - if (server->sin_addr.s_addr == -1) - { - /* This isn't a valid address. Is it a known hostname? */ - hent = gethostbyname(host); - if (hent != NULL) - { - /* found a host with that name */ - bcopy(hent->h_addr, &server->sin_addr, hent->h_length); - } - else - { - fprintf(stderr, "Can't find address for %s\n", host); - free(host); - free(tag); - exit(1); - } - } - - free(host); -} - -static void * -domain_for_user(char *uname, char *locn, ni_id *dir) -{ - char *upath; - int status; - void *d, *d1; - struct sockaddr_in server; - char *tag; - int bytag; - - /* - * Find the user in NetInfo. - */ - upath = malloc(8 + strlen(uname)); - sprintf(upath, "/users/%s", uname); - - if (locn != NULL) - { - bytag = 1; - - if (locn[0] == '/') bytag = 0; - else if (!strncmp(locn, "./", 2)) bytag = 0; - else if (!strncmp(locn, "../", 3)) bytag = 0; - - if (bytag == 1) - { - parse_server_tag(locn, &server, &tag); - d = ni_connect(&server, tag); - if (d == (void *)NULL) return (void *)NULL; - } - else status = ni_open(NULL, locn, &d); - status = ni_pathsearch(d, dir, upath); - free(upath); - - if (status == NI_OK) return d; - - ni_free(d); - return (void *)NULL; - } - - status = ni_open(NULL, ".", &d); - while (status == NI_OK) - { - status = ni_pathsearch(d, dir, upath); - if (status == NI_OK) break; - d1 = d; - status = ni_open(d1, "..", &d); - ni_free(d1); - } - - free(upath); - - if (status == NI_OK) return d; - return (void *)NULL; -} - -int -netinfo_check_passwd(char *uname, char *locn) -{ - char *oldpw; - void *d; - int status; - ni_id dir; - ni_namelist nl; - - d = domain_for_user(uname, locn, &dir); - if (d == (void *)NULL) - { - fprintf(stderr, "user %s not found in NetInfo\n", uname); - exit(1); - } - - /* - * Read the passwd and uid from NetInfo. - */ - status = ni_lookupprop(d, &dir, "passwd", &nl); - if (status == NI_NOPROP) nl.ni_namelist_len = 0; - else if (status != NI_OK) - { - ni_free(d); - fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status)); - exit(1); - } - - oldpw = NULL; - if (nl.ni_namelist_len > 0) oldpw = nl.ni_namelist_val[0]; - - checkpasswd(uname, oldpw); - ni_free(d); - return (0); -} diff --git a/chkpasswd.tproj/od_passwd.c b/chkpasswd.tproj/od_passwd.c new file mode 100644 index 0000000..ab3a68a --- /dev/null +++ b/chkpasswd.tproj/od_passwd.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1998-2008 Apple Inc. All rights reserved. + * Portions Copyright (c) 1988 by Sun Microsystems, Inc. + * Portions Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 +#include +#include +#include +#include +#include +#include + +#include + +//------------------------------------------------------------------------------------- +// od_check_passwd +//------------------------------------------------------------------------------------- + +int od_check_passwd(const char *uname, const char *domain) +{ + int authenticated = 0; + + ODSessionRef session = NULL; + ODNodeRef node = NULL; + ODRecordRef rec = NULL; + CFStringRef user = NULL; + CFStringRef location = NULL; + CFStringRef password = NULL; + + if (uname) user = CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8); + if (domain) location = CFStringCreateWithCString(NULL, domain, kCFStringEncodingUTF8); + + if (user) { + printf("Checking password for %s.\n", uname); + char* p = getpass("Password:"); + if (p) password = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8); + } + + if (password) { + session = ODSessionCreate(NULL, NULL, NULL); + if (session) { + if (location) { + node = ODNodeCreateWithName(NULL, session, location, NULL); + } else { + node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, NULL); + } + if (node) { + rec = ODNodeCopyRecord(node, kODRecordTypeUsers, user, NULL, NULL); + } + if (rec) { + authenticated = ODRecordVerifyPassword(rec, password, NULL); + } + } + } + + if (!authenticated) { + fprintf(stderr, "Sorry\n"); + exit(1); + } + + return 0; +} + + + + + + diff --git a/chkpasswd.tproj/pam_passwd.c b/chkpasswd.tproj/pam_passwd.c new file mode 100644 index 0000000..65790fd --- /dev/null +++ b/chkpasswd.tproj/pam_passwd.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999-2008 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 + +#include +#include /* for openpam_ttyconv() */ + +extern char* progname; +static pam_handle_t *pamh; +static struct pam_conv pamc; + +//------------------------------------------------------------------------------------- +// pam_check_passwd +//------------------------------------------------------------------------------------- + +int pam_check_passwd(char* uname) +{ + int retval = PAM_SUCCESS; + + /* Initialize PAM. */ + pamc.conv = &openpam_ttyconv; + pam_start(progname, uname, &pamc, &pamh); + + printf("Checking password for %s.\n", uname); + + /* Authenticate. */ + if (PAM_SUCCESS != (retval = pam_authenticate(pamh, 0))) + goto pamerr; + + /* Authorize. */ + if (PAM_SUCCESS != (retval = pam_acct_mgmt(pamh, 0)) && PAM_NEW_AUTHTOK_REQD != retval) + goto pamerr; + + /* Change the password. */ + if (PAM_NEW_AUTHTOK_REQD == retval && PAM_SUCCESS != (retval = pam_chauthtok(pamh, 0))) + goto pamerr; + + /* Set the credentials. */ + if (PAM_SUCCESS != (retval = pam_setcred(pamh, PAM_ESTABLISH_CRED))) + goto pamerr; + + /* Open the session. */ + if (PAM_SUCCESS != (retval = pam_open_session(pamh, 0))) + goto pamerr; + + /* Close the session. */ + if (PAM_SUCCESS != (retval = pam_close_session(pamh, 0))) + goto pamerr; + +pamerr: + /* Print an error, if needed. */ + if (PAM_SUCCESS != retval) + fprintf(stderr, "Sorry\n"); + + /* Terminate PAM. */ + pam_end(pamh, retval); + return retval; +} diff --git a/chkpasswd.tproj/passwd.c b/chkpasswd.tproj/passwd.c index ac50cd0..408fe03 100644 --- a/chkpasswd.tproj/passwd.c +++ b/chkpasswd.tproj/passwd.c @@ -23,7 +23,8 @@ */ #define INFO_FILE 1 #define INFO_NIS 2 -#define INFO_DIRECTORYSERVICES 3 +#define INFO_OPEN_DIRECTORY 3 +#define INFO_PAM 4 #ifndef __SLICK__ #define _PASSWD_FILE "/etc/master.passwd" @@ -44,11 +45,14 @@ #define _PASSWORD_LEN 8 #endif +const char* progname = "chkpasswd"; + static int literal = 0; extern int file_check_passwd(char *, char *); extern int nis_check_passwd(char *, char *); -extern int ds_check_passwd(char *, char *); +extern int od_check_passwd(char *, char *); +extern int pam_check_passwd(char *); void checkpasswd(char *name, char *old_pw) @@ -80,73 +84,74 @@ void usage() { fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n"); - fprintf(stderr, "supported infosystems are:\n"); + fprintf(stderr, " infosystem:\n"); fprintf(stderr, " file\n"); - fprintf(stderr, " nis\n"); - fprintf(stderr, " opendirectory\n"); - fprintf(stderr, "for file, location may be a file name (%s is the default)\n", - _PASSWD_FILE); - fprintf(stderr, "for nis, location may be a NIS domainname\n"); - fprintf(stderr, "for opendirectory, location may be a directory node name\n"); - fprintf(stderr, "if -c is specified, the password you supply is compared\n"); - fprintf(stderr, "verbatim without first being crypted\n"); + fprintf(stderr, " NIS\n"); + fprintf(stderr, " OpenDirectory\n"); + fprintf(stderr, " location (for infosystem):\n"); + fprintf(stderr, " file location is path to file (default is %s)\n", _PASSWD_FILE); + fprintf(stderr, " NIS location is NIS domain name\n"); + fprintf(stderr, " OpenDirectory location is directory node name\n"); + fprintf(stderr, " -c: supplied password is compared verbatim without first\n"); + fprintf(stderr, " being crypted\n"); exit(1); } int main(int argc, char *argv[]) { - char *user, *locn; - int i, infosystem; - struct passwd *pw; - - infosystem = INFO_DIRECTORYSERVICES; - user = NULL; - locn = NULL; - - for (i = 1; i < argc; i++) - { - if (!strcmp(argv[i], "-i")) - { - if (++i >= argc) - { - fprintf(stderr, "no argument for -i option\n"); - usage(); - } - - if (!strcmp(argv[i], "File")) infosystem = INFO_FILE; - else if (!strcmp(argv[i], "file")) infosystem = INFO_FILE; - else if (!strcmp(argv[i], "NIS")) infosystem = INFO_NIS; - else if (!strcmp(argv[i], "nis")) infosystem = INFO_NIS; - else if (!strcmp(argv[i], "YP")) infosystem = INFO_NIS; - else if (!strcmp(argv[i], "yp")) infosystem = INFO_NIS; - else if (!strcasecmp(argv[i], "opendirectory")) infosystem = INFO_DIRECTORYSERVICES; - else - { - fprintf(stderr, "unknown info system \"%s\"\n", argv[i]); + char* user = NULL; + char* locn = NULL; + int infosystem, ch; + + infosystem = INFO_PAM; + + while ((ch = getopt(argc, argv, "ci:l:")) != -1) { + switch(ch) { + case 'i': + if (!strcasecmp(optarg, "file")) { + infosystem = INFO_FILE; + } else if (!strcasecmp(optarg, "NIS")) { + infosystem = INFO_NIS; + } else if (!strcasecmp(optarg, "YP")) { + infosystem = INFO_NIS; + } else if (!strcasecmp(optarg, "opendirectory")) { + infosystem = INFO_OPEN_DIRECTORY; + } else if (!strcasecmp(optarg, "PAM")) { + infosystem = INFO_PAM; + } else { + fprintf(stderr, "%s: Unknown info system \'%s\'.\n", + progname, optarg); usage(); } + break; + case 'l': + locn = optarg; + break; + case 'c': + literal++; + break; + case '?': + default: + usage(); + break; } - - else if (!strcmp(argv[i], "-l")) - { - if (++i >= argc) - { - fprintf(stderr, "no argument for -l option\n"); - usage(); - } - locn = argv[i]; - } - - else if (!strcmp(argv[i], "-c")) literal++; - else if (user == NULL) user = argv[i]; - else usage(); + } + argc -= optind; + argv += optind; + + if (argc > 1) { + usage(); + } else if (argc == 1) { + user = argv[0]; } - if (user == NULL) - { - if ((pw = getpwuid(getuid())) == NULL || (user = pw->pw_name) == NULL) - { + if (user == NULL) { + struct passwd* pw = getpwuid(getuid()); + if (pw != NULL && pw->pw_name != NULL) { + user = strdup(pw->pw_name); + } + if (user == NULL) { fprintf(stderr, "you don't have a login name\n"); exit(1); } @@ -160,8 +165,11 @@ main(int argc, char *argv[]) case INFO_NIS: nis_check_passwd(user, locn); break; - case INFO_DIRECTORYSERVICES: - ds_check_passwd(user, locn); + case INFO_OPEN_DIRECTORY: + od_check_passwd(user, locn); + break; + case INFO_PAM: + pam_check_passwd(user); break; } diff --git a/chpass.tproj/Makefile b/chpass.tproj/Makefile index 6d3d8ed..c2cca60 100644 --- a/chpass.tproj/Makefile +++ b/chpass.tproj/Makefile @@ -1,15 +1,17 @@ Project = chpass Install_Dir = /usr/bin -Extra_CC_Flags = -DOPEN_DIRECTORY -fconstant-cfstrings \ - -I../pwd_mkdb.tproj -I../vipw.tproj \ - -F/System/Library/PrivateFrameworks HFILES = chpass.h open_directory.h pw_copy.h CFILES = chpass.c edit.c field.c pw_copy.c table.c util.c \ open_directory.c MANPAGES = chpass.1 -Extra_Frameworks = -F/System/Library/PrivateFrameworks -framework OpenDirectory -framework CoreFoundation +Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags += -DOPEN_DIRECTORY -fconstant-cfstrings \ + -I../pwd_mkdb.tproj -I../vipw.tproj +Extra_LD_Flags = -dead_strip + +Extra_Frameworks = -framework OpenDirectory -framework CoreFoundation include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/chpass.tproj/chpass.c b/chpass.tproj/chpass.c index 8eb9f20..8195e2c 100644 --- a/chpass.tproj/chpass.c +++ b/chpass.tproj/chpass.c @@ -281,7 +281,7 @@ main(int argc, char *argv[]) CFStringRef shell = CFStringCreateWithCString(NULL, arg, kCFStringEncodingUTF8); if (shell) { attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (attrs) CFDictionarySetValue((CFMutableDictionaryRef)attrs, CFSTR(kDS1AttrUserShell), shell); + if (attrs) CFDictionarySetValue((CFMutableDictionaryRef)attrs, kODAttributeTypeUserShell, shell); CFRelease(shell); } } else { diff --git a/chpass.tproj/chpass.h b/chpass.tproj/chpass.h index 8ce5781..2fabe66 100644 --- a/chpass.tproj/chpass.h +++ b/chpass.tproj/chpass.h @@ -82,7 +82,7 @@ typedef struct _entry { size_t len; #if OPEN_DIRECTORY char *except; - CFStringRef attrName; + const CFStringRef *attrName; #else /* OPEN_DIRECTORY */ char *except, *save; #endif /* OPEN_DIRECTORY */ diff --git a/chpass.tproj/edit.c b/chpass.tproj/edit.c index 666b84d..d535654 100644 --- a/chpass.tproj/edit.c +++ b/chpass.tproj/edit.c @@ -174,7 +174,7 @@ display(const char *tfn, struct passwd *pw) } #ifdef OPEN_DIRECTORY - CFArrayRef values = CFDictionaryGetValue(attrs, CFSTR(kDSNAttrRecordName)); + CFArrayRef values = CFDictionaryGetValue(attrs, kODAttributeTypeRecordName); CFStringRef username = (values && CFArrayGetCount(values)) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL; (void)cfprintf(fp, @@ -191,7 +191,7 @@ display(const char *tfn, struct passwd *pw) ENTRY* ep; for (ep = list; ep->prompt; ep++) if (!ep->restricted) { - ep->display(attrs, ep->attrName, ep->prompt, fp); + ep->display(attrs, *ep->attrName, ep->prompt, fp); ndisplayed++; } if(!ndisplayed) { @@ -367,7 +367,7 @@ verify(const char *tfn, struct passwd *pw) { CFStringRef str = CFStringCreateWithCString(NULL, val, kCFStringEncodingUTF8); if (str) { - CFDictionarySetValue(npw, ep->attrName, str); + CFDictionarySetValue(npw, *ep->attrName, str); CFRelease(str); } } diff --git a/chpass.tproj/open_directory.c b/chpass.tproj/open_directory.c index b2cd9b4..9627ad3 100644 --- a/chpass.tproj/open_directory.c +++ b/chpass.tproj/open_directory.c @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include /*--------------------------------------------------------------------------- * PUBLIC setrestricted - sets the restricted flag @@ -41,7 +41,7 @@ setrestricted(CFDictionaryRef attrs) // a restricted shell which they must not change away from. if (restrict_by_default && strcmp(ep->prompt, "shell") == 0) { ep->restricted = 1; - CFArrayRef values = CFDictionaryGetValue(attrs, CFSTR(kDS1AttrUserShell)); + CFArrayRef values = CFDictionaryGetValue(attrs, kODAttributeTypeUserShell); CFTypeRef value = values && CFArrayGetCount(values) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL; if (value && CFGetTypeID(value) == CFStringGetTypeID()) { size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8)+1; @@ -143,7 +143,7 @@ odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictio * Connect to DS server */ session = ODSessionCreate(NULL, NULL, &error); - if ( !session && error && CFErrorGetCode(error) == eServerNotRunning ) { + if ( !session && error && CFErrorGetCode(error) == kODErrorSessionDaemonNotRunning ) { /* * In single-user mode, attempt to load the local DS daemon. */ @@ -161,7 +161,7 @@ odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictio } } else { show_error(error); - return -1; + return NULL; } } @@ -172,20 +172,20 @@ odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictio if (location) { node = ODNodeCreateWithName(NULL, session, location, &error); } else { - node = ODNodeCreateWithNodeType(NULL, session, kODTypeAuthenticationSearchNode, &error); + node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, &error); } if (session) CFRelease(session); if (node) { - CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) }; + CFTypeRef vals[] = { kODAttributeTypeStandardOnly }; CFArrayRef desiredAttrs = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks); - rec = ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), user, desiredAttrs, &error ); + rec = ODNodeCopyRecord(node, kODRecordTypeUsers, user, desiredAttrs, &error); if (desiredAttrs) CFRelease(desiredAttrs); CFRelease(node); } if (rec) { *attrs = ODRecordCopyDetails(rec, NULL, &error); if (*attrs) { - CFArrayRef values = CFDictionaryGetValue(*attrs, CFSTR(kDSNAttrMetaNodeLocation)); + CFArrayRef values = CFDictionaryGetValue(*attrs, kODAttributeTypeMetaNodeLocation); DSPath = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : NULL; } @@ -229,9 +229,9 @@ odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs) // No need to update if entry is restricted if (ep->restricted) continue; - CFArrayRef values_orig = CFDictionaryGetValue(attrs_orig, ep->attrName); + CFArrayRef values_orig = CFDictionaryGetValue(attrs_orig, *ep->attrName); CFTypeRef value_orig = values_orig && CFArrayGetCount(values_orig) ? CFArrayGetValueAtIndex(values_orig, 0) : NULL; - CFTypeRef value = CFDictionaryGetValue(attrs, ep->attrName); + CFTypeRef value = CFDictionaryGetValue(attrs, *ep->attrName); // No need to update if both values are the same if (value == value_orig) continue; @@ -253,7 +253,7 @@ odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs) CFIndex count = CFEqual(value, CFSTR("")) ? 0 : 1; CFTypeRef vals[] = { value }; CFArrayRef values = CFArrayCreate(NULL, vals, count, &kCFTypeArrayCallBacks); - if (values && ODRecordSetValues(rec, ep->attrName, values, &error)) { + if (values && ODRecordSetValue(rec, *ep->attrName, values, &error)) { updated = 1; } if (values) CFRelease(values); diff --git a/chpass.tproj/table.c b/chpass.tproj/table.c index a6dae3e..dba2154 100644 --- a/chpass.tproj/table.c +++ b/chpass.tproj/table.c @@ -74,22 +74,22 @@ char e2[] = ":,"; #include "open_directory.h" ENTRY list[] = { - { "Login", display_string, p_login, 1, 5, e1, CFSTR(kDSNAttrRecordName), }, - { "Password", display_string, p_passwd, 1, 8, e1, CFSTR(kDS1AttrPassword), }, - { "Uid [#]", display_string, p_uid, 1, 3, e1, CFSTR(kDS1AttrUniqueID), }, - { "Gid [# or name]", display_string, p_gid, 1, 3, e1, CFSTR(kDS1AttrPrimaryGroupID), }, - { "Generated uid", display_string, p_uuid, 1, 13, NULL, CFSTR(kDS1AttrGeneratedUID), }, + { "Login", display_string, p_login, 1, 5, e1, &kODAttributeTypeRecordName, }, + { "Password", display_string, p_passwd, 1, 8, e1, &kODAttributeTypePassword, }, + { "Uid [#]", display_string, p_uid, 1, 3, e1, &kODAttributeTypeUniqueID, }, + { "Gid [# or name]", display_string, p_gid, 1, 3, e1, &kODAttributeTypePrimaryGroupID, }, + { "Generated uid", display_string, p_uuid, 1, 13, NULL, &kODAttributeTypeGUID, }, #if 0 { "Change [month day year]", display_time, p_change, 1, 6, NULL, CFSTR(kDS1AttrChange), }, - { "Expire [month day year]", display_time, p_expire, 1, 6, NULL, CFSTR(kDS1AttrExpire), }, + { "Expire [month day year]", display_time, p_expire, 1, 6, NULL, kODAttributeTypeExpire, }, { "Class", display_string, p_class, 0, 5, e1, CFSTR(""), "Class" }, #endif - { "Home directory", display_string, p_hdir, 1, 14, e1, CFSTR(kDS1AttrNFSHomeDirectory), }, - { "Shell", display_string, p_shell, 1, 5, e1, CFSTR(kDS1AttrUserShell), }, - { "Full Name", display_string, p_gecos, 1, 9, e2, CFSTR(kDS1AttrDistinguishedName), }, - { "Office Location", display_string, p_gecos, 1, 8, e2, CFSTR(kDSNAttrBuilding), }, - { "Office Phone", display_string, p_gecos, 1, 12, e2, CFSTR(kDSNAttrPhoneNumber), }, - { "Home Phone", display_string, p_gecos, 1, 10, e2, CFSTR(kDSNAttrHomePhoneNumber), }, + { "Home directory", display_string, p_hdir, 1, 14, e1, &kODAttributeTypeNFSHomeDirectory, }, + { "Shell", display_string, p_shell, 1, 5, e1, &kODAttributeTypeUserShell, }, + { "Full Name", display_string, p_gecos, 1, 9, e2, &kODAttributeTypeFullName, }, + { "Office Location", display_string, p_gecos, 1, 8, e2, &kODAttributeTypeBuilding, }, + { "Office Phone", display_string, p_gecos, 1, 12, e2, &kODAttributeTypePhoneNumber, }, + { "Home Phone", display_string, p_gecos, 1, 10, e2, &kODAttributeTypeHomePhoneNumber, }, { NULL, NULL, NULL, 0, 0, NULL, NULL,}, }; #else /* OPEN_DIRECTORY */ diff --git a/dirhelper.tproj/Makefile b/dirhelper.tproj/Makefile index 1e301e7..bb05ae4 100644 --- a/dirhelper.tproj/Makefile +++ b/dirhelper.tproj/Makefile @@ -6,8 +6,11 @@ SERVERDEFS = /usr/local/include/dirhelper.defs MANPAGES = dirhelper.8 LAUNCHD_PLISTS = com.apple.bsd.dirhelper.plist -Extra_CC_Flags = -D__MigTypeCheck=1 +Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags += -D__MigTypeCheck=1 +Extra_LD_Flags = -dead_strip +Extra_LD_Flags += -lbsm + #CFLAGS = -g -mdynamic-no-pic -Os -Wall -Wextra -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror -D__MigTypeCheck=1 $(RC_CFLAGS) -I $(OBJDIR) -Extra_LD_Flags = -lbsm include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/dirhelper.tproj/dirhelper.c b/dirhelper.tproj/dirhelper.c index e925332..d6dff17 100644 --- a/dirhelper.tproj/dirhelper.c +++ b/dirhelper.tproj/dirhelper.c @@ -66,7 +66,7 @@ int file_check(const char* path, int mode, int uid, int gid); int is_safeboot(void); void clean_files_older_than(const char* path, time_t when); -void clean_directory(const char* name, int); +void clean_directories(const char* names[], int); kern_return_t do___dirhelper_create_user_local( @@ -176,7 +176,7 @@ clean_files_older_than(const char* path, time_t when) { fts = fts_open(path_argv, FTS_PHYSICAL | FTS_XDEV, NULL); if (fts) { FTSENT* ent; - asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s", path); + asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning " VAR_FOLDERS_PATH "%s", path); while ((ent = fts_read(fts))) { switch(ent->fts_info) { case FTS_F: @@ -186,6 +186,9 @@ clean_files_older_than(const char* path, time_t when) { // that we can avoid a race with other processes // attempting to open the file. if (when == 0) { +#if DEBUG + asl_log(NULL, NULL, ASL_LEVEL_ALERT, "unlink(" VAR_FOLDERS_PATH "%s)", ent->fts_path); +#endif (void)unlink(ent->fts_path); } else if (S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_atime < when) { int fd = open(ent->fts_path, O_RDONLY | O_NONBLOCK); @@ -195,6 +198,9 @@ clean_files_older_than(const char* path, time_t when) { struct stat sb; res = fstat(fd, &sb); if (res == 0 && sb.st_atime < when) { +#if DEBUG + asl_log(NULL, NULL, ASL_LEVEL_ALERT, "unlink(" VAR_FOLDERS_PATH "%s)", ent->fts_path); +#endif (void)unlink(ent->fts_path); } (void)flock(fd, LOCK_UN); @@ -207,19 +213,25 @@ clean_files_older_than(const char* path, time_t when) { case FTS_SL: case FTS_SLNONE: if (when == 0) { +#if DEBUG + asl_log(NULL, NULL, ASL_LEVEL_ALERT, "unlink(" VAR_FOLDERS_PATH "%s)", ent->fts_path); +#endif (void)unlink(ent->fts_path); } break; case FTS_DP: if (when == 0) { +#if DEBUG + asl_log(NULL, NULL, ASL_LEVEL_ALERT, "rmdir(" VAR_FOLDERS_PATH "%s)", ent->fts_path); +#endif (void)rmdir(ent->fts_path); } break; case FTS_ERR: case FTS_NS: - asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", ent->fts_path, strerror(ent->fts_errno)); + asl_log(NULL, NULL, ASL_LEVEL_ERR, VAR_FOLDERS_PATH "%s: %s", ent->fts_path, strerror(ent->fts_errno)); break; default: @@ -228,7 +240,7 @@ clean_files_older_than(const char* path, time_t when) { } fts_close(fts); } else { - asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno)); + asl_log(NULL, NULL, ASL_LEVEL_ERR, VAR_FOLDERS_PATH "%s: %s", path, strerror(errno)); } } @@ -242,6 +254,7 @@ file_check(const char* path, int mode, int uid, int gid) { check = check && ((sb.st_gid == (gid_t)gid) || gid == -1); } else { if (errno != ENOENT) { + /* This will print a shorter path after chroot() */ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno)); } check = 0; @@ -262,9 +275,10 @@ is_safeboot(void) { } void -clean_directory(const char* name, int machineBoot) { +clean_directories(const char* dirs[], int machineBoot) { DIR* d; time_t when = 0; + int i; if (!machineBoot) { struct timeval now; @@ -274,8 +288,8 @@ clean_directory(const char* name, int machineBoot) { days = strtol(str, NULL, 0); } (void)gettimeofday(&now, NULL); - - asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s older than %ld days", name, days); + for (i = 0; dirs[i]; i++) + asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s older than %ld days", dirs[i], days); when = now.tv_sec - (days * 60 * 60 * 24); } @@ -292,8 +306,12 @@ clean_directory(const char* name, int machineBoot) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", VAR_FOLDERS_PATH, "invalid ownership"); return; } - - if ((d = opendir(VAR_FOLDERS_PATH))) { + + if (chroot(VAR_FOLDERS_PATH)) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, "chroot(%s) failed: %s", + VAR_FOLDERS_PATH, strerror(errno)); + } + if ((d = opendir("/"))) { struct dirent* e; char path[PATH_MAX]; @@ -301,7 +319,7 @@ clean_directory(const char* name, int machineBoot) { while ((e = readdir(d))) { if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; - snprintf(path, sizeof(path), "%s%s", VAR_FOLDERS_PATH, e->d_name); + snprintf(path, sizeof(path), "%s%s", "/", e->d_name); if (is_root_wheel_directory(path)) { DIR* d2 = opendir(path); if (d2) { @@ -311,16 +329,17 @@ clean_directory(const char* name, int machineBoot) { while ((e2 = readdir(d2))) { char temporary_items[PATH_MAX]; if (strcmp(e2->d_name, ".") == 0 || strcmp(e2->d_name, "..") == 0) continue; - - snprintf(temporary_items, sizeof(temporary_items), - "%s/%s/%s", path, e2->d_name, name); - if (is_directory(temporary_items)) { - // at boot time we clean all files, - // otherwise only clean regular files. - clean_files_older_than(temporary_items, when); + for (i = 0; dirs[i]; i++) { + const char *name = dirs[i]; + snprintf(temporary_items, sizeof(temporary_items), + "%s/%s/%s", path, e2->d_name, name); + if (is_directory(temporary_items)) { + // at boot time we clean all files, + // otherwise only clean regular files. + clean_files_older_than(temporary_items, when); + } } } - closedir(d2); } else { asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno)); @@ -343,14 +362,24 @@ main(int argc, char* argv[]) { // Clean up TemporaryItems directory when launched at boot. // It is safe to clean all file types at this time. if (argc > 1 && strcmp(argv[1], "-machineBoot") == 0) { - clean_directory(DIRHELPER_TEMP_STR, 1); - clean_directory("TemporaryItems", 1); - clean_directory("Cleanup At Startup", 1); - if (is_safeboot()) clean_directory(DIRHELPER_CACHE_STR, 1); + const char *dirs[5]; + int i = 0; + dirs[i++] = DIRHELPER_TEMP_STR; + dirs[i++] = "TemporaryItems"; + dirs[i++] = "Cleanup At Startup"; + if (is_safeboot()) { + dirs[i++] = DIRHELPER_CACHE_STR; + } + dirs[i] = NULL; + clean_directories(dirs, 1); exit(EXIT_SUCCESS); } else if (argc > 1 && strcmp(argv[1], "-cleanTemporaryItems") == 0) { - clean_directory(DIRHELPER_TEMP_STR, 0); - clean_directory("TemporaryItems", 0); + const char *dirs[] = { + DIRHELPER_TEMP_STR, + "TemporaryItems", + NULL + }; + clean_directories(dirs, 0); exit(EXIT_SUCCESS); } else if (argc > 1) { exit(EXIT_FAILURE); @@ -417,8 +446,13 @@ main(int argc, char* argv[]) { kr = mach_port_get_attributes(mach_task_self(), mp, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &status_count); if (kr == KERN_SUCCESS && status.mps_msgcount == 0) { - clean_directory(DIRHELPER_TEMP_STR, 0); - clean_directory("TemporaryItems", 0); + const char *dirs[] = { + DIRHELPER_TEMP_STR, + "TemporaryItems", + NULL + }; + clean_directories(dirs, 0); + exit(EXIT_SUCCESS); } // main event loop diff --git a/dmesg.tproj/Makefile b/dmesg.tproj/Makefile index 955ab2c..7ab0dcf 100644 --- a/dmesg.tproj/Makefile +++ b/dmesg.tproj/Makefile @@ -5,6 +5,8 @@ CFILES = dmesg.c MANPAGES = dmesg.8 MAKEFILE = tool.make -Extra_LD_Flags = -lproc +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip +Extra_LD_Flags += -lproc include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/dp_notify_lib/Makefile b/dp_notify_lib/Makefile index 8b8e4f0..528c5a1 100644 --- a/dp_notify_lib/Makefile +++ b/dp_notify_lib/Makefile @@ -5,7 +5,7 @@ Install_Dir = /usr/local/lib SERVERDEFS = ../dynamic_pager.tproj/backing_store_alerts.defs USERDEFS = ../dynamic_pager.tproj/backing_store_triggers.defs -Extra_MIG_Flags = -no-cpp-precomp -R -untyped -DNO_DIRECT_RPC -I$(SRCROOT) +Extra_MIG_Flags = -R -untyped -DNO_DIRECT_RPC -I$(SRCROOT) Extra_LD_Flags = -static include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/dpkg/control b/dpkg/control deleted file mode 100644 index bd3d434..0000000 --- a/dpkg/control +++ /dev/null @@ -1,4 +0,0 @@ -Package: system-cmds -Maintainer: Darwin Developers -Description: System commands -Build-Depends: build-base, librpcsvc-hdrs, libinfo-hdrs, libstreams-hdrs, iokituser, libcurses-hdrs, corefoundation, carbonheaders, project-makefiles, iostoragefamily diff --git a/dynamic_pager.tproj/Makefile b/dynamic_pager.tproj/Makefile index 24bf360..dc5ae6a 100644 --- a/dynamic_pager.tproj/Makefile +++ b/dynamic_pager.tproj/Makefile @@ -8,18 +8,22 @@ USERDEFS = backing_store_alerts.defs MANPAGES = dynamic_pager.8 LAUNCHD_PLISTS = com.apple.dynamic_pager.plist -Extra_CC_Flags = -no-cpp-precomp -DNO_DIRECT_RPC +Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_LD_Flags = -dead_strip -Extra_LD_Flags = -framework CoreFoundation -framework IOKit -Extra_MIG_Flags = -no-cpp-precomp -R -untyped -DNO_DIRECT_RPC +Extra_CC_Flags += -DNO_DIRECT_RPC + +Extra_Frameworks += -framework CoreFoundation -framework IOKit +Extra_MIG_Flags = -R -untyped -DNO_DIRECT_RPC include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) - + after_install: ifeq "$(Embedded)" "YES" /usr/libexec/PlistBuddy -x \ -c "Add :Disabled bool true" \ "$(DSTROOT)/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist" endif + plutil -convert binary1 "$(DSTROOT)/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist" diff --git a/dynamic_pager.tproj/com.apple.dynamic_pager.plist b/dynamic_pager.tproj/com.apple.dynamic_pager.plist index 5b2c7b8..1553c7a 100644 --- a/dynamic_pager.tproj/com.apple.dynamic_pager.plist +++ b/dynamic_pager.tproj/com.apple.dynamic_pager.plist @@ -12,5 +12,9 @@ OnDemand + HopefullyExitsLast + + EnableTransactions + diff --git a/dynamic_pager.tproj/dynamic_pager.8 b/dynamic_pager.tproj/dynamic_pager.8 index eaae275..aa235dc 100644 --- a/dynamic_pager.tproj/dynamic_pager.8 +++ b/dynamic_pager.tproj/dynamic_pager.8 @@ -8,7 +8,6 @@ .Nd external storage manager for dynamic pager .Sh SYNOPSIS .Nm dynamic_pager -.Op Fl E .Op Fl F Ar filename .Op Fl S Ar filesize .Op Fl H Ar high-water-trigger @@ -29,9 +28,6 @@ when the external paging pool expands or contracts. .Sh OPTIONS .Bl -tag -width Ds .\" ========== -.It Fl E -Encrypt the data in the swap files. -.\" ========== .It Fl F The base name of the .Ar filename @@ -77,7 +73,18 @@ options disable that default and cause to use a series of fixed sized external paging files. .El .Sh FILES -.Bl -tag -width /private/var/vp/swapfile* -compact +.Bl -tag -width /Library/Preferences/com.apple.virtualMemory.plist -compact .It Pa /private/var/vm/swapfile* Default external paging files. +.It Pa /Library/Preferences/com.apple.virtualMemory.plist +Configuration file. +.El +.Sh XML PROPERTY LIST KEYS +The following keys can be specified in the configuration file. Please see +.Xr plist 5 +for more information about property list files. +.Pp +.Bl -ohang +.It Sy UseEncryptedSwap +This optional key activates encrypted swap (aka Secure VM), so that all data is encrypted before being written to a swap file. The default is on for portable computers and off for other computers. .El diff --git a/dynamic_pager.tproj/dynamic_pager.c b/dynamic_pager.tproj/dynamic_pager.c index 2e056c8..b44878f 100644 --- a/dynamic_pager.tproj/dynamic_pager.c +++ b/dynamic_pager.tproj/dynamic_pager.c @@ -11,6 +11,7 @@ #define MACH_BSD #endif #include +#include #include #include #include @@ -31,10 +32,9 @@ #include #include -#include -#include -#include #include +#include +#include #include #include @@ -100,22 +100,12 @@ server_alert_loop( max_size + MAX_TRAILER_SIZE, TRUE)) != KERN_SUCCESS) return kr; - if ((kr = vm_protect(mach_task_self(), - (vm_address_t)bufRequest, - max_size + MAX_TRAILER_SIZE, - FALSE, VM_PROT_ALL)) != KERN_SUCCESS) - return kr; mlock(bufRequest, max_size + MAX_TRAILER_SIZE); if ((kr = vm_allocate(mach_task_self(), (vm_address_t *)&bufReply, max_size + MAX_TRAILER_SIZE, TRUE)) != KERN_SUCCESS) return kr; - if ((kr = vm_protect(mach_task_self(), - (vm_address_t)bufReply, - max_size + MAX_TRAILER_SIZE, - FALSE, VM_PROT_ALL)) != KERN_SUCCESS) - return kr; mlock(bufReply, max_size + MAX_TRAILER_SIZE); while(TRUE) { mr = mach_msg(&bufRequest->Head, MACH_RCV_MSG|options, @@ -212,9 +202,8 @@ default_pager_space_alert(alert_port, flags) int flags; { char subfile[512]; - FILE *file_ptr; off_t filesize; - int error; + int error=0, fd=0; kern_return_t ret; int cur_limits; unsigned int cur_size; @@ -245,19 +234,18 @@ default_pager_space_alert(alert_port, flags) notifications = HI_WAT_ALERT; sprintf(subfile, "%s%d", fileroot, file_count); - file_ptr = fopen(subfile, "w+"); - if (file_ptr == NULL) { + fd = open(subfile, O_CREAT|O_EXCL|O_RDWR,(mode_t)(S_IRUSR|S_IWUSR)); + if (fd == -1) { /* force error recovery below */ error = -1; } else { - fchmod(fileno(file_ptr), (mode_t)01600); - error = fcntl(fileno(file_ptr), F_SETSIZE, &filesize); + error = fcntl(fd, F_SETSIZE, &filesize); if(error) { - error = ftruncate(fileno(file_ptr), filesize); + error = ftruncate(fd, filesize); } if(error) unlink(subfile); - fclose(file_ptr); + close(fd); } if(error == -1) { @@ -272,6 +260,8 @@ default_pager_space_alert(alert_port, flags) notifications = HI_WAT_ALERT | LO_WAT_ALERT; else notifications = HI_WAT_ALERT; + + notifications |= SWAP_FILE_CREATION_ERROR; local_hi_water = local_hi_water>>2; if(notify_high >= (local_hi_water)) { @@ -286,7 +276,6 @@ default_pager_space_alert(alert_port, flags) notify_high = 0; } } - macx_triggers(local_hi_water, limits[cur_limits].low_water, notifications, alert_port); } else { if(hi_water < notify_high) { if(local_hi_water < notify_high) { @@ -299,7 +288,8 @@ default_pager_space_alert(alert_port, flags) } local_hi_water = hi_water; } - ret = macx_swapon(subfile, flags, cur_size, priority); + ret = macx_swapon((uint64_t)(uintptr_t)subfile, + flags, cur_size, priority); if(ret) { unlink(subfile); @@ -330,7 +320,6 @@ default_pager_space_alert(alert_port, flags) notify_high = 0; } } - macx_triggers(local_hi_water, limits[cur_limits].low_water, notifications, alert_port); } else if(bs_recovery <= cur_size) { if((bs_recovery != 0) && (notify_port)) { backing_store_alert(notify_port, @@ -360,7 +349,8 @@ default_pager_space_alert(alert_port, flags) notify_high = 0; bs_recovery = 0; } - if((error = macx_swapoff(subfile, flags)) == 0) { + if((error = macx_swapoff((uint64_t)(uintptr_t)subfile, + flags)) == 0) { unlink(subfile); file_count--; @@ -408,24 +398,22 @@ paging_setup(flags, size, priority, low, high, encrypted) { off_t filesize = size; char subfile[512]; - FILE *file_ptr; - int error; + int error, fd = 0; file_count = 0; sprintf(subfile, "%s%d", fileroot, file_count); - file_ptr = fopen(subfile, "w+"); - if (file_ptr == NULL) { + fd = open(subfile, O_CREAT|O_EXCL|O_RDWR, ((mode_t)(S_IRUSR|S_IWUSR))); + if (fd == -1) { fprintf(stderr, "dynamic_pager: cannot create paging file %s!\n", subfile); exit(EXIT_FAILURE); } - fchmod(fileno(file_ptr), (mode_t)01600); - error = fcntl(fileno(file_ptr), F_SETSIZE, &filesize); + error = fcntl(fd, F_SETSIZE, &filesize); if(error) { - error = ftruncate(fileno(file_ptr), filesize); + error = ftruncate(fd, filesize); } - fclose(file_ptr); + close(fd); if (error == -1) { fprintf(stderr, "dynamic_pager: cannot extend paging file size %s to %llu!\n", @@ -444,7 +432,7 @@ paging_setup(flags, size, priority, low, high, encrypted) (encrypted ? "on" : "off")); } - macx_swapon(subfile, flags, size, priority); + macx_swapon((uint64_t)(uintptr_t)subfile, flags, size, priority); if(hi_water) { mach_msg_type_name_t poly; @@ -510,9 +498,9 @@ should_encrypt_swap(void) CFTypeRef value; boolean_t should_encrypt; boolean_t explicit_value; - CFTypeRef snap; explicit_value = false; + should_encrypt = true; fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)VM_PREFS_PLIST, strlen(VM_PREFS_PLIST), false); if (fileURL == NULL) { @@ -559,30 +547,16 @@ should_encrypt_swap(void) done: if (! explicit_value) { +#if TARGET_OS_EMBEDDED + should_encrypt = FALSE; +#else /* by default, encrypt swap on laptops only */ - mach_timespec_t w; - kern_return_t kr; - - /* wait up to 60 seconds for IOKit to quiesce */ - w.tv_sec = 60; - w.tv_nsec = 0; - kr = IOKitWaitQuiet(kIOMasterPortDefault, &w); - if (kr != kIOReturnSuccess) { - /* - * Can't tell if we're on a laptop, - * assume we do want encrypted swap. - */ - should_encrypt = TRUE; - /*fprintf(stderr, "dynamic_pager: IOKitWaitQuiet ret 0x%x (%s)\n", kr, mach_error_string(kr));*/ - } else { - /* - * Look for battery power source. - */ - snap = IOPSCopyPowerSourcesInfo(); - should_encrypt = (kCFBooleanTrue == IOPSPowerSourceSupported(snap, CFSTR(kIOPMBatteryPowerKey))); - CFRelease(snap); - /*fprintf(stderr, "dynamic_pager: battery power source: %d\n", should_encrypt);*/ - } + /* + * Look for battery power source. + */ + should_encrypt = (kCFBooleanTrue == IOPSPowerSourceSupported(NULL, CFSTR(kIOPMBatteryPowerKey))); + /*fprintf(stderr, "dynamic_pager: battery power source: %d\n", should_encrypt);*/ +#endif } return should_encrypt; @@ -595,7 +569,7 @@ main(int argc, char **argv) extern int optind; char default_filename[] = "/private/var/vm/swapfile"; int ch; - int variable_sized = 1; + int variable_sized = 1,flags=0; boolean_t encrypted_swap; /* @@ -606,6 +580,7 @@ main(int argc, char **argv) seteuid(getuid()); strcpy(fileroot, default_filename); +retry: limits[0].size = 20000000; limits[0].low_water = 0; @@ -693,9 +668,14 @@ main(int argc, char **argv) * we only want the portion of the pathname that should already exist */ strcpy(tmp, fileroot); - if (q = strrchr(tmp, '/')) + if ((q = strrchr(tmp, '/'))) *q = 0; + /* + * Remove all files in the swap directory. + */ + clean_swap_directory(tmp); + if (statfs(tmp, &sfs) == -1) { /* * Setup the swap directory. @@ -715,11 +695,6 @@ main(int argc, char **argv) } } - /* - * Remove all files in the swap directory. - */ - clean_swap_directory(tmp); - if (fs_limit != (u_int64_t) -1) { /* * Limit the maximum size of a swap file to 1/8 the free @@ -751,8 +726,16 @@ main(int argc, char **argv) /* * further limit the maximum size of a swap file */ - if (memsize > MAXIMUM_SIZE) + if (memsize <= MINIMUM_SIZE) { + (void)fprintf(stderr, "dynamic_pager: Need more space on the disk to enable swapping.\n"); + sleep(30); + goto retry; + } else if (memsize <= (MINIMUM_SIZE*2)) { + (void)fprintf(stderr, "dynamic_pager: Activating emergency swap file immediately.\n"); + flags |= USE_EMERGENCY_SWAP_FILE_FIRST; + } else if (memsize > MAXIMUM_SIZE) { memsize = MAXIMUM_SIZE; + } size = MINIMUM_SIZE; @@ -797,7 +780,7 @@ main(int argc, char **argv) argc -= optind; argv += optind; - paging_setup(0, limits[0].size, priority, limits[0].low_water, hi_water, + paging_setup(flags, limits[0].size, priority, limits[0].low_water, hi_water, encrypted_swap); return (0); diff --git a/fs_usage.tproj/Makefile b/fs_usage.tproj/Makefile index 7d3d5a0..0c3f358 100644 --- a/fs_usage.tproj/Makefile +++ b/fs_usage.tproj/Makefile @@ -4,7 +4,10 @@ Install_Dir = /usr/bin CFILES = fs_usage.c MANPAGES = fs_usage.1 -Extra_CC_Flags = -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip -lutil + +Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/fs_usage.tproj/fs_usage.c b/fs_usage.tproj/fs_usage.c index 137a90e..f9e02c1 100644 --- a/fs_usage.tproj/fs_usage.c +++ b/fs_usage.tproj/fs_usage.c @@ -57,36 +57,60 @@ cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c #endif /*KERNEL_PRIVATE*/ #include +#include #include #import #import #include +#include -extern int errno; - +#define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */ +#define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */ +#define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */ #define MAXINDEX 2048 typedef struct LibraryRange { - uint64_t b_address; - uint64_t e_address; + uint64_t b_address; + uint64_t e_address; } LibraryRange; LibraryRange framework32; LibraryRange framework64; +#define TEXT_R 0 +#define DATA_R 1 +#define OBJC_R 2 +#define IMPORT_R 3 +#define UNICODE_R 4 +#define IMAGE_R 5 +#define LINKEDIT_R 6 + + +char *frameworkType[] = { + " ", + " ", + " ", + " ", + " ", + " ", + "", +}; + + typedef struct LibraryInfo { - uint64_t b_address; - uint64_t e_address; - char *name; + uint64_t b_address; + uint64_t e_address; + int r_type; + char *name; } LibraryInfo; LibraryInfo frameworkInfo[MAXINDEX]; int numFrameworks = 0; -char *lookup_name(uint64_t user_addr); +void lookup_name(uint64_t user_addr, char **type, char **name); /* @@ -96,7 +120,7 @@ char *lookup_name(uint64_t user_addr); get reflected in the -w mode output. */ #define NUMPARMS 23 -#define PATHLENGTH (NUMPARMS*sizeof(long)) +#define PATHLENGTH (NUMPARMS*sizeof(uintptr_t)) #define MAXCOLS 132 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80) #define MAXWIDTH MAX_WIDE_MODE_COLS + 64 @@ -104,7 +128,7 @@ char *lookup_name(uint64_t user_addr); struct th_info { int my_index; int in_filemgr; - int thread; + uintptr_t thread; int pid; int type; int arg1; @@ -115,14 +139,14 @@ struct th_info { int arg6; int arg7; int arg8; - int child_thread; + uintptr_t child_thread; int waited; double stime; - long *pathptr; - long pathname[NUMPARMS + 1]; /* add room for null terminator */ + uintptr_t *pathptr; + uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */ }; -#define MAX_THREADS 512 +#define MAX_THREADS 1024 struct th_info th_state[MAX_THREADS]; kd_threadmap *last_map = NULL; @@ -182,8 +206,8 @@ struct diskio { int blkno; int iosize; int io_errno; - int issuing_thread; - int completion_thread; + uintptr_t issuing_thread; + uintptr_t completion_thread; char issuing_command[MAXCOMLEN]; double issued_time; double completed_time; @@ -199,24 +223,25 @@ struct diskio *insert_diskio(); struct diskio *complete_diskio(); void free_diskio(); void print_diskio(); -void format_print(struct th_info *, char *, int, int, int, int, int, int, int, double, double, int, char *, struct diskio *); -void exit_syscall(char *, int, int, int, int, int, int, int, double); +void format_print(struct th_info *, char *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio *); +void enter_syscall_now(uintptr_t, int, kd_buf *, char *, double); +void enter_syscall(uintptr_t, int, kd_buf *, char *, double); +void exit_syscall(char *, uintptr_t, int, int, int, int, int, int, double); +void extend_syscall(uintptr_t, int, kd_buf *); char *find_disk_name(); void cache_disk_names(); -int ReadSharedCacheMap(const char *, LibraryRange *); +void recache_disk_names(); +int ReadSharedCacheMap(const char *, LibraryRange *, char *); void SortFrameworkAddresses(); -void mark_thread_waited(int); +void mark_thread_waited(uintptr_t); int check_filter_mode(struct th_info *, int, int, int, char *); void fs_usage_fd_set(unsigned int, unsigned int); int fs_usage_fd_isset(unsigned int, unsigned int); void fs_usage_fd_clear(unsigned int, unsigned int); void init_arguments_buffer(); int get_real_command_name(int, char *, int); -void create_map_entry(int, int, char *); - -void enter_syscall(); -void extend_syscall(); -void kill_thread_map(); +void create_map_entry(uintptr_t, int, char *); +void kill_thread_map(uintptr_t); #define CLASS_MASK 0xff000000 #define CSC_MASK 0xffff0000 @@ -232,9 +257,12 @@ void kill_thread_map(); #define MACH_pageout 0x01300004 #define MACH_sched 0x01400000 #define MACH_stkhandoff 0x01400008 +#define MACH_idle 0x01400024 #define VFS_LOOKUP 0x03010090 #define BSC_exit 0x040C0004 +#define SPEC_ioctl 0x3060000 + #define P_DISKIO 0x03020000 #define P_DISKIO_DONE 0x03020004 #define P_DISKIO_MASK (CSC_MASK | 0x4) @@ -292,11 +320,12 @@ void kill_thread_map(); #define BSC_unlink 0x040C0028 #define BSC_chdir 0x040c0030 #define BSC_fchdir 0x040c0034 -#define BSC_mknod 0x040C0038 -#define BSC_chmod 0x040C003C -#define BSC_chown 0x040C0040 -#define BSC_access 0x040C0084 -#define BSC_chflags 0x040C0088 +#define BSC_mknod 0x040C0038 +#define BSC_chmod 0x040C003C +#define BSC_chown 0x040C0040 +#define BSC_getfsstat 0x040C0048 +#define BSC_access 0x040C0084 +#define BSC_chflags 0x040C0088 #define BSC_fchflags 0x040C008C #define BSC_sync 0x040C0090 #define BSC_dup 0x040C00A4 @@ -305,6 +334,7 @@ void kill_thread_map(); #define BSC_symlink 0x040C00E4 #define BSC_readlink 0x040C00E8 #define BSC_execve 0x040C00EC +#define BSC_umask 0x040C00F0 #define BSC_chroot 0x040C00F4 #define BSC_msync 0x040C0104 #define BSC_dup2 0x040C0168 @@ -374,6 +404,19 @@ void kill_thread_map(); #define BSC_aio_read 0x040C04F8 #define BSC_aio_write 0x040C04FC #define BSC_lio_listio 0x040C0500 +#define BSC_sendfile 0x040C0544 +#define BSC_stat64 0x040C0548 +#define BSC_fstat64 0x040C054C +#define BSC_lstat64 0x040C0550 +#define BSC_stat64_extended 0x040C0554 +#define BSC_lstat64_extended 0x040C0558 +#define BSC_fstat64_extended 0x040C055C +#define BSC_getdirentries64 0x040C0560 +#define BSC_statfs64 0x040C0564 +#define BSC_fstatfs64 0x040C0568 +#define BSC_getfsstat64 0x040C056C +#define BSC_pthread_chdir 0x040C0570 +#define BSC_pthread_fchdir 0x040C0574 #define BSC_lchown 0x040C05B0 #define BSC_read_nocancel 0x040c0630 @@ -507,6 +550,9 @@ void kill_thread_map(); #define FMT_FCHFLAGS 29 #define FMT_IOCTL 30 #define FMT_MMAP 31 +#define FMT_UMASK 32 +#define FMT_SENDFILE 33 +#define FMT_SPEC_IOCTL 34 #define MAX_BSD_SYSCALL 512 @@ -559,6 +605,7 @@ int bsd_syscall_types[] = { BSC_symlink, BSC_readlink, BSC_execve, + BSC_umask, BSC_chroot, BSC_dup2, BSC_fsync, @@ -633,11 +680,25 @@ int bsd_syscall_types[] = { BSC_aio_write, BSC_lio_listio, BSC_lchown, + BSC_sendfile, BSC_msync, BSC_msync_nocancel, BSC_fcntl, BSC_fcntl_nocancel, BSC_ioctl, + BSC_stat64, + BSC_fstat64, + BSC_lstat64, + BSC_stat64_extended, + BSC_lstat64_extended, + BSC_fstat64_extended, + BSC_getdirentries64, + BSC_statfs64, + BSC_fstatfs64, + BSC_pthread_chdir, + BSC_pthread_fchdir, + BSC_getfsstat, + BSC_getfsstat64, 0 }; @@ -733,18 +794,12 @@ int exclude_default_pids = 1; struct kinfo_proc *kp_buffer = 0; int kp_nentries = 0; -#define SAMPLE_SIZE 100000 - int num_cpus; #define EVENT_BASE 60000 int num_events = EVENT_BASE; -#define DBG_ZERO_FILL_FAULT 1 -#define DBG_PAGEIN_FAULT 2 -#define DBG_COW_FAULT 3 -#define DBG_CACHE_HIT_FAULT 4 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) #define DBG_FUNC_MASK 0xfffffffc @@ -769,7 +824,7 @@ kd_threadmap *mapptr = 0; /* pointer to list of threads */ typedef struct { unsigned int fd_valid; /* set if this is a valid entry */ - unsigned int fd_thread; + uintptr_t fd_thread; unsigned int fd_setsize; /* this is a bit count */ unsigned long *fd_setptr; /* file descripter bitmap */ } fd_threadmap; @@ -779,6 +834,14 @@ fd_threadmap *fdmapptr = 0; /* pointer to list of threads for fd tracking */ int trace_enabled = 0; int set_remove_flag = 1; +char *RAW_file = (char *)0; +int RAW_flag = 0; +int RAW_fd = 0; +double bias_now = 0.0; +double start_time = 0.0; +double end_time = 99999999999.9; + + void set_numbufs(); void set_init(); void set_enable(); @@ -840,7 +903,7 @@ void sigwinch() int exit_usage(char *myname) { - fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname); + fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname); fprintf(stderr, " -e exclude the specified list of pids from the sample\n"); fprintf(stderr, " and exclude fs_usage by default\n"); fprintf(stderr, " -w force wider, detailed, output\n"); @@ -895,6 +958,11 @@ void init_tables(void) continue; } switch (type) { + + case BSC_sendfile: + bsd_syscalls[code].sc_name = "sendfile"; + bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */ + break; /* once we add an extended info trace event */ case BSC_recvmsg: case BSC_recvmsg_nocancel: @@ -982,10 +1050,18 @@ void init_tables(void) bsd_syscalls[code].sc_name = "stat"; break; + case BSC_stat64: + bsd_syscalls[code].sc_name = "stat64"; + break; + case BSC_stat_extended: bsd_syscalls[code].sc_name = "stat_extended"; break; + case BSC_stat64_extended: + bsd_syscalls[code].sc_name = "stat_extended64"; + break; + case BSC_execve: bsd_syscalls[code].sc_name = "execve"; break; @@ -1058,19 +1134,37 @@ void init_tables(void) bsd_syscalls[code].sc_format = FMT_FD; break; + case BSC_fstat64: + bsd_syscalls[code].sc_name = "fstat64"; + bsd_syscalls[code].sc_format = FMT_FD; + break; + case BSC_fstat_extended: bsd_syscalls[code].sc_name = "fstat_extended"; bsd_syscalls[code].sc_format = FMT_FD; break; + case BSC_fstat64_extended: + bsd_syscalls[code].sc_name = "fstat64_extended"; + bsd_syscalls[code].sc_format = FMT_FD; + break; + case BSC_lstat: bsd_syscalls[code].sc_name = "lstat"; break; + case BSC_lstat64: + bsd_syscalls[code].sc_name = "lstat64"; + break; + case BSC_lstat_extended: bsd_syscalls[code].sc_name = "lstat_extended"; break; + case BSC_lstat64_extended: + bsd_syscalls[code].sc_name = "lstat_extended64"; + break; + case BSC_lstatv: bsd_syscalls[code].sc_name = "lstatv"; break; @@ -1087,6 +1181,11 @@ void init_tables(void) bsd_syscalls[code].sc_name = "mknod"; break; + case BSC_umask: + bsd_syscalls[code].sc_name = "umask"; + bsd_syscalls[code].sc_format = FMT_UMASK; + break; + case BSC_chmod: bsd_syscalls[code].sc_name = "chmod"; bsd_syscalls[code].sc_format = FMT_CHMOD; @@ -1133,6 +1232,10 @@ void init_tables(void) bsd_syscalls[code].sc_name = "chdir"; break; + case BSC_pthread_chdir: + bsd_syscalls[code].sc_name = "pthread_chdir"; + break; + case BSC_chroot: bsd_syscalls[code].sc_name = "chroot"; break; @@ -1142,7 +1245,7 @@ void init_tables(void) break; case BSC_delete: - bsd_syscalls[code].sc_name = "delete"; + bsd_syscalls[code].sc_name = "delete-Carbon"; break; case BSC_undelete: @@ -1172,6 +1275,11 @@ void init_tables(void) bsd_syscalls[code].sc_format = FMT_FD; break; + case BSC_pthread_fchdir: + bsd_syscalls[code].sc_name = "pthread_fchdir"; + bsd_syscalls[code].sc_format = FMT_FD; + break; + case BSC_futimes: bsd_syscalls[code].sc_name = "futimes"; bsd_syscalls[code].sc_format = FMT_FD; @@ -1243,11 +1351,28 @@ void init_tables(void) bsd_syscalls[code].sc_name = "statfs"; break; + case BSC_statfs64: + bsd_syscalls[code].sc_name = "statfs64"; + break; + + case BSC_getfsstat: + bsd_syscalls[code].sc_name = "getfsstat"; + break; + + case BSC_getfsstat64: + bsd_syscalls[code].sc_name = "getfsstat64"; + break; + case BSC_fstatfs: bsd_syscalls[code].sc_name = "fstatfs"; bsd_syscalls[code].sc_format = FMT_FD; break; + case BSC_fstatfs64: + bsd_syscalls[code].sc_name = "fstatfs64"; + bsd_syscalls[code].sc_format = FMT_FD; + break; + case BSC_pathconf: bsd_syscalls[code].sc_name = "pathconf"; break; @@ -1262,6 +1387,11 @@ void init_tables(void) bsd_syscalls[code].sc_format = FMT_FD_IO; break; + case BSC_getdirentries64: + bsd_syscalls[code].sc_name = "getdirentries64"; + bsd_syscalls[code].sc_format = FMT_FD_IO; + break; + case BSC_lseek: bsd_syscalls[code].sc_name = "lseek"; bsd_syscalls[code].sc_format = FMT_LSEEK; @@ -1684,10 +1814,11 @@ main(argc, argv) void set_pidexclude(); int quit(); - if ( geteuid() != 0 ) { - fprintf(stderr, "'fs_usage' must be run as root...\n"); - exit(1); - } + if (0 != reexec_to_match_kernel()) { + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); + } + get_screenwidth(); /* get our name */ @@ -1700,35 +1831,57 @@ main(argc, argv) } } - while ((ch = getopt(argc, argv, "ewf:")) != EOF) { + while ((ch = getopt(argc, argv, "ewf:R:S:E:")) != EOF) { + switch(ch) { + case 'e': exclude_pids = 1; exclude_default_pids = 0; break; + case 'w': wideflag = 1; if ((uint)columns < MAX_WIDE_MODE_COLS) - columns = MAX_WIDE_MODE_COLS; + columns = MAX_WIDE_MODE_COLS; break; + case 'f': if (!strcmp(optarg, "network")) - filter_mode |= NETWORK_FILTER; + filter_mode |= NETWORK_FILTER; else if (!strcmp(optarg, "filesys")) - filter_mode |= FILESYS_FILTER; + filter_mode |= FILESYS_FILTER; else if (!strcmp(optarg, "cachehit")) - filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */ + filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */ else if (!strcmp(optarg, "exec")) - filter_mode |= EXEC_FILTER; + filter_mode |= EXEC_FILTER; else if (!strcmp(optarg, "pathname")) - filter_mode |= PATHNAME_FILTER; + filter_mode |= PATHNAME_FILTER; + break; + + case 'R': + RAW_flag = 1; + RAW_file = optarg; break; + case 'S': + start_time = atof(optarg); + break; + + case 'E': + end_time = atof(optarg); + break; + default: exit_usage(myname); } - } - + } + if (!RAW_flag) { + if ( geteuid() != 0 ) { + fprintf(stderr, "'fs_usage' must be run as root...\n"); + exit(1); + } + } argc -= optind; argv += optind; @@ -1779,72 +1932,78 @@ main(argc, argv) fprintf(stderr, "pid %d\n", pids[i]); } #endif - - /* set up signal handlers */ - signal(SIGINT, leave); - signal(SIGQUIT, leave); - - sigaction(SIGHUP, (struct sigaction *)NULL, &osa); - - if (osa.sa_handler == SIG_DFL) - signal(SIGHUP, leave); - signal(SIGTERM, leave); + if (!RAW_flag) { + + /* set up signal handlers */ + signal(SIGINT, leave); + signal(SIGQUIT, leave); + + sigaction(SIGHUP, (struct sigaction *)NULL, &osa); + + if (osa.sa_handler == SIG_DFL) + signal(SIGHUP, leave); + signal(SIGTERM, leave); + + /* grab the number of cpus */ + size_t len; + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + mib[2] = 0; + len = sizeof(num_cpus); + sysctl(mib, 2, &num_cpus, &len, NULL, 0); + num_events = EVENT_BASE * num_cpus; + } signal(SIGWINCH, sigwinch); - /* grab the number of cpus */ - size_t len; - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - mib[2] = 0; - len = sizeof(num_cpus); - sysctl(mib, 2, &num_cpus, &len, NULL, 0); - num_events = EVENT_BASE * num_cpus; - if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0) - quit("can't allocate memory for tracing info\n"); + quit("can't allocate memory for tracing info\n"); - if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32)) - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64); - else { - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32); - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64); + if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) { + ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64"); + } else { + ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc"); + ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64"); } SortFrameworkAddresses(); cache_disk_names(); - set_remove(); - set_numbufs(num_events); - set_init(); + if (!RAW_flag) { - if (exclude_pids == 0) { - for (i = 0; i < num_of_pids; i++) - set_pidcheck(pids[i], 1); - } else { - for (i = 0; i < num_of_pids; i++) - set_pidexclude(pids[i], 1); - } + set_remove(); + set_numbufs(num_events); + set_init(); - if (select_pid_mode && !one_good_pid) - { - /* - An attempt to restrict output to a given - pid or command has failed. Exit gracefully - */ - set_remove(); - exit_usage(myname); - } + if (exclude_pids == 0) { + for (i = 0; i < num_of_pids; i++) + set_pidcheck(pids[i], 1); + } else { + for (i = 0; i < num_of_pids; i++) + set_pidexclude(pids[i], 1); + } - set_enable(1); + if (select_pid_mode && !one_good_pid) + { + /* + An attempt to restrict output to a given + pid or command has failed. Exit gracefully + */ + set_remove(); + exit_usage(myname); + } + + set_enable(1); + init_arguments_buffer(); + } getdivisor(); - init_arguments_buffer(); init_tables(); /* main loop */ while (1) { - usleep(1000 * usleep_ms); + if (!RAW_flag) + usleep(1000 * usleep_ms); sample_sc(); @@ -1899,7 +2058,7 @@ void destroy_thread(struct th_info *ti) { struct th_info *find_empty(void) { - struct th_info *ti; + struct th_info *ti; for (ti = &th_state[cur_start]; ti < &th_state[MAX_THREADS]; ti++, cur_start++) { if (ti->thread == 0) { @@ -1915,7 +2074,7 @@ struct th_info *find_empty(void) { } -struct th_info *find_thread(int thread, int type) { +struct th_info *find_thread(uintptr_t thread, int type) { struct th_info *ti; for (ti = &th_state[0]; ti <= &th_state[cur_max]; ti++) { @@ -1936,7 +2095,7 @@ struct th_info *find_thread(int thread, int type) { void -mark_thread_waited(int thread) { +mark_thread_waited(uintptr_t thread) { struct th_info *ti; for (ti = th_state; ti <= &th_state[cur_max]; ti++) { @@ -2113,65 +2272,78 @@ sample_sc() kd_buf *kd; int i, count; size_t needed; + uint32_t my_buffer_size = 0; void read_command_map(); void create_map_entry(); - /* Get kernel buffer information */ - get_bufinfo(&bufinfo); - + if (!RAW_flag) { + /* Get kernel buffer information */ + get_bufinfo(&bufinfo); + } else { + my_buffer_size = num_events * sizeof(kd_buf); + } if (need_new_map) { read_command_map(); need_new_map = 0; } - needed = bufinfo.nkdbufs * sizeof(kd_buf); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDREADTR\n"); - count = needed; - - if (count > (SAMPLE_SIZE / 8)) { - if (usleep_ms > USLEEP_BEHIND) - usleep_ms = USLEEP_BEHIND; - else if (usleep_ms > USLEEP_MIN) - usleep_ms /= 2; - - } else if (count < (SAMPLE_SIZE / 16)) { - if (usleep_ms < USLEEP_MAX) - usleep_ms *= 2; - } + if (!RAW_flag) { + needed = bufinfo.nkdbufs * sizeof(kd_buf); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDREADTR; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; /* no flags */ + + if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDREADTR\n"); + count = needed; + + if (count > (num_events / 8)) { + if (usleep_ms > USLEEP_BEHIND) + usleep_ms = USLEEP_BEHIND; + else if (usleep_ms > USLEEP_MIN) + usleep_ms /= 2; + + } else if (count < (num_events / 16)) { + if (usleep_ms < USLEEP_MAX) + usleep_ms *= 2; + } - if (bufinfo.flags & KDBG_WRAPPED) { - fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count); + if (bufinfo.flags & KDBG_WRAPPED) { + fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count); - for (i = 0; i <= cur_max; i++) { - th_state[i].thread = 0; - th_state[i].pid = 0; - th_state[i].pathptr = (long *)NULL; - th_state[i].pathname[0] = 0; - } - cur_max = 0; - cur_start = 0; - need_new_map = 1; - map_is_the_same = 0; + for (i = 0; i <= cur_max; i++) { + th_state[i].thread = 0; + th_state[i].pid = 0; + th_state[i].pathptr = (uintptr_t *)NULL; + th_state[i].pathname[0] = 0; + } + cur_max = 0; + cur_start = 0; + need_new_map = 1; + map_is_the_same = 0; - set_enable(0); - set_enable(1); + set_enable(0); + set_enable(1); + } + } else { + int bytes_read; + + if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf)) + exit(0); + count = bytes_read / sizeof(kd_buf); } kd = (kd_buf *)my_buffer; #if 0 fprintf(stderr, "READTR returned %d items\n", count); #endif for (i = 0; i < count; i++) { - int debugid, thread; + uint32_t debugid; + uintptr_t thread; int type; - int index; - long *sargptr; + int index; + uintptr_t *sargptr; uint64_t now; long long l_usecs; int secs; @@ -2184,9 +2356,9 @@ sample_sc() debugid = kd[i].debugid; type = kd[i].debugid & DBG_FUNC_MASK; - now = kd[i].timestamp & KDBG_TIMESTAMP_MASK; + now = kdbg_get_timestamp(&kd[i]); - if (i == 0) + if (i == 0 && !RAW_flag) { curr_time = time((long *)0); /* @@ -2200,6 +2372,8 @@ sample_sc() bias_secs = curr_time - secs; } } + if (RAW_flag && bias_now == 0.0) + bias_now = now; if ((type & P_DISKIO_MASK) == P_DISKIO) { insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now); @@ -2268,6 +2442,7 @@ sample_sc() continue; break; + case MACH_idle: case MACH_sched: case MACH_stkhandoff: mark_thread_waited(thread); @@ -2295,8 +2470,8 @@ sample_sc() * kernel sends us more VFS_LOOKUP entries than we can * handle. */ - if (sargptr >= &ti->pathname[NUMPARMS]) { - continue; + if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname[NUMPARMS]) { + continue; } /* @@ -2343,16 +2518,30 @@ sample_sc() switch (type) { + case SPEC_ioctl: + if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE) + exit_syscall("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now); + else { + if ((ti = find_thread(thread, type))) { + destroy_thread(ti); + } + } + continue; + case MACH_pageout: if (kd[i].arg2) - exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); + exit_syscall("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); else - exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); + exit_syscall("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); continue; case MACH_vmfault: if (kd[i].arg4 == DBG_PAGEIN_FAULT) exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); + else if (kd[i].arg4 == DBG_PAGEINV_FAULT) + exit_syscall("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); + else if (kd[i].arg4 == DBG_PAGEIND_FAULT) + exit_syscall("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT) exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now); else { @@ -2415,7 +2604,7 @@ sample_sc() void -enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now) +enter_syscall_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now) { struct th_info *ti; int secs; @@ -2441,12 +2630,17 @@ enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now) if ((ti = find_empty()) == NULL) return; - if ((type & CLASS_MASK) == FILEMGR_BASE) { + if ((type & CLASS_MASK) == FILEMGR_BASE && + (!RAW_flag || (now >= start_time && now <= end_time))) { filemgr_in_progress++; ti->in_filemgr = 1; - l_usecs = (long long)(now / divisor); + if (RAW_flag) { + l_usecs = (long long)((now - bias_now) / divisor); + l_usecs += ((long long)8 * (long long)3600 * (long long)1000000); + } else + l_usecs = (long long)(now / divisor); secs = l_usecs / 1000000; curr_time = bias_secs + secs; @@ -2470,7 +2664,7 @@ enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now) nmclen = strlen(buf); printf("%s", buf); - sprintf(buf, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); + sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); argsclen = strlen(buf); /* @@ -2500,7 +2694,7 @@ enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now) else printf("%-12.12s\n", map->command); } else - printf(" %-24.24s (%5d, %#x, 0x%x, 0x%x)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); + printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); } ti->thread = thread; ti->waited = 0; @@ -2510,17 +2704,17 @@ enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now) ti->arg2 = kd->arg2; ti->arg3 = kd->arg3; ti->arg4 = kd->arg4; - ti->pathptr = (long *)NULL; + ti->pathptr = (uintptr_t *)NULL; ti->pathname[0] = 0; } void -enter_syscall(int thread, int type, kd_buf *kd, char *name, double now) +enter_syscall(uintptr_t thread, int type, kd_buf *kd, char *name, double now) { int index; - if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd) { + if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl) { enter_syscall_now(thread, type, kd, name, now); return; } @@ -2560,7 +2754,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now) */ void -extend_syscall(int thread, int type, kd_buf *kd) +extend_syscall(uintptr_t thread, int type, kd_buf *kd) { struct th_info *ti; @@ -2616,7 +2810,7 @@ extend_syscall(int thread, int type, kd_buf *kd) void -exit_syscall(char *sc_name, int thread, int type, int arg1, int arg2, int arg3, int arg4, +exit_syscall(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4, int format, double now) { struct th_info *ti; @@ -2688,7 +2882,7 @@ int clip_64bit(char *s, uint64_t value) void -format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, int arg2, int arg3, int arg4, +format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4, int format, double now, double stime, int waited, char *pathname, struct diskio *dio) { int secs; @@ -2707,17 +2901,29 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, uint64_t user_addr; uint64_t user_size; char *framework_name; + char *framework_type; char *p1; char *p2; char buf[MAXWIDTH]; command_name = ""; int need_msec_update = 0; static char timestamp[32]; - static int last_timestamp = 0; + static int last_timestamp = -1; static int timestamp_len = 0; static int last_msec = 0; + if (RAW_flag) { + l_usecs = (long long)((now - bias_now) / divisor); + + if ((double)l_usecs < start_time || (double)l_usecs > end_time) + return; + l_usecs += ((long long)8 * (long long)3600 * (long long)1000000); + } else + l_usecs = (long long)(now / divisor); + secs = l_usecs / 1000000; + curr_time = bias_secs + secs; + class = type >> 24; if (dio) @@ -2735,10 +2941,6 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, if (map) command_name = map->command; } - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - curr_time = bias_secs + secs; - if (last_timestamp != curr_time) { timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11])); last_timestamp = curr_time; @@ -2776,7 +2978,8 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, else clen = printf("%s %-17.17s", timestamp, sc_name); - framework_name = (char *)0; + + framework_name = NULL; if (columns > MAXCOLS || wideflag) { @@ -2830,7 +3033,8 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, * pagein */ user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3; - framework_name = lookup_name(user_addr); + + lookup_name(user_addr, &framework_type, &framework_name); clen += clip_64bit(" A=", user_addr); break; @@ -2840,7 +3044,7 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, */ user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3; - framework_name = lookup_name(user_addr); + lookup_name(user_addr, &framework_type, &framework_name); clen += clip_64bit(" A=", user_addr); break; @@ -2907,6 +3111,7 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, * fcntl */ char *p = NULL; + int fd = -1; if (arg1) clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); @@ -2979,6 +3184,21 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, p = "PATHPKG_CHECK"; break; + case F_OPENFROM: + p = "OPENFROM"; + + if (arg1 == 0) + fd = arg2; + break; + + case F_UNLINKFROM: + p = "UNLINKFROM"; + break; + + case F_CHECK_OPENEVT: + p = "CHECK_OPENEVT"; + break; + case F_NOCACHE: if (ti->arg3) p = "CACHING OFF"; @@ -2986,10 +3206,20 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, p = "CACHING ON"; break; + case F_GLOBAL_NOCACHE: + if (ti->arg3) + p = "CACHING OFF (GLOBAL)"; + else + p = "CACHING ON (GLOBAL)"; + break; + } - if (p) - clen += printf(" <%s>", p); - else + if (p) { + if (fd == -1) + clen += printf(" <%s>", p); + else + clen += printf(" <%s> F=%d", p, fd); + } else clen += printf(" ", ti->arg2); break; @@ -3010,6 +3240,16 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, break; } + case FMT_SPEC_IOCTL: + { + /* + * fcntl + */ + clen += printf(" /dev/%s", find_disk_name(arg1)); + + break; + } + case FMT_SELECT: /* * select @@ -3178,6 +3418,7 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, break; } + case FMT_UMASK: case FMT_FCHMOD: case FMT_FCHMOD_EXT: case FMT_CHMOD: @@ -3199,7 +3440,9 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, else clen += printf(" "); } - if (format == FMT_FCHMOD || format == FMT_CHMOD) + if (format == FMT_UMASK) + mode = ti->arg1; + else if (format == FMT_FCHMOD || format == FMT_CHMOD) mode = ti->arg2; else mode = ti->arg4; @@ -3207,7 +3450,7 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, get_mode_string(mode, &buf[0]); if (arg1 == 0) - clen += printf("<%s> ", buf); + clen += printf("<%s> ", buf); else clen += printf("<%s>", buf); break; @@ -3456,7 +3699,7 @@ format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, clen -= 3; if (framework_name) - len = sprintf(&buf[0], " %s ", framework_name); + len = sprintf(&buf[0], " %s %s ", framework_type, framework_name); else if (*pathname != '\0') len = sprintf(&buf[0], " %s ", pathname); else @@ -3558,31 +3801,63 @@ void read_command_map() } prev_total_threads = total_threads; - total_threads = bufinfo.nkdthreads; - size = bufinfo.nkdthreads * sizeof(kd_threadmap); - if (size) - { - if ((mapptr = (kd_threadmap *) malloc(size))) - { - bzero (mapptr, size); + if (!RAW_flag) { + + total_threads = bufinfo.nkdthreads; + size = bufinfo.nkdthreads * sizeof(kd_threadmap); + + if (size) + { + if ((mapptr = (kd_threadmap *) malloc(size))) + { + bzero (mapptr, size); - /* Now read the threadmap */ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDTHRMAP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) - { - /* This is not fatal -- just means I cant map command strings */ - free(mapptr); - mapptr = 0; - } - } - } + /* Now read the threadmap */ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDTHRMAP; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; /* no flags */ + if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) + { + /* This is not fatal -- just means I cant map command strings */ + free(mapptr); + mapptr = 0; + } + } + } + } else { + uint32_t count_of_names; + + RAW_fd = open(RAW_file, O_RDONLY); + if (RAW_fd < 0) { + perror("Can't open RAW file"); + exit(1); + } + if (read(RAW_fd, &count_of_names, sizeof(uint32_t)) != sizeof(uint32_t)) { + perror("read of RAW file failed"); + exit(2); + } + total_threads = count_of_names; + size = count_of_names * sizeof(kd_threadmap); + + if (size) + { + if ((mapptr = (kd_threadmap *) malloc(size))) + { + bzero (mapptr, size); + + if (read(RAW_fd, mapptr, size) != size) { + + free(mapptr); + mapptr = 0; + } + } + } + } if (mapptr && (filter_mode & (NETWORK_FILTER | FILESYS_FILTER))) { if (fdmapptr) @@ -3633,7 +3908,7 @@ void read_command_map() } -void create_map_entry(int thread, int pid, char *command) +void create_map_entry(uintptr_t thread, int pid, char *command) { int i, n; kd_threadmap *map; @@ -3644,7 +3919,7 @@ void create_map_entry(int thread, int pid, char *command) for (i = 0, map = 0; !map && i < total_threads; i++) { - if ((int)mapptr[i].thread == thread ) + if (mapptr[i].thread == thread ) { map = &mapptr[i]; /* Reuse this entry, the thread has been * reassigned */ @@ -3721,7 +3996,7 @@ void create_map_entry(int thread, int pid, char *command) } -kd_threadmap *find_thread_map(int thread) +kd_threadmap *find_thread_map(uintptr_t thread) { int i; kd_threadmap *map; @@ -3732,7 +4007,7 @@ kd_threadmap *find_thread_map(int thread) for (i = 0; i < total_threads; i++) { map = &mapptr[i]; - if (map->valid && ((int)map->thread == thread)) + if (map->valid && (map->thread == thread)) { return(map); } @@ -3740,7 +4015,7 @@ kd_threadmap *find_thread_map(int thread) return ((kd_threadmap *)0); } -fd_threadmap *find_fd_thread_map(int thread) +fd_threadmap *find_fd_thread_map(uintptr_t thread) { int i; fd_threadmap *fdmap = 0; @@ -3751,7 +4026,7 @@ fd_threadmap *find_fd_thread_map(int thread) for (i = 0; i < total_threads; i++) { fdmap = &fdmapptr[i]; - if (fdmap->fd_valid && ((int)fdmap->fd_thread == thread)) + if (fdmap->fd_valid && (fdmap->fd_thread == thread)) { return(fdmap); } @@ -3761,7 +4036,7 @@ fd_threadmap *find_fd_thread_map(int thread) void -kill_thread_map(int thread) +kill_thread_map(uintptr_t thread) { kd_threadmap *map; fd_threadmap *fdmap; @@ -3823,32 +4098,37 @@ argtopid(str) -char *lookup_name(uint64_t user_addr) +void +lookup_name(uint64_t user_addr, char **type, char **name) { - register int i; - register int start, last; + int i; + int start, last; - if (numFrameworks && ((user_addr >= framework32.b_address && user_addr < framework32.e_address) || - (user_addr >= framework64.b_address && user_addr < framework64.e_address))) { - - start = 0; - last = numFrameworks; - - for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) { + *name = NULL; + *type = NULL; - if (user_addr >= frameworkInfo[i].b_address && user_addr < frameworkInfo[i].e_address) - return(frameworkInfo[i].name); + if (numFrameworks) { - if (user_addr >= frameworkInfo[i].b_address) { - start = i; - i = start + ((last - i) / 2); - } else { - last = i; - i = start + ((i - start) / 2); + if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) || + (user_addr >= framework64.b_address && user_addr < framework64.e_address)) { + + start = 0; + last = numFrameworks; + + for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) { + if (user_addr > frameworkInfo[i].e_address) { + start = i+1; + } else { + last = i; + } + } + if (start < numFrameworks && + user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) { + *type = frameworkType[frameworkInfo[start].r_type]; + *name = frameworkInfo[start].name; } } } - return (0); } @@ -3882,18 +4162,18 @@ int scanline(char *inputstring, char **argv, int maxtokens) } -int ReadSharedCacheMap(const char *path, LibraryRange *lr) +int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) { - char buf[1024]; - - FILE *fd; - uint64_t b_frameworkAddress, b_frameworkDataAddress; - uint64_t e_frameworkAddress, e_frameworkDataAddress; - char frameworkName[256]; - char *tokens[64]; - int ntokens; - char *substring,*ptr; - + uint64_t b_address, e_address; + char buf[1024]; + char *fnp; + FILE *fd; + char frameworkName[256]; + char *tokens[64]; + int ntokens; + int type; + int linkedit_found = 0; + char *substring, *ptr; bzero(buf, sizeof(buf)); bzero(tokens, sizeof(tokens)); @@ -3901,7 +4181,6 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr) lr->b_address = 0; lr->e_address = 0; - if ((fd = fopen(path, "r")) == 0) { return 0; @@ -3915,11 +4194,6 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr) frameworkName[0] = 0; for (;;) { - b_frameworkAddress = 0; - b_frameworkDataAddress = 0; - e_frameworkAddress = 0; - e_frameworkDataAddress = 0; - /* * Extract lib name from path name */ @@ -3957,6 +4231,9 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr) strncpy(frameworkName, substring, 256); frameworkName[255] = 0; } + fnp = (char *)malloc(strlen(frameworkName) + 1); + strcpy(fnp, frameworkName); + while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) { /* @@ -3969,48 +4246,52 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr) if (ntokens < 4) continue; - if (strncmp(tokens[0], "__TEXT", 6) == 0) { - b_frameworkAddress = strtoull(tokens[1], 0, 16); - e_frameworkAddress = strtoull(tokens[3], 0, 16); - } else if (strncmp(tokens[0], "__DATA", 6) == 0) { - b_frameworkDataAddress = strtoull(tokens[1], 0, 16); - e_frameworkDataAddress = strtoull(tokens[3], 0, 16); - } else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0) - break; - } - /* - * Make sure that we have 2 addresses - */ - if (b_frameworkAddress && b_frameworkDataAddress) { - - frameworkInfo[numFrameworks].b_address = b_frameworkAddress; - frameworkInfo[numFrameworks].e_address = e_frameworkAddress; + if (strncmp(tokens[0], "__TEXT", 6) == 0) + type = TEXT_R; + else if (strncmp(tokens[0], "__DATA", 6) == 0) + type = DATA_R; + else if (strncmp(tokens[0], "__OBJC", 6) == 0) + type = OBJC_R; + else if (strncmp(tokens[0], "__IMPORT", 8) == 0) + type = IMPORT_R; + else if (strncmp(tokens[0], "__UNICODE", 9) == 0) + type = UNICODE_R; + else if (strncmp(tokens[0], "__IMAGE", 7) == 0) + type = IMAGE_R; + else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0) + type = LINKEDIT_R; + else + type = -1; - frameworkInfo[numFrameworks+1].b_address = b_frameworkDataAddress; - frameworkInfo[numFrameworks+1].e_address = e_frameworkDataAddress; + if (type == LINKEDIT_R && linkedit_found) + break; - frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1); - strcpy(frameworkInfo[numFrameworks].name, frameworkName); - frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name; + if (type != -1) { + b_address = strtoull(tokens[1], 0, 16); + e_address = strtoull(tokens[3], 0, 16); - numFrameworks += 2; + frameworkInfo[numFrameworks].b_address = b_address; + frameworkInfo[numFrameworks].e_address = e_address; + frameworkInfo[numFrameworks].r_type = type; + + if (type == LINKEDIT_R) { + frameworkInfo[numFrameworks].name = linkedit_name; + linkedit_found = 1; + } else + frameworkInfo[numFrameworks].name = fnp; #if 0 - printf("%s: %qx-%qx %qx-%qx\n", frameworkName, b_frameworkAddress, e_frameworkAddress, b_frameworkDataAddress, e_frameworkDataAddress); + printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address); #endif - if (lr->b_address == 0) - lr->b_address = b_frameworkAddress; + if (lr->b_address == 0 || b_address < lr->b_address) + lr->b_address = b_address; - if (b_frameworkAddress < lr->b_address) - lr->b_address = b_frameworkAddress; + if (lr->e_address == 0 || e_address > lr->e_address) + lr->e_address = e_address; - if (b_frameworkDataAddress < lr->b_address) - lr->b_address = b_frameworkDataAddress; - - if (e_frameworkAddress > lr->e_address) - lr->e_address = e_frameworkAddress; - - if (e_frameworkDataAddress > lr->e_address) - lr->e_address = e_frameworkDataAddress; + numFrameworks++; + } + if (type == LINKEDIT_R) + break; } if (fgets(buf, 1023, fd) == 0) break; @@ -4019,6 +4300,9 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr) } fclose(fd); +#if 0 + printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address); +#endif return 1; } @@ -4035,7 +4319,7 @@ SortFrameworkAddresses() } -struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, int thread, double curtime) +struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime) { register struct diskio *dio; register kd_threadmap *map; @@ -4073,7 +4357,7 @@ struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, } -struct diskio *complete_diskio(int bp, int io_errno, int resid, int thread, double curtime) +struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime) { register struct diskio *dio; @@ -4197,16 +4481,36 @@ void cache_disk_names() } +void recache_disk_names() +{ + struct diskrec *dnp, *next_dnp; + + for (dnp = disk_list; dnp; dnp = next_dnp) { + next_dnp = dnp->next; + + free(dnp->diskname); + free(dnp); + } + disk_list = NULL; + + cache_disk_names(); +} + + char *find_disk_name(int dev) { struct diskrec *dnp; + int i; if (dev == NFS_DEV) return ("NFS"); - for (dnp = disk_list; dnp; dnp = dnp->next) { - if (dnp->dev == dev) - return (dnp->diskname); + for (i = 0; i < 2; i++) { + for (dnp = disk_list; dnp; dnp = dnp->next) { + if (dnp->dev == dev) + return (dnp->diskname); + } + recache_disk_names(); } return ("NOTFOUND"); } @@ -4495,7 +4799,7 @@ get_real_command_name(int pid, char *cbuf, int csize) * was called with. */ mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS; + mib[1] = KERN_PROCARGS2; mib[2] = pid; mib[3] = 0; diff --git a/getconf.tproj/Makefile b/getconf.tproj/Makefile index 5e86b05..aa855d9 100644 --- a/getconf.tproj/Makefile +++ b/getconf.tproj/Makefile @@ -9,8 +9,10 @@ CFILES = getconf.c \ $(OBJROOT)/$(Project)/sysconf.c MANPAGES = getconf.1 -Extra_CC_Flags = -include _fbsd_compat.h -DAPPLE_GETCONF_UNDERSCORE \ +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -include _fbsd_compat.h -DAPPLE_GETCONF_UNDERSCORE \ -DAPPLE_GETCONF_SPEC -I. +Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/getconf.tproj/getconf.1 b/getconf.tproj/getconf.1 index d28bccb..384f780 100644 --- a/getconf.tproj/getconf.1 +++ b/getconf.tproj/getconf.1 @@ -26,7 +26,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.bin/getconf/getconf.1,v 1.12 2003/09/08 19:57:21 ru Exp $ +.\" $FreeBSD: src/usr.bin/getconf/getconf.1,v 1.14 2005/01/18 13:43:49 ru Exp $ .\" .Dd September 18, 2002 .Dt GETCONF 1 @@ -149,22 +149,8 @@ to use the standard programming environments described above. Many of these values are also available through the .Xr sysctl 8 mechanism. -.Sh DIAGNOSTICS +.Sh EXIT STATUS .Ex -std -Use of a -.Ar system_var -or -.Ar path_var -which is completely unrecognized is considered an error, -causing a diagnostic message to be written to standard error. -One -which is known but merely undefined does not result in an error -indication. -The -.Nm -utility recognizes all of the variables defined for -.St -p1003.1-2001 , -including those which are not currently implemented. .Sh EXAMPLES The command: .Pp @@ -192,6 +178,21 @@ in the .Li POSIX_V6_LPBIG_OFFBIG programming environment, if the system supports that environment. +.Sh DIAGNOSTICS +Use of a +.Ar system_var +or +.Ar path_var +which is completely unrecognized is considered an error, +causing a diagnostic message to be written to standard error. +One +which is known but merely undefined does not result in an error +indication. +The +.Nm +utility recognizes all of the variables defined for +.St -p1003.1-2001 , +including those which are not currently implemented. .Sh SEE ALSO .Xr pathconf 2 , .Xr confstr 3 , diff --git a/getconf.tproj/getconf.c b/getconf.tproj/getconf.c index 9cb0b7d..5ee262d 100644 --- a/getconf.tproj/getconf.c +++ b/getconf.tproj/getconf.c @@ -28,7 +28,7 @@ */ #include -__FBSDID("$FreeBSD: src/usr.bin/getconf/getconf.c,v 1.9 2003/08/22 17:32:07 markm Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/getconf/getconf.c,v 1.10 2006/12/06 12:00:26 maxim Exp $"); #include @@ -139,21 +139,23 @@ static void do_confstr(const char *name, int key) { size_t len; + int savederr; + savederr = errno; errno = 0; len = confstr(key, 0, 0); if (len == 0) { - if (errno != 0) { + if (errno) err(EX_OSERR, "confstr: %s", name); - } else { + else printf("undefined\n"); - } } else { char buf[len + 1]; confstr(key, buf, len); printf("%s\n", buf); } + errno = savederr; } static void diff --git a/getconf.tproj/progenv.gperf b/getconf.tproj/progenv.gperf index 4f2319f..4e3245a 100644 --- a/getconf.tproj/progenv.gperf +++ b/getconf.tproj/progenv.gperf @@ -37,7 +37,7 @@ static const struct map *in_word_set(const char *str); #define have_LPBIG_OFFBIG NULL #endif -#if defined(__i386__) || defined(__powerpc__) +#if defined(__i386__) || defined(__powerpc__) || defined(__x86_64__) #define have_ILP32_OFFBIG NULL #endif diff --git a/getty.tproj/Makefile b/getty.tproj/Makefile index 8c6b7a3..fe7ba77 100644 --- a/getty.tproj/Makefile +++ b/getty.tproj/Makefile @@ -10,4 +10,12 @@ ifeq ($(Embedded),YES) LAUNCHD_PLISTS = com.apple.getty.plist endif +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +ifeq ($(Embedded),YES) +after_install: + plutil -convert binary1 "$(DSTROOT)/System/Library/LaunchDaemons/$(LAUNCHD_PLISTS)" +endif diff --git a/getty.tproj/extern.h b/getty.tproj/extern.h index 76fdf44..34bc85d 100644 --- a/getty.tproj/extern.h +++ b/getty.tproj/extern.h @@ -49,7 +49,7 @@ const char *autobaud(void); int delaybits(void); void edithost(const char *); void gendefaults(void); -void gettable(const char *, char *); +void gettable(const char *); void makeenv(char *[]); const char *portselector(void); void set_ttydefaults(int); diff --git a/getty.tproj/main.c b/getty.tproj/main.c index c25373c..ee1361d 100644 --- a/getty.tproj/main.c +++ b/getty.tproj/main.c @@ -111,8 +111,6 @@ char ttyn[32]; #define OBUFSIZ 128 #define TABBUFSIZ 512 -char defent[TABBUFSIZ]; -char tabent[TABBUFSIZ]; const char *tname; char *env[128]; @@ -214,7 +212,7 @@ main(int argc, char *argv[]) limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); - gettable("default", defent); + gettable("default"); gendefaults(); tname = "default"; if (argc > 1) @@ -842,7 +840,7 @@ dogettytab() { /* Read the database entry. */ - gettable(tname, tabent); + gettable(tname); /* * Avoid inheriting the parity values from the default entry diff --git a/getty.tproj/subr.c b/getty.tproj/subr.c index 5c3fb85..7a9abc2 100644 --- a/getty.tproj/subr.c +++ b/getty.tproj/subr.c @@ -64,8 +64,9 @@ static const char rcsid[] = * Get a table entry. */ void -gettable(const char *name, char *buf) +gettable(const char *name) { + char *buf = NULL; struct gettystrs *sp; struct gettynums *np; struct gettyflags *fp; @@ -175,6 +176,8 @@ gettable(const char *name, char *buf) printf("cgetflags: %s='%c' set='%c'\r\n", fp->field, fp->value + '0', fp->set + '0'); #endif /* DEBUG */ + + free(buf); } void diff --git a/hostinfo.tproj/Makefile b/hostinfo.tproj/Makefile index c958a9d..2b6dcc4 100644 --- a/hostinfo.tproj/Makefile +++ b/hostinfo.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/bin CFILES = hostinfo.c MANPAGES = hostinfo.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/hostinfo.tproj/hostinfo.8 b/hostinfo.tproj/hostinfo.8 index 770a843..c24e7ab 100644 --- a/hostinfo.tproj/hostinfo.8 +++ b/hostinfo.tproj/hostinfo.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2003 Apple Computer, Inc. All rights reserved. +.\" Copyright (c) 2003-2009 Apple Inc. All rights reserved. .\" .\" The contents of this file constitute Original Code as defined in and .\" are subject to the Apple Public Source License Version 1.1 (the @@ -48,6 +48,11 @@ The version string compiled into the kernel executing on the host system. The maximum possible processors for which the kernel is configured, followed by the number of physical and logical processors available. .Pp +Note: on Intel architectures, physical processors are referred to as cores, and +logical processors are referred to as hardware threads; there may be multiple +logical processors per core and multiple cores per processor package. +This command does not report the number of processor packages. +.Pp .It Processor type: The host's processor type and subtype. .Pp diff --git a/iostat.tproj/Makefile b/iostat.tproj/Makefile index ef85974..b6a5ca7 100644 --- a/iostat.tproj/Makefile +++ b/iostat.tproj/Makefile @@ -3,6 +3,10 @@ Install_Dir = /usr/sbin CFILES = iostat.c MANPAGES = iostat.8 + +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + Extra_Frameworks = -framework CoreFoundation -framework IOKit include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/iostat.tproj/iostat.c b/iostat.tproj/iostat.c index ea2cb74..2713ef4 100644 --- a/iostat.tproj/iostat.c +++ b/iostat.tproj/iostat.c @@ -864,10 +864,8 @@ static void remove_drivelist(void* context, io_iterator_t drivelist) /* get name from properties */ name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)); - CFRelease(properties); - if (!name) continue; - if (CFStringGetCString(name, bsdname, MAXDRIVENAME, CFStringGetSystemEncoding())) { + if (name && CFStringGetCString(name, bsdname, MAXDRIVENAME, CFStringGetSystemEncoding())) { int i; for (i = 0; i < num_devices; ++i) { if (strcmp(bsdname,drivestat[i].name) == 0) { @@ -881,7 +879,7 @@ static void remove_drivelist(void* context, io_iterator_t drivelist) } } } - + CFRelease(properties); IOObjectRelease(drive); } } diff --git a/kgmon.tproj/Makefile b/kgmon.tproj/Makefile deleted file mode 100644 index 9436b34..0000000 --- a/kgmon.tproj/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Generated by the NeXT Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = kgmon - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Tool - -CFILES = kgmon.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kgmon.8 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = tool.make -NEXTSTEP_INSTALLDIR = /usr/sbin -WINDOWS_INSTALLDIR = /usr/sbin -PDO_UNIX_INSTALLDIR = /usr/sbin -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/kgmon.tproj/kgmon.8 b/kgmon.tproj/kgmon.8 deleted file mode 100644 index da55da4..0000000 --- a/kgmon.tproj/kgmon.8 +++ /dev/null @@ -1,128 +0,0 @@ -.\" Copyright (c) 1983, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)kgmon.8 8.1 (Berkeley) 6/6/93 -.\" -.Dd June 6, 1993 -.Dt KGMON 8 -.Os BSD 4.2 -.Sh NAME -.Nm kgmon -.Nd generate a dump of the operating system's profile buffers -.Sh SYNOPSIS -.Nm kgmon -.Op Fl bhpr -.Op Fl M core -.Op Fl N system -.Sh DESCRIPTION -.Nm Kgmon -is a tool used when profiling the operating system. -When no arguments are supplied, -.Nm kgmon -indicates the state of operating system profiling as running, -off, or not configured. -(see -.Xr config 8 ) -If the -.Fl p -flag is specified, -.Nm kgmon -extracts profile data from the operating system and produces a -.Pa gmon.out -file suitable for later analysis by -.Xr gprof 1 . -.Pp -The options are as follows: -.Bl -tag -width Ds -.\" ========== -.It Fl b -Resume the collection of profile data. -.\" ========== -.It Fl h -Stop the collection of profile data. -.\" ========== -.It Fl M -Extract values associated with the name list from the specified core -instead of the default ``/dev/kmem''. -.\" ========== -.It Fl N -Extract the name list from the specified system instead of the -default ``/vmunix''. -.\" ========== -.It Fl p -Dump the contents of the profile buffers into a -.Pa gmon.out -file. -.\" ========== -.It Fl r -Reset all the profile buffers. -If the -.Fl p -flag is also specified, the -.Pa gmon.out -file is generated before the buffers are reset. -.El -.Pp -If neither -.Fl b -nor -.Fl h -is specified, the state of profiling collection remains unchanged. -For example, if the -.Fl p -flag is specified and profile data is being collected, -profiling will be momentarily suspended, -the operating system profile buffers will be dumped, -and profiling will be immediately resumed. -.Sh FILES -.Bl -tag -width /dev/kmemx -compact -.It Pa /vmunix -the default system -.It Pa /dev/kmem -the default memory -.El -.Sh SEE ALSO -.Xr gprof 1 , -.Xr config 8 -.Sh DIAGNOSTICS -Users with only read permission on -.Pa /dev/kmem -cannot change the state -of profiling collection. -If profiling is in progress, -they can get a -.Pa gmon.out -file containing a warning that the data may be inconsistent. -.Sh HISTORY -The -.Nm kgmon -command appeared in -.Bx 4.2 . diff --git a/kgmon.tproj/kgmon.c b/kgmon.tproj/kgmon.c deleted file mode 100644 index 84999be..0000000 --- a/kgmon.tproj/kgmon.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 1983, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef __APPLE__ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1983, 1992, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93"; -#endif -static const char rcsid[] = - "$FreeBSD: src/usr.sbin/kgmon/kgmon.c,v 1.14 2004/08/30 03:11:46 marcel Exp $"; -#endif /* not lint */ -#endif /* !__APPLE__ */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct nlist nl[] = { -#define N_GMONPARAM 0 - { "__gmonparam" }, -#define N_PROFHZ 1 - { "_profhz" }, - { NULL }, -}; - -struct kvmvars { - kvm_t *kd; - struct gmonparam gpm; -}; - -int Bflag, bflag, hflag, kflag, rflag, pflag; -int debug = 0; -int getprof(struct kvmvars *); -int getprofhz(struct kvmvars *); -void kern_readonly(int); -int openfiles(char *, char *, struct kvmvars *); -void setprof(struct kvmvars *kvp, int state); -void dumpstate(struct kvmvars *kvp); -void reset(struct kvmvars *kvp); -static void usage(void); - -int -main(int argc, char **argv) -{ -#ifdef __APPLE__ - extern char *optarg; - extern int optind; -#endif - int ch, mode, disp, accessmode; - struct kvmvars kvmvars; - char *system, *kmemf; - - seteuid(getuid()); - kmemf = NULL; - system = NULL; -#ifdef __APPLE__ - while ((ch = getopt(argc, argv, "M:N:bhpr")) != -1) { -#else - while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != -1) { -#endif - switch((char)ch) { - - case 'M': - kmemf = optarg; - kflag = 1; - break; - - case 'N': - system = optarg; - break; - -#ifndef __APPLE__ - case 'B': - Bflag = 1; - break; -#endif - - case 'b': - bflag = 1; - break; - - case 'h': - hflag = 1; - break; - - case 'p': - pflag = 1; - break; - - case 'r': - rflag = 1; - break; - - default: - usage(); - } - } - argc -= optind; - argv += optind; - -#define BACKWARD_COMPATIBILITY -#ifdef BACKWARD_COMPATIBILITY - if (*argv) { - system = *argv; - if (*++argv) { - kmemf = *argv; - ++kflag; - } - } -#endif - if (system == NULL) -#ifdef __APPLE__ - system = _PATH_UNIX; -#else - system = (char *)getbootfile(); -#endif - accessmode = openfiles(system, kmemf, &kvmvars); - mode = getprof(&kvmvars); - if (hflag) - disp = GMON_PROF_OFF; -#ifndef __APPLE__ - else if (Bflag) - disp = GMON_PROF_HIRES; -#endif - else if (bflag) - disp = GMON_PROF_ON; - else - disp = mode; - if (pflag) - dumpstate(&kvmvars); - if (rflag) - reset(&kvmvars); - if (accessmode == O_RDWR) - setprof(&kvmvars, disp); - (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n", -#ifndef __APPLE__ - disp == GMON_PROF_OFF ? "off" : - disp == GMON_PROF_HIRES ? "running (high resolution)" : - disp == GMON_PROF_ON ? "running" : - disp == GMON_PROF_BUSY ? "busy" : - disp == GMON_PROF_ERROR ? "off (error)" : - "in an unknown state"); -#else - disp == GMON_PROF_OFF ? "off" : "running"); -#endif /* __APPLE__ */ - return (0); -} - -static void -usage() -{ -#ifdef __APPLE__ - fprintf(stderr, "usage: kgmon [-bhrp]\n"); -#else - fprintf(stderr, "usage: kgmon [-Bbhrp] [-M core] [-N system]\n"); -#endif - exit(1); -} - -/* - * Check that profiling is enabled and open any ncessary files. - */ -int -openfiles(system, kmemf, kvp) - char *system; - char *kmemf; - struct kvmvars *kvp; -{ - size_t size; - int mib[3], state, openmode; - char errbuf[_POSIX2_LINE_MAX]; - - if (!kflag) { - mib[0] = CTL_KERN; - mib[1] = KERN_PROF; - mib[2] = GPROF_STATE; - size = sizeof state; - if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) - errx(20, "profiling not defined in kernel"); -#ifdef __APPLE__ - if (!(bflag || hflag || rflag || - (pflag && (state == GMON_PROF_ON)))) - return (O_RDONLY); -#else - if (!(Bflag || bflag || hflag || rflag || - (pflag && - (state == GMON_PROF_HIRES || state == GMON_PROF_ON)))) - return (O_RDONLY); -#endif - (void)seteuid(0); - if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0) - return (O_RDWR); - (void)seteuid(getuid()); - kern_readonly(state); - return (O_RDONLY); - } -#ifdef __APPLE__ - openmode = (bflag || hflag || pflag || rflag) -#else - openmode = (Bflag || bflag || hflag || pflag || rflag) -#endif - ? O_RDWR : O_RDONLY; - kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf); - if (kvp->kd == NULL) { - if (openmode == O_RDWR) { - openmode = O_RDONLY; - kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY, - errbuf); - } - if (kvp->kd == NULL) - errx(2, "kvm_openfiles: %s", errbuf); - kern_readonly(GMON_PROF_ON); - } - if (kvm_nlist(kvp->kd, nl) < 0) - errx(3, "%s: no namelist", system); - if (!nl[N_GMONPARAM].n_value) - errx(20, "profiling not defined in kernel"); - return (openmode); -} - -/* - * Suppress options that require a writable kernel. - */ -void -kern_readonly(mode) - int mode; -{ - - (void)fprintf(stderr, "kgmon: kernel read-only: "); -#ifdef __APPLE__ - if (pflag && mode == GMON_PROF_ON) -#else - if (pflag && (mode == GMON_PROF_HIRES || mode == GMON_PROF_ON)) -#endif - (void)fprintf(stderr, "data may be inconsistent\n"); - if (rflag) - (void)fprintf(stderr, "-r supressed\n"); -#ifndef __APPLE__ - if (Bflag) - (void)fprintf(stderr, "-B supressed\n"); -#endif - if (bflag) - (void)fprintf(stderr, "-b supressed\n"); - if (hflag) - (void)fprintf(stderr, "-h supressed\n"); -#ifdef __APPLE__ - rflag = bflag = hflag = 0; -#else - rflag = Bflag = bflag = hflag = 0; -#endif -} - -/* - * Get the state of kernel profiling. - */ -int -getprof(kvp) - struct kvmvars *kvp; -{ - size_t size; - int mib[3]; - - if (kflag) { - size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm, - sizeof kvp->gpm); - } else { - mib[0] = CTL_KERN; - mib[1] = KERN_PROF; - mib[2] = GPROF_GMONPARAM; - size = sizeof kvp->gpm; - if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0) - size = 0; - } - -#ifdef __APPLE__ - if (size != sizeof kvp->gpm) - errx(4, "cannot get gmonparam: %s", - kflag ? kvm_geterr(kvp->kd) : strerror(errno)); -#else /* __APPLE__ */ - /* - * Accept certain undersized "structs" from old kernels. We need - * everything up to hashfraction, and want profrate and - * histcounter_type. Assume that the kernel doesn't put garbage - * in any padding that is returned instead of profrate and - * histcounter_type. This is a bad assumption for dead kernels, - * since kvm_read() will normally return garbage for bytes beyond - * the end of the actual kernel struct, if any. - */ - if (size < offsetof(struct gmonparam, hashfraction) + - sizeof(kvp->gpm.hashfraction) || size > sizeof(kvp->gpm)) - errx(4, "cannot get gmonparam: %s", - kflag ? kvm_geterr(kvp->kd) : strerror(errno)); - bzero((char *)&kvp->gpm + size, sizeof(kvp->gpm) - size); - if (kvp->gpm.profrate == 0) - kvp->gpm.profrate = getprofhz(kvp); -#ifdef __i386__ - if (kvp->gpm.histcounter_type == 0) { - /* - * This fixup only works for not-so-old i386 kernels. The - * magic 16 is the kernel FUNCTION_ALIGNMENT. 64-bit - * counters are signed; smaller counters are unsigned. - */ - kvp->gpm.histcounter_type = 16 / - (kvp->gpm.textsize / kvp->gpm.kcountsize) * CHAR_BIT; - if (kvp->gpm.histcounter_type == 64) - kvp->gpm.histcounter_type = -64; - } -#endif -#endif /* __APPLE__ */ - - return (kvp->gpm.state); -} - -/* - * Enable or disable kernel profiling according to the state variable. - */ -void -setprof(kvp, state) - struct kvmvars *kvp; - int state; -{ - struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value; - size_t sz; - int mib[3], oldstate; - - sz = sizeof(state); - if (!kflag) { - mib[0] = CTL_KERN; - mib[1] = KERN_PROF; - mib[2] = GPROF_STATE; - if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0) - goto bad; - if (oldstate == state) - return; - (void)seteuid(0); - if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) { - (void)seteuid(getuid()); - return; - } - (void)seteuid(getuid()); - } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) - == sz) - return; -bad: - warnx("warning: cannot turn profiling %s", - state == GMON_PROF_OFF ? "off" : "on"); -} - -/* - * Build the gmon.out file. - */ -void -dumpstate(kvp) - struct kvmvars *kvp; -{ - register FILE *fp; - struct rawarc rawarc; - struct tostruct *tos; - u_long frompc; - u_short *froms, *tickbuf; - size_t i; - int mib[3]; - struct gmonhdr h; - int fromindex, endfrom, toindex; - - setprof(kvp, GMON_PROF_OFF); - fp = fopen("gmon.out", "w"); - if (fp == 0) { - warn("gmon.out"); - return; - } - - /* - * Build the gmon header and write it to a file. - */ - bzero(&h, sizeof(h)); - h.lpc = kvp->gpm.lowpc; - h.hpc = kvp->gpm.highpc; - h.ncnt = kvp->gpm.kcountsize + sizeof(h); - h.version = GMONVERSION; -#ifdef __APPLE__ - h.profrate = getprofhz(kvp); -#else - h.profrate = kvp->gpm.profrate; - h.histcounter_type = kvp->gpm.histcounter_type; -#endif - fwrite((char *)&h, sizeof(h), 1, fp); - - /* - * Write out the tick buffer. - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROF; - if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) - errx(5, "cannot allocate kcount space"); - if (kflag) { - i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf, - kvp->gpm.kcountsize); - } else { - mib[2] = GPROF_COUNT; - i = kvp->gpm.kcountsize; - if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0) - i = 0; - } - if (i != kvp->gpm.kcountsize) - errx(6, "read ticks: read %lu, got %ld: %s", - kvp->gpm.kcountsize, (long)i, - kflag ? kvm_geterr(kvp->kd) : strerror(errno)); - if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) - err(7, "writing tocks to gmon.out"); - free(tickbuf); - - /* - * Write out the arc info. - */ - if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) - errx(8, "cannot allocate froms space"); - if (kflag) { - i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms, - kvp->gpm.fromssize); - } else { - mib[2] = GPROF_FROMS; - i = kvp->gpm.fromssize; - if (sysctl(mib, 3, froms, &i, NULL, 0) < 0) - i = 0; - } - if (i != kvp->gpm.fromssize) - errx(9, "read froms: read %lu, got %ld: %s", - kvp->gpm.fromssize, (long)i, - kflag ? kvm_geterr(kvp->kd) : strerror(errno)); - if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) - errx(10, "cannot allocate tos space"); - if (kflag) { - i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos, - kvp->gpm.tossize); - } else { - mib[2] = GPROF_TOS; - i = kvp->gpm.tossize; - if (sysctl(mib, 3, tos, &i, NULL, 0) < 0) - i = 0; - } - if (i != kvp->gpm.tossize) - errx(11, "read tos: read %lu, got %ld: %s", - kvp->gpm.tossize, (long)i, - kflag ? kvm_geterr(kvp->kd) : strerror(errno)); - if (debug) - warnx("lowpc 0x%lx, textsize 0x%lx", - (unsigned long)kvp->gpm.lowpc, kvp->gpm.textsize); - endfrom = kvp->gpm.fromssize / sizeof(*froms); - for (fromindex = 0; fromindex < endfrom; ++fromindex) { - if (froms[fromindex] == 0) - continue; - frompc = (u_long)kvp->gpm.lowpc + - (fromindex * kvp->gpm.hashfraction * sizeof(*froms)); - for (toindex = froms[fromindex]; toindex != 0; - toindex = tos[toindex].link) { - if (debug) - warnx("[mcleanup] frompc 0x%lx selfpc 0x%lx " - "count %ld", frompc, tos[toindex].selfpc, - tos[toindex].count); - rawarc.raw_frompc = frompc; - rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; - rawarc.raw_count = tos[toindex].count; - fwrite((char *)&rawarc, sizeof(rawarc), 1, fp); - } - } - fclose(fp); -} - -/* - * Get the profiling rate. - */ -int -getprofhz(kvp) - struct kvmvars *kvp; -{ - size_t size; - int mib[2], profrate; - struct clockinfo clockrate; - - if (kflag) { - profrate = 1; - if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate, - sizeof profrate) != sizeof profrate) - warnx("get clockrate: %s", kvm_geterr(kvp->kd)); - return (profrate); - } - mib[0] = CTL_KERN; - mib[1] = KERN_CLOCKRATE; - clockrate.profhz = 1; - size = sizeof clockrate; - if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0) - warn("get clockrate: %s", strerror(errno)); - return (clockrate.profhz); -} - -/* - * Reset the kernel profiling date structures. - */ -void -reset(kvp) - struct kvmvars *kvp; -{ - char *zbuf; - u_long biggest; - int mib[3]; - - setprof(kvp, GMON_PROF_OFF); - - biggest = kvp->gpm.kcountsize; - if (kvp->gpm.fromssize > biggest) - biggest = kvp->gpm.fromssize; - if (kvp->gpm.tossize > biggest) - biggest = kvp->gpm.tossize; - if ((zbuf = (char *)malloc(biggest)) == NULL) - errx(12, "cannot allocate zbuf space"); - bzero(zbuf, biggest); - if (kflag) { - if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf, - kvp->gpm.kcountsize) != kvp->gpm.kcountsize) - errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd)); - if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf, - kvp->gpm.fromssize) != kvp->gpm.fromssize) - errx(14, "froms zero: %s", kvm_geterr(kvp->kd)); - if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf, - kvp->gpm.tossize) != kvp->gpm.tossize) - errx(15, "tos zero: %s", kvm_geterr(kvp->kd)); - return; - } - (void)seteuid(0); - mib[0] = CTL_KERN; - mib[1] = KERN_PROF; - mib[2] = GPROF_COUNT; - if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) - errx(13, "tickbuf zero: %s", strerror(errno)); - mib[2] = GPROF_FROMS; - if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) - errx(14, "froms zero: %s", strerror(errno)); - mib[2] = GPROF_TOS; - if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) - errx(15, "tos zero: %s", strerror(errno)); - (void)seteuid(getuid()); - free(zbuf); -} diff --git a/kmodload.tproj/Makefile b/kmodload.tproj/Makefile deleted file mode 100644 index 947e08a..0000000 --- a/kmodload.tproj/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# -# Generated by the Apple Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = kmodload - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Tool - -HFILES = kld_patch.h vers_rsrc.h c++rem3.h - -CFILES = c++rem3.c kld_patch.c kmodload.c vers_rsrc.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodload.8\ - kmodsyms.8 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = tool.make -NEXTSTEP_INSTALLDIR = /sbin -WINDOWS_INSTALLDIR = /Library/Executables -PDO_UNIX_INSTALLDIR = /bin -LIBS = -lkld -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/kmodload.tproj/c++rem3.c b/kmodload.tproj/c++rem3.c deleted file mode 100644 index dfea388..0000000 --- a/kmodload.tproj/c++rem3.c +++ /dev/null @@ -1,2209 +0,0 @@ -// 45678901234567890123456789012345678901234567890123456789012345678901234567890 -/* - -Rules specification by -Stan Shebs of Apple Computer, Inc 2002 - -Parse and remangle implemented by -Godfrey van der Linden of Apple Computer, Inc 2002 - -Rules for demangling IOKit symbols - -In Darwin versions 1.0 through at least 5.2, IOKit is compiled using -GCC version 2. GCC 2's C++ symbol mangling algorithm ultimately -derives from the basic scheme described in the Annotated C++ Reference -Manual (ARM), section 7.2.1c, with a number of changes, mostly due to -the expansion of the language since the ARM was published in 1990. - -This description is not complete. It omits RTTI, thunks, and -templates, since they are not allowed in IOKit. The description also -mentions mangled name constructs that are not disallowed in IOKit, but -that as of Jan 2002, did actually appear in any symbol in the base -system. - -A mangled name basically consists of a function name followed -by two underscores, optionally followed by a signature computed -from the function's argument types. (Note that in Darwin, the -compiler adds an additional underscore to all C and C++ symbols. -The description assumes this has been removed.) - - ::= - | - - ::= [ ] - - ::= [ "_GLOBAL_" [ID] "__" ] "__" [ ] - - ::= * - | NULL - -Questions for Stan (@@@Stan@@@) -1> A valid implies a null function name. -2> I wonder if an is mutually exclusive with a perhaps something like :- - ::= [ "_GLOBAL_" ("I"|"D") "__" ] (( "__") | ) -3> Do constructors turn up as an opinfo or a NULL function name? - -The optional "_GLOBAL_"("I"|"D")"__" sequence indicates global constructors -and destructors, but in practice these do not appear with the mach-o Apple 2.95 - -A Null indicates a constructor or an operator. - -Since may include trailing underscores, the demangler -should scan forward until a non-underscore is seen, and then take the -last two as the separator between name and signature. - - may also include any number of leading underscores, so -the demangler needs to add those to and look for the -"__" following the name. - - ::= ("_._"|"_$_" ) ; destructor - | "__vt_" ; virtual table - | "_" ("."|"$") ; Variable - - ::= - | "Q" - | "K" ; ignored and illegal - - ::= - - ::= * - - ::= "type" - | "__op" - | "__" - | "a" - - ::= "aa" # && - | "aad" # &= - | "ad" # & - | "adv" # /= - | "aer" # ^= - | "als" # <<= - | "amd" # %= - | "ami" # -= - | "aml" # *= - | "aor" # |= - | "apl" # += - | "ars" # >>= - | "as" # = - | "cl" # () - | "cm" # , - | "cn" # ?: - | "co" # ~ - | "dl" # delete - | "dv" # / - | "eq" # == - | "er" # ^ - | "ge" # >= - | "gt" # > - | "le" # <= - | "ls" # << - | "lt" # < - | "md" # % - | "mi" # - - | "ml" # * - | "mm" # -- - | "mn" # ? - | "ne" # != - | "nt" # ! - | "nw" # new - | "oo" # || - | "or" # | - | "pl" # + - | "pp" # ++ - | "rf" # -> - | "rm" # ->* - | "rs" # >> - | "sz" # sizeof - | "vc" # [] - | "vd" # delete[] - | "vn" # new[] - -Questions for Stan (@@@Stan@@@) -1> What the hell is The "type" & "__op" stuff? - -IOKit has so far only been observed to use operations new ("nw") and -delete ("dl"). - -The signature is a concatenated list of elements, which are usually -argument types, but may include other sorts of things. - - ::= * - - ::= - | "S" - | "F" [ "_" ] - -Questions for Stan (@@@Stan@@@) -1> I think the 'B' phrase should probably read '| "B" '? -2> Ambiguous productions for signature - OSObject::func(struct timeval fred) => _func__8OSObject7timeval - signature could be parsed as - or - I believe the second one must be the valid production. - - ::= * - - :: - - ::= * - -The is the number of characters in . - -Argument types are a concatenated sequence of types. - - ::= # Empty - | + - ::= [ "n" ] - | "N" - | "T" - -The "N" repeats and "T" references to already-seen typescan only -appear if -fno-squangle (no squashed mangling), and in practice aren't -seen in IOKit symbols. - - ::= | * "_" - -Return types are just like any other sort of type. - - ::= - -Types consist of a variable number of declarators in front of a basic -type. - - ::= * - - ::= "P" ; pointer - | "p" ; pointer (but never occurs?) - | "R" ; reference (&) - | "A" ; array - | "T" - | "O" - | - -The "A" production can produce an ambigous output if it is followed by a counted class name or structure name. - -The "T" reference to a type does not appear in IOKit symbols, nor do -the "M" and "O" declarators. - - ::= ; function - | ; method - | * - - ::= "F" "_" - - ::= "M" - -A qualified name consists of a count of types, followed by all the -types concatenated together. For instance, Namespace::Class is -Q29Namespace5Class. For more than 9 types (which has not yet occurred -in IOKit), the multi-digit count is surrounded by underscores. - -Questions for Stan (@@@Stan@@@) -1> Can the types in a qualified name really be generic types or can the set be restricted to just counted class names? - - ::= | "_" * "_" - -Fundamental types are single letters representing standard built-in -types, optionally preceded by type qualifiers for properties like -signedness and constness. For instance, CUi is a const unsigned int. - - ::= "S" ; signed (chars only) - | "U" ; unsigned (any integral type) - | "J" ; __complex - | - - ::= - | "b" ; bool - | "c" ; char - | "d" ; double - | "f" ; float - | "i" ; int - | "l" ; long - | "r" ; long double - | "s" ; short - | "v" ; void - | "w" ; wchar_t - | "x" ; long long - | "G" ; ????? - | "e" ; ellipsis - -"G" does not appear in IOKit symbols in this context. - - ::= "C" ; const - | "V" ; volatile - | "u" ; restrict (C99) - | "G" ; struct/union/enum unused by gcc3 - -The restrict qualifier has not appeared in IOKit symbols. - -*/ -#if KERNEL - -#include -#include - -#include - -#include - -#include - -enum { false = 0, true = 1 }; - -#else /* !KERNEL */ - -#include - -#include -#include -#include - -#include - -#endif /* KERNEL */ - -#include "c++rem3.h" - -#define STRLEN(s) (sizeof(s)-1) -#define APPENDSTR(c, str) do { appendNStr(c, str, STRLEN(str)); } while (0) - -#define MAX_COMPOUND_TYPES 128 -#define MAX_ENTRIES 256 -#define MAX_SDICT_ENTRIES 256 -#define MAX_BDICT_ENTRIES 64 -#define MAX_RETURN_BUFFER 256 - -// Can't be bigger that 16 entries -typedef enum NameTypes { - kNTUndefined, kNTClass, kNTFunction, kNTFuncEnd, - kNTMethod, kNTBuiltIn, kNTDeclarator, kNTArray, - kNTKName, kNTSubstitute, kNTSubQualClass -} NameTypes; - -typedef struct TypeData { - short fStartEntry, fNumEntries; -} TypeData; - -typedef struct BaseTypeData { - const char *fFundTypeID; // May contain the type itself for kNTBuiltIt - unsigned int fLen:16; - unsigned int fType:4; // Must fit a NameType - unsigned int fVolatile:1; - unsigned int fConst:1; - unsigned int fSigned:1; - unsigned int fUnsigned:1; - unsigned int fPseudo:1; - unsigned int fQualified:1; -} BaseTypeData; - -typedef struct CheckPoint { - const char *fInChar; - unsigned char fNumI, fNumO, fNumT, fNumB, fNumS; -} CheckPoint; - -typedef struct ParseContext { - CheckPoint fP; - BaseTypeData fInEntries[MAX_ENTRIES]; // Input parsed elements - BaseTypeData fOutEntries[MAX_ENTRIES]; // Output parsed elements - TypeData fTypeList[MAX_COMPOUND_TYPES]; // Table of types - TypeData fSubDict[MAX_SDICT_ENTRIES]; - TypeData fBDict[MAX_BDICT_ENTRIES]; // B dictionary types - BaseTypeData *fCurBaseP; - const char *fInStr; - char *fOutStrEnd; - char *fOutChar; - int fInSize; - Rem3Return fRetCode; -} ParseContext; - -// -// The only forward declaration necessary -// -static Boolean parse_type(ParseContext *c); - -// Helper functions for walking through the string -static __inline__ char getNext(ParseContext *c) -{ - return *c->fP.fInChar++; -} - -static __inline__ CheckPoint *checkPoint(ParseContext *c) -{ - return &c->fP; -} - -static __inline__ void resetTo(ParseContext *c, CheckPoint *chk) -{ - c->fP = *chk; -} - -static __inline__ const char *inCharFromCheck(ParseContext *c, CheckPoint *chk) -{ - return chk->fInChar; -} - -static __inline__ void advance(ParseContext *c, int len) -{ - c->fP.fInChar += len; -} - -static __inline__ Boolean retard(ParseContext *c, int len) -{ - const char *cp = c->fP.fInChar - len; - if (cp < c->fInStr) - return false; - - c->fP.fInChar = cp; - return true; -} - -static __inline__ char peekAt(ParseContext *c, int index) -{ - return c->fP.fInChar[index]; -} - -static __inline__ char peekNext(ParseContext *c) -{ - return peekAt(c, 0); -} - -static __inline__ Boolean atEnd(ParseContext *c) -{ - return '\0' == peekNext(c); -} - -static __inline__ Boolean hasRemain(ParseContext *c, int len) -{ - return (c->fP.fInChar - c->fInStr + len <= c->fInSize); -} - -// -// Routines for allocating entries in the various -// -static __inline__ BaseTypeData *newIn(ParseContext *c) -{ - BaseTypeData *iP; - - if (c->fP.fNumI < MAX_ENTRIES) { - iP = &c->fInEntries[c->fP.fNumI++]; - bzero(iP, sizeof(*iP)); - c->fCurBaseP = iP; - return iP; - } - else { - c->fRetCode = kR3InternalNotRemangled; - return NULL; - } -} - -static __inline__ BaseTypeData *newOut(ParseContext *c) -{ - BaseTypeData *oP; - - if (c->fP.fNumO < MAX_ENTRIES) { - oP = &c->fOutEntries[c->fP.fNumO++]; - return oP; - } - else { - c->fRetCode = kR3InternalNotRemangled; - return NULL; - } -} - -static __inline__ TypeData * -newSub(ParseContext *c, int start, int num) -{ - TypeData *sP; - - if (c->fP.fNumS < MAX_SDICT_ENTRIES) { - sP = &c->fSubDict[c->fP.fNumS++]; - sP->fStartEntry = start; - sP->fNumEntries = num; - return sP; - } - else { - c->fRetCode = kR3InternalNotRemangled; - return NULL; - } -} - -static __inline__ TypeData * -newBDict(ParseContext *c, int start, int num) -{ - TypeData *bP; - - if (c->fP.fNumB < MAX_BDICT_ENTRIES) { - bP = &c->fBDict[c->fP.fNumB++]; - bP->fStartEntry = start; - bP->fNumEntries = num; - return bP; - } - else { - c->fRetCode = kR3InternalNotRemangled; - return NULL; - } -} - -static __inline__ TypeData * -newType(ParseContext *c, int start) -{ - TypeData *tP; - - if (c->fP.fNumT < MAX_COMPOUND_TYPES) { - tP = &c->fTypeList[c->fP.fNumT++]; - tP->fStartEntry = start; - return tP; - } - else - return NULL; -} - -static __inline__ TypeData * -dupType(ParseContext *c, TypeData *iTP, int offset) -{ - TypeData *tP = newType(c, iTP->fStartEntry + offset); - if (tP) - tP->fNumEntries = iTP->fNumEntries; - - return tP; -} - -// -// Identifier character recognition helpers, can be optimised -// -static __inline__ Boolean isValidFirstAlphabetic(char c) -{ - if ('a' <= c && c <= 'z') - return true; - else if ('A' <= c && c <= 'Z') - return true; - else - return false; -} - -static __inline__ Boolean isValidFirstChar(char c) -{ - if (isValidFirstAlphabetic(c)) - return true; - else if (c == '_') - return true; - else - return false; -} - -static __inline__ Boolean isValidChar(char c) -{ - if (isValidFirstChar(c)) - return true; - else if ('0' <= c && c <= '9') - return true; - else - return false; -} - -// -// Helper function for recognising characters and strings -// - -// Check the current input is the given character -static __inline__ Boolean isNext(ParseContext *c, char ch) -{ - if (peekNext(c) == ch) { - advance(c, 1); - return true; - } - else - return false; -} - -// Check the current input is ONE of the characters in str -static Boolean charNext(ParseContext *c, char *str) -{ - if (hasRemain(c, 1)) { - char ch = peekNext(c); - char next; - - while ( (next = *str++) ) - if (next == ch) { - advance(c, 1); - return true; - } - } - - return false; -} - -// Check the current input for 'str' -static Boolean strNext(ParseContext *c, const char *str) -{ - const char *cp = c->fP.fInChar; - - do { - if (!*str) { - c->fP.fInChar = (char *) cp; - return true; - } - else if (!*cp) - return false; - - } while (*cp++ == *str++); - - return false; -} - -// -// Qualifier re-encoding -// -static void -decodeQual(BaseTypeData *typeP, int *qualLenP, const char **qualP) -{ - const char *qual; - int qualLen; - - if (typeP->fConst && typeP->fVolatile) - { qual = "VK"; qualLen = 2; } - else if (typeP->fConst) - { qual = "K"; qualLen = 1; } - else if (typeP->fVolatile) - { qual = "V"; qualLen = 1; } - else - { qual = NULL; qualLen = 0; } - - *qualLenP = qualLen; - *qualP = qual; -} - - -// -// Output functions -// - -static void appendChar(ParseContext *c, char ch) -{ - char *outAddr = c->fOutChar++; - if (outAddr < c->fOutStrEnd) - *outAddr = ch; -} - -static void appendNStr(ParseContext *c, const char *str, int len) -{ - char *outAddr = c->fOutChar; - - c->fOutChar += len; - if (c->fOutChar < c->fOutStrEnd) - bcopy(str, outAddr, len); -} - -static __inline__ void appendStr(ParseContext *c, const char *str) -{ - appendNStr(c, str, strlen(str)); -} - -static void appendSub(ParseContext *c, int ls) -{ - appendChar(c, 'S'); - if (ls) { - if (--ls >= 36) { - int ms; - - ms = ls / 36; - appendChar(c, (ms < 10)? '0' + ms : 'A' + ms - 10); - ls -= (ms * 36); - } - appendChar(c, (ls < 10)? '0' + ls : 'A' + ls - 10); - } - appendChar(c, '_'); -} - -static Boolean compareTypes(ParseContext *c, int sub, int entry, int numEntries) -{ - TypeData *subP = &c->fSubDict[sub]; - BaseTypeData *bSP, *bIP; - int i; - - if (subP->fNumEntries != numEntries) - return false; - - bSP = &c->fInEntries[subP->fStartEntry]; - bIP = &c->fInEntries[entry]; - - for (i = 0; i < numEntries; i++, bSP++, bIP++) { - if (bSP->fType != bIP->fType) - return false; - - switch (bSP->fType) { - case kNTClass: - if (bSP->fLen != bIP->fLen) - return false; - else if (strncmp(bSP->fFundTypeID, bIP->fFundTypeID, bSP->fLen)) - return false; - break; - - case kNTArray: - case kNTBuiltIn: - case kNTDeclarator: - if (bSP->fFundTypeID != bIP->fFundTypeID) - return false; - break; - - case kNTMethod: - case kNTFunction: - case kNTUndefined: - case kNTKName: - break; // OK so far - - default: - return false; // Fatal errors - } - } - - return true; -} - -static int searchDict(ParseContext *c, int entry, int numE) -{ - int sub, numSubs = c->fP.fNumS; - - // don't try to substitute the last builtin - if (numE == 1 && kNTBuiltIn == c->fInEntries[entry].fType) - return -1; - - for (sub = 0; sub < numSubs; sub++) - if (compareTypes(c, sub, entry, numE)) - return sub; - - return -1; -} - -static int searchDictClass(ParseContext *c, const char *qname, int len) -{ - TypeData *subP; - int sub, numSubs = c->fP.fNumS; - - for (sub = 0, subP = c->fSubDict; sub < numSubs; sub++, subP++) { - BaseTypeData *iP = &c->fInEntries[subP->fStartEntry]; - - if (kNTClass != iP->fType || iP->fLen != len) - continue; - if (!strncmp(iP->fFundTypeID, qname, len)) - return sub; - } - - return -1; -} - -static Boolean -appendQualifiedClass(ParseContext *c, int entry) -{ - BaseTypeData *iP, *oP, *sP, *endSP; - const char *cp, *typeID; - int sub, subEntry, prefixLen; - int q_count; - - int decodeStart = c->fP.fNumI; - - // Scan through the incom - iP = &c->fInEntries[entry]; - endSP = &c->fInEntries[MAX_ENTRIES]; - sP = &c->fInEntries[decodeStart]; - - prefixLen = iP->fLen; - typeID = cp = iP->fFundTypeID; - for (q_count = 0; sP < endSP && (cp-typeID) < prefixLen; q_count++, sP++) { - int count; - - count = strtoul(cp, (char **) &cp, 10); - cp += count; - - sP->fType = kNTClass; - sP->fFundTypeID = typeID; - sP->fLen = cp - typeID; - } - if (sP >= endSP) - return false; - - // Search backwards until I find the first substitution - sub = -1; - for (subEntry = q_count, sP--; subEntry > 0; subEntry--, sP--) { - sub = searchDictClass(c, sP->fFundTypeID, sP->fLen); - if (-1 != sub) - break; - } - - // Now drop the symbol into the output buffer - oP = newOut(c); - if (!oP) - return false; - - if (sub < 0) - *oP = *iP; // No sub copy original - else { - // Substitution found - prefixLen = sP->fLen; // Length of substitution - - oP->fType = kNTSubstitute; // Assume complete substitution - oP->fLen = sub; - oP->fFundTypeID = 0; - - // We have a partial substitution so tag on the unmatched bit - if (prefixLen != iP->fLen) { - oP->fType = kNTSubQualClass; // Re-characterise as 2 part sub - - oP = newOut(c); - if (!oP) - return false; - - *oP = *iP; // Duplicate the original - oP->fType = kNTSubQualClass; - oP->fFundTypeID += prefixLen; // Skip leading substituted text - oP->fLen -= prefixLen; - } - } - - // Finally insert the qualified class names into the dictionary - for (subEntry++, sP++; subEntry < q_count; subEntry++, decodeStart++) { - c->fInEntries[decodeStart] = *sP++; - if (!newSub(c, decodeStart, 1)) - return false; - } - c->fP.fNumI = decodeStart; - - if (!newSub(c, entry, 1)) - return false; - - return true; -} - -static int -appendType(ParseContext *c, int type) -{ - BaseTypeData *iP, *oP; - TypeData *tP; - int i, sub; - int entry, numE, lastEntry; - Boolean found; - - if (type >= c->fP.fNumT) - return -1; - - tP = &c->fTypeList[type++]; - entry = tP->fStartEntry; - numE = tP->fNumEntries; - lastEntry = entry + numE; - iP = 0; - for (i = 0, found = false, sub = -1; i < numE; i++) { - iP = &c->fInEntries[entry + i]; - switch (iP->fType) { - - // Function & Builtin can't be compressed alone - case kNTFunction: - case kNTBuiltIn: - i++; // Copy the current entry - found = true; - break; - - case kNTClass: - case kNTMethod: - sub = searchDict(c, entry + i, numE - i); - if (sub < 0 && !iP->fQualified) - i++; - found = true; - break; - - case kNTDeclarator: - case kNTArray: - sub = searchDict(c, entry + i, numE - i); - found = (sub >= 0); - break; - - // Internal error's should never occur - case kNTKName: - case kNTSubstitute: - case kNTSubQualClass: - case kNTUndefined: - default: - return -1; - } - if (found) - break; - } - - if (!found) - return -1; // Internal error: no terminal symbol? - - // Copy the already input buffer to the output - oP = &c->fOutEntries[c->fP.fNumO]; - if (i) { - if (c->fP.fNumO + i >= MAX_ENTRIES) - return -1; - - bcopy(&c->fInEntries[entry], oP, i * sizeof(*oP)); - c->fP.fNumO += i; - oP += i; - } - - if (sub >= 0) { - // We found a substitution - oP->fType = kNTSubstitute; - oP->fLen = sub; - c->fP.fNumO++; // Increment output for the substitution - - // Walk over types that have been substituted - while (type < c->fP.fNumT - && c->fTypeList[type].fStartEntry < lastEntry) - type++; - } - else switch (iP->fType) - { - case kNTMethod: - type = appendType(c, type); // Class Name - if (type < 0) - return type; - type = appendType(c, type); // Pointer to function - if (type < 0) - return type; - break; - - case kNTFunction: - type = appendType(c, type); // Return type - if (type < 0) - return type; - - // process the argument list - do { - tP = &c->fTypeList[type]; - if (tP->fStartEntry < lastEntry) { - type = appendType(c, type); - if (type < 0) - return type; - } - else - break; - } while (type < c->fP.fNumT); - oP = newOut(c); - if (!oP) - return -1; - oP->fType = kNTFuncEnd; - break; - - case kNTBuiltIn: - i--; // Do not store the buildit in the dictionary - break; - - case kNTClass: // Nothing more to do - if (!iP->fQualified) - break; - else if (appendQualifiedClass(c, entry + i)) - break; - else - return -1; - } - - // No further substititions to be had update the dictionary - for (i += entry; --i >= entry; ) { - if (!newSub(c, i, lastEntry - i)) - return -1; - } - - return type; -} - -static Boolean appendArgumentList(ParseContext *c) -{ - int i, num; - - c->fRetCode = kR3InternalNotRemangled; - // Setup the output entry array - num = c->fP.fNumT; - for (i = 0; i < num; ) { - i = appendType(c, i); - if (i < 0) - return false; - } - - // First pass output uncompressed types - for (i = 0, num = c->fP.fNumO; i < num; i++) { - BaseTypeData *bP; - - bP = &c->fOutEntries[i]; - - if (bP->fPseudo) - continue; // Pseudo entry do not output; - - switch (bP->fType) { - - case kNTSubstitute: appendSub(c, bP->fLen); break; - - case kNTSubQualClass: - appendChar(c, 'N'); - appendSub(c, bP->fLen); - i++; bP = &c->fOutEntries[i]; - appendNStr(c, bP->fFundTypeID, bP->fLen); - appendChar(c, 'E'); - break; - - case kNTClass: - if (bP->fQualified) { - appendChar(c, 'N'); - appendNStr(c, bP->fFundTypeID, bP->fLen); - appendChar(c, 'E'); - } - else - appendNStr(c, bP->fFundTypeID, bP->fLen); - break; - - case kNTArray: { - char numbuf[16]; // Bigger than MAX_LONG + 3 - int len; - len = snprintf(numbuf, sizeof(numbuf), - "A%lu_", (unsigned long) bP->fFundTypeID); - appendNStr(c, numbuf, len); - break; - } - - case kNTBuiltIn: - case kNTDeclarator: appendChar(c, (int) bP->fFundTypeID); break; - case kNTMethod: appendChar(c, 'M'); break; - case kNTFunction: appendChar(c, 'F'); break; - case kNTFuncEnd: appendChar(c, 'E'); break; - - case kNTUndefined: - case kNTKName: - default: - return false; // Fatal errors - } - } - - // Successful remangle - c->fRetCode = kR3Remangled; - return true; -} - -// -// Parse routines -// - -// ::= * -static Boolean parse_count(ParseContext *c, int *countP) -{ - int count = 0; - char ch; - - ch = peekNext(c); - if (ch < '1' || ch > '9') - return false; - - count = strtol(c->fP.fInChar, (char **) &c->fP.fInChar, 10); - if (countP) - *countP = count; - - return true; -} - - -// "n" can cause the following type to be ambiguous as -// n23_Pc... can be -// "n" ... -// | "n" '_' ... -// However as the class '_Pc' is probably going to be unlikely a quick -// check to see if the next field is a valid type would probably clear -// up the abiguity for the majority of cases. -// -// ::= | * "_" -static Boolean parse_index(ParseContext *c, int *indexP) -{ - CheckPoint chk = *checkPoint(c); - char ch0, ch1; - int index; - - ch0 = peekAt(c, 0); - ch1 = peekAt(c, 1); - - if ( !('0' <= ch0 && ch0 <= '9') ) - goto abandonParse; - if ('0' <= ch1 && ch1 <= '9') { - if (!parse_count(c, &index)) - goto abandonParse; - if (isNext(c, '_')) { - // @@@ gvdl: Ambiguity check one day - if (indexP) - *indexP = index; - return true; - } - else - resetTo(c, &chk); // Must be the one digit case - } - - // One digit case - advance(c, 1); - index = ch0 - '0'; - - if (indexP) - *indexP = index; - return true; - -abandonParse: - return false; -} - - -// ::= "C" ; const -// | "V" ; volatile -// | "u" ; restrict (C99) unsupported -// | "G" ; struct/union/enum ; unused in gcc3 -static Boolean parse_qualifiers(ParseContext *c) -{ - BaseTypeData *bP = c->fCurBaseP; - - for (;;) { - if (isNext(c, 'C')) - bP->fConst = true; // "C" ; const - else if (isNext(c, 'V')) - bP->fVolatile = true; // "V" ; volatile - else if (isNext(c, 'u')) - return false; // "u" ; restrict (C99) - else if (isNext(c, 'G')) - continue; // "G" ; struct/union/enum ; unused - else - break; - } - - return true; -} - -// Assumes we have an open fInEntry in fCurBaseP -static Boolean duplicateEntries(ParseContext *c, int start, int numE) -{ - BaseTypeData *bIP = &c->fInEntries[start]; // First duplicate entry - BaseTypeData *bP = c->fCurBaseP; - int i; - - // Duplicating a method - if (kNTMethod == bIP->fType) { - bP--; // Strip leading 'P' declarator - c->fP.fNumI--; - } - - numE--; - - // do we have room available for duplication - if (c->fP.fNumI + numE >= MAX_ENTRIES) - return false; - - // Copy the parse entries over - bcopy(bIP, bP, (numE + 1) * sizeof(*bP)); - - // Now we have to duplicate the types for the new entry - for (i = 0; i < c->fP.fNumT; i++) { - TypeData *tP = &c->fTypeList[i]; - if (tP->fStartEntry < start) - continue; - else if (tP->fStartEntry <= start + numE) - dupType(c, tP, bP - bIP); - else - break; - } - - c->fP.fNumI += numE; - bP += numE; - c->fCurBaseP = bP; - - return true; -} - -// Must have a valid c->fCurBaseP pointer on entry -// ::= ; plain class name -// | "Q" ; qualified name -// | "B" ; compressed name -// | "K" ; ignored and illegal -// ::= + -// ::= | "_" * "_" -// ::= -// ::= * -static Boolean -parse_class_name(ParseContext *c) -{ - BaseTypeData *bP = c->fCurBaseP; - const char *typeId = c->fP.fInChar; - char ch; - int count; - - if (parse_count(c, &count)) { - - // ::= - if (!hasRemain(c, count)) - goto abandonParse; - - bP->fType = kNTClass; - advance(c, count); - - bP->fFundTypeID = typeId; - bP->fLen = c->fP.fInChar - typeId; - } - else { - switch (peekNext(c)) { - - case 'Q': { - int i, q_count; - - advance(c, 1); - - // | "Q" ; qualified name - // ::= + - // ::= | "_" * "_" - if ('_' == (ch = getNext(c))) { - advance(c, 1); - if (!parse_count(c, &q_count) || !isNext(c, '_')) - goto abandonParse; - } - else if ('1' <= ch && ch <= '9') - q_count = ch - '0'; - - if (!q_count) - goto abandonParse; - - typeId = c->fP.fInChar; - bP->fType = kNTClass; - bP->fQualified = true; - i = 0; - for (i = 0; i < q_count; i++) { - if (parse_count(c, &count)) - advance(c, count); - else - goto abandonParse; - } - bP->fLen = c->fP.fInChar - typeId; - bP->fFundTypeID = typeId; - break; - } - - case 'B': - // | "B" - advance(c, 1); - - if (!parse_index(c, &count) || count >= c->fP.fNumB) - goto abandonParse; - - if (!duplicateEntries(c, c->fBDict[count].fStartEntry, - c->fBDict[count].fNumEntries)) - goto abandonParse; - return true; - - case 'K': default: - goto abandonParse; - } - } - - if (newBDict(c, bP - c->fInEntries, 1)) - return true; - -abandonParse: - return false; -} - -// ::= -// | "b" ; bool -// | "c" ; char -// | "d" ; double -// | "e" ; ellipsis -// | "f" ; float -// | "i" ; int -// | "l" ; long -// | "r" ; long double -// | "s" ; short -// | "v" ; void -// | "w" ; wchar_t -// | "x" ; long long -// | "G" ; ??? -static Boolean parse_fund_type_id(ParseContext *c) -{ - BaseTypeData *bP = c->fCurBaseP; - - if (!parse_class_name(c)) { - // Use the TypeID pointer as a 4 character buffer - char ch = peekNext(c); - - if (bP->fSigned && 'c' != ch) - goto abandonParse; // illegal only chars can be signed - - switch (ch) { - - case 'b': case 'd': case 'f': case 'v': case 'w': // No map types - break; - - case 'c': // character - if (bP->fSigned) ch = 'a'; - else if (bP->fUnsigned) ch = 'h'; - break; - case 'e': // ellipsis - ch = 'z'; - break; - case 'i': // int - if (bP->fUnsigned) ch = 'j'; - break; - case 'l': // long - if (bP->fUnsigned) ch = 'm'; - break; - case 'r': // long double - ch = 'e'; - break; - case 's': // short - if (bP->fUnsigned) ch = 't'; - break; - case 'x': // long long - if (bP->fUnsigned) ch = 'y'; - break; - - case 'G': // Don't understand "G" - default: - goto abandonParse; - } - - advance(c, 1); // Consume the input character - bP->fFundTypeID = (void *) (int) ch; - bP->fLen = 0; - bP->fType = kNTBuiltIn; - } - - return true; - -abandonParse: - return false; -} - -// ::= [ "n" ] -// | "N" ; Not implemented -// | "T" ; Not implemented -static Boolean parse_arg_type(ParseContext *c) -{ - // Don't bother to check point as parse_argument_types does it for us - - TypeData *typeP; - int repeat = 0; - - typeP = &c->fTypeList[c->fP.fNumT]; // Cache type for later repeat - if (!parse_type(c)) - return false; - - // Now check for a repeat count on this type - if (isNext(c, 'n')) { - if (!parse_index(c, &repeat)) - return false; - - do { - c->fCurBaseP = newIn(c); // Duplicate requires a fresh type - if (!c->fCurBaseP) - return false; - if (!duplicateEntries(c, typeP->fStartEntry, typeP->fNumEntries)) - return false; - } while (--repeat); - } - - return true; -} - -// ::= # Empty -// | + -static Boolean parse_argument_types(ParseContext *c) -{ - if (atEnd(c)) - return true; - - if (!parse_arg_type(c)) - goto abandonParse; - - while (!atEnd(c) && parse_arg_type(c)) - ; - - return true; - - // Not a counted class name so reset to checkPoint -abandonParse: - return false; -} - -// leaf function so the copy aside buffer isn't on the primary -// recursion stack. -static Boolean -rotateFunction(ParseContext *c, int argStart, int retStart) -{ - char returnTypeBuffer[MAX_RETURN_BUFFER]; - int numArg, numRet; - int lenArg, lenRet; - char *sArgP, *sRetP; - int i; - - TypeData *argTP = &c->fTypeList[argStart]; - TypeData *retTP = &c->fTypeList[retStart]; - - // Rotate around the entries first - numArg = retTP->fStartEntry - argTP->fStartEntry; - numRet = retTP->fNumEntries; - lenArg = numArg * sizeof(BaseTypeData); - lenRet = numRet * sizeof(BaseTypeData); - - // Copy the return type into a buffer - if (lenRet > sizeof(returnTypeBuffer)) - return false; - - sArgP = (char *) (&c->fInEntries[argTP->fStartEntry]); - sRetP = (char *) (&c->fInEntries[retTP->fStartEntry]); - - bcopy(sRetP, returnTypeBuffer, lenRet); - bcopy(sArgP, sArgP + lenRet, lenArg); - bcopy(returnTypeBuffer, sArgP, lenRet); - - // Retarget the argument and return types for the new entry positions - lenArg = numArg; - lenRet = numRet; - numArg = retStart - argStart; - numRet = c->fP.fNumT - retStart; - for (i = 0; i < numArg; i++) - c->fTypeList[argStart+i].fStartEntry += lenRet; - for (i = 0; i < numRet; i++) - c->fTypeList[retStart+i].fStartEntry -= lenArg; - - // Rotate the BDictionary - for (i = 0; i < c->fP.fNumB; i++) { - TypeData *bDP = &c->fBDict[i]; - int start = bDP->fStartEntry; - - if (start >= argTP->fStartEntry) - bDP->fStartEntry = start + lenRet; - else if (start >= retTP->fStartEntry) - bDP->fStartEntry = start - lenArg; - } - - // Finally rotate the retargeted type structures. - lenArg = numArg * sizeof(TypeData); - lenRet = numRet * sizeof(TypeData); - - sArgP = (char *) (&c->fTypeList[argStart]); - sRetP = (char *) (&c->fTypeList[retStart]); - - bcopy(sRetP, returnTypeBuffer, lenRet); - bcopy(sArgP, sArgP + lenRet, lenArg); - bcopy(returnTypeBuffer, sArgP, lenRet); - - return true; -} - -// ::= "F" "_" -static Boolean parse_function_type(ParseContext *c, Boolean forMethod) -{ - TypeData *bDictP = 0; - BaseTypeData *bP = c->fCurBaseP; - - int argTypeStart, retTypeStart; - - if (!forMethod) { - bDictP = newBDict(c, c->fP.fNumI-1, 0); - if (!bDictP) - goto abandonParse; - } - - if (!isNext(c, 'F')) - goto abandonParse; - - bP->fType = kNTFunction; - - // Note that the argument types will advance the Entry list - argTypeStart = c->fP.fNumT; - if (!parse_argument_types(c)) - goto abandonParse; - - if (!isNext(c, '_')) - goto abandonParse; - - // Parse the return type - retTypeStart = c->fP.fNumT; - if (!parse_type(c)) - goto abandonParse; - - // gcc3 puts the return code just after the 'F' declaration - // as this impacts the order of the compression I need to rotate - // the return type and the argument types. - if (!rotateFunction(c, argTypeStart, retTypeStart)) - goto abandonParse; - - if (!forMethod) - bDictP->fNumEntries = c->fP.fNumI - bDictP->fStartEntry; - - return true; - -abandonParse: - return false; -} - -// To convert 2.95 method to a 3.0 method I need to prune the -// first argument of the function type out of the parse tree. -static Boolean cleanMethodFunction(ParseContext *c, int type) -{ - TypeData *typeP, *startTP, *endTP; - BaseTypeData *bP; - int i, thisStart, thisEnd, thisLen, funcRemain; - - // Get pointer for the return value's type. - startTP = &c->fTypeList[type+1]; - endTP = &c->fTypeList[c->fP.fNumT]; - - // Now look for the first type that starts after the return type - thisEnd = startTP->fStartEntry + startTP->fNumEntries; - for (startTP++; startTP < endTP; startTP++) - if (startTP->fStartEntry >= thisEnd) - break; - - if (startTP >= endTP) { - c->fRetCode = kR3InternalNotRemangled; - return false; // Internal error: should never happen - } - - // We now have a pointer to the 1st argument in the input list - // we will need to excise the entries from the input list and don't forget - // to remove the associated types from the type list. - - thisLen = startTP->fNumEntries; - thisStart = startTP->fStartEntry; - thisEnd = thisStart + thisLen; - funcRemain = c->fP.fNumI - thisEnd; - bP = &c->fInEntries[thisStart]; - - // If we have no arguments then replace the pointer with a void - if (!funcRemain) { - c->fP.fNumI -= (thisLen - 1); - - bP->fFundTypeID = (void *) (int) 'v'; // Void arg list - bP->fLen = 0; - bP->fType = kNTBuiltIn; - - // Update the type entry for the void argument list - startTP->fNumEntries = 1; - return true; - } - - // Move the argument list down to replace the 'this' pointer - bcopy(bP + thisLen, bP, funcRemain * sizeof(*bP)); - c->fP.fNumI -= thisLen; - - // And remove the 'this' pointers type - - // First walk over all of the types that have to be removed - for (typeP = startTP + 1; typeP < endTP; typeP++) - if (typeP->fStartEntry >= thisEnd) - break; - - if (typeP >= endTP) { - c->fRetCode = kR3InternalNotRemangled; - return false; // Internal error Can't be a void argument list. - } - - bcopy(typeP, startTP, (char *) endTP - (char *) typeP); - - c->fP.fNumT -= typeP - startTP; - endTP = &c->fTypeList[c->fP.fNumT]; - for (typeP = startTP ; typeP < endTP; typeP++) - typeP->fStartEntry -= thisLen; - - // Finally we can retarget the BDictionary lists - for (i = 0; i < c->fP.fNumB; i++) { - TypeData *bDP = &c->fBDict[i]; - int start = bDP->fStartEntry; - - if (start < thisStart) - continue; - if (start >= thisEnd) - break; - - bDP->fStartEntry = start - thisLen; - } - - return true; -} - -// ::= "M" -// -// Note this is a very bad function. Gcc3 doesn't doesn't use pointer that -// is immediately before this entry. We will have to delete the 'P' declarator -// that is before the method declaration. -// We will also have to prune the first type in the argument list as Gcc3 -// doesn't register the 'this' pointer within the function list. -static Boolean parse_method_type(ParseContext *c) -{ - TypeData *bDictP; - TypeData *typeP; - BaseTypeData *bP; - - bDictP = newBDict(c, c->fP.fNumI-2, 0); - if (!bDictP) - goto abandonParse; - - // Replace 'P' declarator - c->fP.fNumI--; - bP = c->fCurBaseP - 1; - - if (!isNext(c, 'M')) - goto abandonParse; - - if (bP->fFundTypeID != (void *) (int) 'P') - goto abandonParse; - - // Replace the previous 'Pointer' declarator - bP->fType = kNTMethod; - bP->fFundTypeID = NULL; - bP->fLen = 0; - - // Grab the method's 'this' type specification - typeP = newType(c, c->fP.fNumI); - if (!newIn(c) || !typeP) - goto abandonParse; - - if (!parse_class_name(c)) - goto abandonParse; - typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry; - - // Grab the specifier - typeP = newType(c, c->fP.fNumI); - if (!newIn(c) || !typeP) - goto abandonParse; - - if (!parse_function_type(c, /* forMethod */ true)) - goto abandonParse; - - if (!cleanMethodFunction(c, typeP - c->fTypeList)) - goto abandonParse; - typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry; - - // Finally update the dictionary with the M & 'this' - bDictP->fNumEntries = c->fP.fNumI - bDictP->fStartEntry; - - return true; - -abandonParse: - return false; -} - -static Boolean emitQualifiers(ParseContext *c) -{ - BaseTypeData *bP = c->fCurBaseP; - - if (bP->fVolatile || bP->fConst) { - Boolean isConst, isVolatile, isSigned, isUnsigned; - - isVolatile = bP->fVolatile; - isConst = bP->fConst; - isSigned = bP->fSigned; - isUnsigned = bP->fUnsigned; - bP->fConst = bP->fVolatile = bP->fSigned = bP->fUnsigned = 0; - - if (isVolatile) { - bP->fType = kNTDeclarator; - bP->fFundTypeID = (void *) (int) 'V'; - bP->fLen = 0; - bP = newIn(c); - if (!bP) - return false; - } - if (isConst) { - bP->fType = kNTDeclarator; - bP->fFundTypeID = (void *) (int) 'K'; - bP->fLen = 0; - bP = newIn(c); - if (!bP) - return false; - } - bP->fSigned = isSigned; - bP->fUnsigned = isUnsigned; - } - - return true; -} - - -// ::= ; function -// | ; method -// | * -// ::= "S" ; signed (chars only) -// | "U" ; unsigned (any integral type) -// | "J" ; __complex -// | -static Boolean parse_base_type(ParseContext *c) -{ - if ('F' == peekNext(c)) { - if (!parse_function_type(c, /* forMethod */ false)) - goto abandonParse; - } - else if ('M' == peekNext(c)) { - if (!parse_method_type(c)) - goto abandonParse; - } - else { - // | * - BaseTypeData *bP = c->fCurBaseP; - for (;;) { - if (isNext(c, 'S')) - // ::= "S" ; signed (chars only) - { bP->fSigned = true; continue; } - else if (isNext(c, 'U')) - // | "U" ; unsigned (any integral type) - { bP->fUnsigned = true; continue; } - else if (isNext(c, 'C')) - // | - // ::= "C" ; const - { bP->fConst = true; continue; } - else if (isNext(c, 'V')) - // | "V" ; volatile - { bP->fVolatile = true; continue; } - else if (charNext(c, "Ju")) - goto abandonParse; // Don't support these qualifiers - // | "J" ; __complex - // | "u" ; restrict (C99) - else - break; - } - - if (!emitQualifiers(c)) - goto abandonParse; - - if (!parse_fund_type_id(c)) - goto abandonParse; - } - return true; - -abandonParse: - return false; -} - -// Use the top SDict as a stack of declarators. -// parses * -// ::= "P" ; pointer -// | "p" ; pointer (but never occurs?) -// | "R" ; reference (&) -// | "A" ; array -// | "T" -// | "O" -// | -// -// As a side-effect the fCurBaseP is setup with any qualifiers on exit -static Boolean parse_declarators(ParseContext *c) -{ - int count; - BaseTypeData *dP; - - // Note we MUST go through the for loop at least once - for (count = 0; ; count++) { - const char *curDecl; - char ch; - - if (!newIn(c)) - goto abandonParse; - - // ::= production - if (!parse_qualifiers(c) || !emitQualifiers(c)) - goto abandonParse; - - dP = c->fCurBaseP; // Find the current base type pointer - - curDecl = c->fP.fInChar; - - switch (peekNext(c)) { - - case 'P': case 'p': case 'R': - // ::= "P" ; pointer - // | "p" ; pointer (but never occurs?) - // | "R" ; reference (&) - - dP->fType = kNTDeclarator; - advance(c, 1); - - ch = *curDecl; - if ('p' == ch) ch = 'P'; - dP->fFundTypeID = (void *) (int) ch; - dP->fLen = 0; - continue; // Go around again - - case 'A': - // | "A" ; array - dP->fType = kNTArray; - - advance(c, 1); curDecl++; - curDecl = (void *) - strtoul(curDecl, (char **) &c->fP.fInChar, 10); - if (!curDecl) - goto abandonParse; - dP->fFundTypeID = curDecl; - dP->fLen = 0; - continue; // Go around again - - case 'T': case 'O': - // | "T" Unsupported - // | "O" Unsupported - goto abandonParse; - - default: - break; - } - - break; - } - - dP->fLen = 0; - return true; - -abandonParse: - return false; -} - -// ::= * -static Boolean parse_type(ParseContext *c) -{ - CheckPoint chk = *checkPoint(c); - TypeData *typeP = newType(c, c->fP.fNumI); - if (!typeP) - goto abandonParse; - - // As a side-effect the fCurBaseP is setup with any qualifiers on exit - if (!parse_declarators(c)) - goto abandonParse; - - // Merge the last qualifiers into the base type - if (!parse_base_type(c) || kNTUndefined == c->fCurBaseP->fType) - goto abandonParse; - - typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry; - return true; - -abandonParse: - resetTo(c, &chk); - return false; -} - -// ::= * -// No need to check point as an invalid function name is fatal -// Consumes trailing "__". -static Boolean -parse_function_name(ParseContext *c) -{ - char ch; - - while ( (ch = peekNext(c)) ) - { - advance(c, 1); - if ('_' == ch && '_' == peekNext(c)) { - do { - advance(c, 1); - } while ('_' == peekNext(c)); - return true; - } - } - - return false; -} - -// ::= "type" -// | "__op" -// | "__" ; Implies null function name -// | "a" -// ::= "aa" # && ==> "aa" -// | "aad" # &= ==> "aN" -// | "ad" # & ==> "ad" -// | "adv" # /= ==> "dV" -// | "aer" # ^= ==> "eO" -// | "als" # <<= ==> "lS" -// | "amd" # %= ==> "rM" -// | "ami" # -= ==> "mI" -// | "aml" # *= ==> "mL -// | "aor" # |= ==> "oR -// | "apl" # += ==> "pL -// | "ars" # >>= ==> "rS -// | "as" # = ==> "aS -// | "cl" # () ==> "cl -// | "cm" # , ==> "cm -// | "cn" # ?: ==> "qu -// | "co" # ~ ==> "co -// | "dl" # delete ==> "dl -// | "dv" # / ==> "dv -// | "eq" # == ==> "eq -// | "er" # ^ ==> "eo -// | "ge" # >= ==> "ge -// | "gt" # > ==> "gt -// | "le" # <= ==> "le -// | "ls" # << ==> "ls -// | "lt" # < ==> "lt -// | "md" # % ==> "rm -// | "mi" # - ==> "mi -// | "ml" # * ==> "ml -// | "mm" # -- ==> "mm -// | "mn" # "???????????????? -// | "mx" # >? ==> "???????????????? -// | "ne" # != ==> "ne -// | "nt" # ! ==> "nt -// | "nw" # new ==> "nw -// | "oo" # || ==> "oo" -// | "or" # | ==> "or -// | "pl" # + ==> "pl -// | "pp" # ++ ==> "pp -// | "rf" # -> ==> "pt -// | "rm" # ->* ==> "pm -// | "rs" # >> ==> "rs -// | "sz" # sizeof ==> "sz -// | "vc" # [] ==> "ix -// | "vd" # delete[] ==> "da -// | "vn" # new[] ==> "na -static struct opMap { - const char *op295, *op3; -} opMapTable[] = { - {"aad", "aN" }, {"adv", "dV" }, {"aer", "eO" }, {"als", "lS" }, - {"amd", "rM" }, {"ami", "mI" }, {"aml", "mL" }, {"aor", "oR" }, - {"apl", "pL" }, {"ars", "rS" }, {"aa", "aa" }, {"ad", "ad" }, - {"as", "aS" }, {"cl", "cl" }, {"cm", "cm" }, {"cn", "qu" }, - {"co", "co" }, {"dl", "dl" }, {"dv", "dv" }, {"eq", "eq" }, - {"er", "eo" }, {"ge", "ge" }, {"gt", "gt" }, {"le", "le" }, - {"ls", "ls" }, {"lt", "lt" }, {"md", "rm" }, {"mi", "mi" }, - {"ml", "ml" }, {"mm", "mm" }, {"mn", NULL }, {"mx", NULL }, - {"ne", "ne" }, {"nt", "nt" }, {"nw", "nw" }, {"oo", "oo" }, - {"or", "or" }, {"pl", "pl" }, {"pp", "pp" }, {"rf", "pt" }, - {"rm", "pm" }, {"rs", "rs" }, {"sz", "sz" }, {"vc", "ix" }, - {"vd", "da" }, {"vn", "na" }, -}; - -static Boolean parse_opinfo(ParseContext *c, const char **opInfoP) -{ - CheckPoint chk = *checkPoint(c); - const char *op; - char ch; - int i; - - if ('a' == (ch = peekNext(c))) { - goto abandonParse; - } - else if (strNext(c, "type")) { - goto abandonParse; - } - else if (retard(c, 4) && strNext(c, "____op")) { - // @@@ gvdl: check this out it may change - // ::= "__op" - goto abandonParse; - } - - // Failed till now so reset and see if we have an operator - resetTo(c, &chk); - - // quick check to see if we may have an operator - if (!strrchr("acdeglmnoprsv", peekNext(c))) - goto abandonParse; - - op = NULL; - for (i = 0; i < sizeof(opMapTable)/sizeof(opMapTable[0]); i++) { - if (strNext(c, opMapTable[i].op295)) { - op = opMapTable[i].op3; - break; - } - } - if (!op) - goto abandonParse; - - if (!strNext(c, "__")) // Trailing underbars - goto abandonParse; - - if (opInfoP) - *opInfoP = op; - return true; - -abandonParse: - return false; -} - -// ::= * -// ::= -// | "K" -// | "S" -// | "F" [ "_" ] -// ::= -// Treat the prefix's s_element as a full type -static Boolean -parse_signature(ParseContext *c, - const char *func, int funcLen, const char *op) -{ - BaseTypeData *bP; - TypeData *tP; - - Boolean isFunction = false; - - if (isNext(c, 'F')) { - // | "F" [ "_" ] - - char numbuf[16]; // Bigger than MAX_INT + 4 - int len; - isFunction = true; - if (!funcLen) - goto abandonParse; - - len = snprintf(numbuf, sizeof(numbuf), "__Z%d", funcLen); - - appendNStr(c, numbuf, len); - appendNStr(c, func, funcLen); - } - else if (isNext(c, 'S')) { - // | "S" ; Ignored - goto abandonParse; - } - else { - const char *qual; - int qualLen; - - // See if we can find a qualified class reference - tP = newType(c, c->fP.fNumI); - if (!tP) - goto abandonParse; - - bP = newIn(c); - if (!bP) - goto abandonParse; - - // Parse any qualifiers, store results in *fCurBaseP - bP->fPseudo = true; - if (!parse_qualifiers(c)) - goto abandonParse; - - if (!parse_class_name(c)) - goto abandonParse; - - bP = c->fCurBaseP; // class name may have redifined current - tP->fNumEntries = c->fP.fNumI - tP->fStartEntry; - - APPENDSTR(c, "__ZN"); - decodeQual(bP, &qualLen, &qual); - if (qualLen) - appendNStr(c, qual, qualLen); - appendNStr(c, bP->fFundTypeID, bP->fLen); - - if (funcLen) { - char numbuf[16]; // Bigger than MAX_INT + 1 - int len; - - len = snprintf(numbuf, sizeof(numbuf), "%d", funcLen); - appendNStr(c, numbuf, len); - appendNStr(c, func, funcLen); - } - else if (op) - appendStr(c, op); - else { - // No function & no op means constructor choose one of C1 & C2 - APPENDSTR(c, "C2"); - } - appendChar(c, 'E'); - } - - if (atEnd(c)) { - appendChar(c, 'v'); // void argument list - c->fRetCode = kR3Remangled; - return true; - } - - c->fCurBaseP = NULL; - if (!parse_argument_types(c)) - goto abandonParse; - - if (isFunction) { - if (isNext(c, '_')) { - // && !parse_type(c) @@@ gvdl: Unsupported return - c->fRetCode = kR3InternalNotRemangled; - goto abandonParse; - } - } - - if (!atEnd(c)) - goto abandonParse; - - // OK we have a complete and successful parse now output the - // argument list - return appendArgumentList(c); - -abandonParse: - return false; -} - -// ::= [ ] -// ::= [ "_GLOBAL_" [ID] "__" ] "__" [ ] -static Boolean parse_mangled_name(ParseContext *c) -{ - CheckPoint chk; - CheckPoint dubBarChk; - const char *func; - - // parse - if (strNext(c, "_GLOBAL_")) { // Is this GLOBAL static constructor? - // gvdl: can't deal with _GLOBAL_ - c->fRetCode = kR3InternalNotRemangled; - return false; // Can't deal with these - } - - func = c->fP.fInChar; - for (chk = *checkPoint(c); ; resetTo(c, &dubBarChk)) { - int funcLen; - const char *op = NULL; - - if (!parse_function_name(c)) - goto abandonParse; - dubBarChk = *checkPoint(c); - - // Note that the opInfo may be earlier than the curDoubleBar - // in which case the function name may need to be shrunk later on. - (void) parse_opinfo(c, &op); - - if (atEnd(c)) - goto abandonParse; // No Signature? - - funcLen = inCharFromCheck(c, &dubBarChk) - func - 2; - if (parse_signature(c, func, funcLen, op)) - return true; - - if (kR3NotRemangled != c->fRetCode) - goto abandonParse; - - // If no error then try again maybe another '__' exists - } - -abandonParse: - resetTo(c, &chk); - return false; -} - -// ::= ("_._" | "_$_" ) ; destructor -// | "__vt_" ; virtual table -// | "_" ("."|"$") -static Boolean parse_gnu_special(ParseContext *c) -{ - CheckPoint chk = *checkPoint(c); - BaseTypeData *bP = newIn(c); - - if (!bP) - return false; - - // What do the intel desctructors look like - if (strNext(c, "_._") || strNext(c, "_$_") ) // Is this a destructor - { - if (!parse_class_name(c) || !atEnd(c)) - goto abandonParse; - APPENDSTR(c, "__ZN"); - appendNStr(c, bP->fFundTypeID, bP->fLen); - APPENDSTR(c, "D2Ev"); - c->fRetCode = kR3Remangled; - return true; - } - else if (strNext(c, "__vt_")) // Is it's a vtable? - { - if (!parse_class_name(c) || !atEnd(c)) - goto abandonParse; - - APPENDSTR(c, "__ZTV"); - if (kNTClass != bP->fType) - goto abandonParse; - else if (bP->fQualified) { - appendChar(c, 'N'); - appendNStr(c, bP->fFundTypeID, bP->fLen); - appendChar(c, 'E'); - } - else - appendNStr(c, bP->fFundTypeID, bP->fLen); - - c->fRetCode = kR3Remangled; - return true; - } - else if (isNext(c, '_')) // Maybe it's a variable - { - const char *varname; - int varlen, len; - char numbuf[16]; // Bigger than MAX_INT + 1 - - if (!parse_class_name(c)) // Loads up the bP structure - goto abandonParse; - - if (!isNext(c, '.') && !isNext(c, '$')) - goto abandonParse; - - // Parse the variable name now. - varname = c->fP.fInChar; - if (atEnd(c) || !isValidFirstChar(getNext(c))) - goto abandonParse; - - while ( !atEnd(c) ) - if (!isValidChar(getNext(c))) - goto abandonParse; - - varlen = c->fP.fInChar - varname; - len = snprintf(numbuf, sizeof(numbuf), "%d", varlen); - - APPENDSTR(c, "__ZN"); - appendNStr(c, bP->fFundTypeID, bP->fLen); - - appendNStr(c, numbuf, len); - appendNStr(c, varname, varlen); - appendChar(c, 'E'); - - c->fRetCode = kR3Remangled; - return true; - } - - // Oh well it is none of those so give up but reset scan -abandonParse: - resetTo(c, &chk); - return false; -} - -// ::= -// | -static Boolean parse_special_or_name(ParseContext *c) -{ - Boolean res; - - - res = (parse_gnu_special(c) || parse_mangled_name(c)); - appendChar(c, '\0'); - - return res; -} - -Rem3Return rem3_remangle_name(char *gcc3, int *gcc3size, const char *gcc295) -{ - ParseContext *c; - Rem3Return result; - int size; - - if (!gcc295 || !gcc3 || !gcc3size) - return kR3BadArgument; - - size = strlen(gcc295); - if (size < 2) - return kR3NotRemangled; // Not a valid C++ symbol - else if (*gcc295 != '_') - return kR3NotRemangled; // no leading '_', not valid - - c = (ParseContext *) malloc(sizeof(*c)); - if (!c) - return kR3InternalNotRemangled; - bzero(c, sizeof(*c)); - - c->fInSize = size; - c->fInStr = gcc295 + 1; // Strip leading '_' - c->fP.fInChar = c->fInStr; - - c->fOutStrEnd = gcc3 + *gcc3size; - c->fOutChar = gcc3; - - c->fRetCode = kR3NotRemangled; - (void) parse_special_or_name(c); - - result = c->fRetCode; - if (kR3Remangled == result) { - if (c->fOutChar > c->fOutStrEnd) - result = kR3BufferTooSmallRemangled; - *gcc3size = c->fOutChar - gcc3 - 1; // Remove nul from len - } - - free(c); - - return result; -} diff --git a/kmodload.tproj/c++rem3.h b/kmodload.tproj/c++rem3.h deleted file mode 100644 index 9f37019..0000000 --- a/kmodload.tproj/c++rem3.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* - * History: - * 2002-02-26 gvdl Initial implementation of the gcc 2.95 -> gcc 3.x - * symbol remangler. - */ - -#include - -typedef enum Rem3Return { - kR3NotRemangled = 0, // Wasn't a 2.95 C++ symbol but otherwise OK - kR3Remangled, // Was sucessfully remangled from 2.95 -> 3.x - kR3InternalNotRemangled, // Symbol is too big to be parsed - kR3BufferTooSmallRemangled, // Is 2.95 symbol but insufficent output space - kR3BadArgument, // One of the pointers are NULL -} Rem3Return; - -__BEGIN_DECLS - -extern Rem3Return -rem3_remangle_name(char *gcc3, int *gcc3size, const char *gcc295); - -__END_DECLS diff --git a/kmodload.tproj/kld_patch.c b/kmodload.tproj/kld_patch.c deleted file mode 100644 index 3016199..0000000 --- a/kmodload.tproj/kld_patch.c +++ /dev/null @@ -1,2478 +0,0 @@ -/* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* - * History: - * 2001-05-30 gvdl Initial implementation of the vtable patcher. - */ -// 45678901234567890123456789012345678901234567890123456789012345678901234567890 - -#include -#include -#include -#include - -#if KERNEL - -#include -#include - -#include - -#include - -#include -#include - -#include "mach_loader.h" - -#include - -enum { false = 0, true = 1 }; - -#define vm_page_size page_size - -extern load_return_t fatfile_getarch( - void * vp, // normally a (struct vnode *) - vm_offset_t data_ptr, - struct fat_arch * archret); - -__private_extern__ char *strstr(const char *in, const char *str); - -#else /* !KERNEL */ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#define PAGE_SIZE vm_page_size -#define PAGE_MASK (PAGE_SIZE - 1) - -#endif /* KERNEL */ - -#include "kld_patch.h" -#include "c++rem3.h" - -#if 0 -#define DIE() do { for (;;) ; } while(0) - -#if KERNEL -# define LOG_DELAY() /* IODelay(200000) */ -# define DEBUG_LOG(x) do { IOLog x; LOG_DELAY(); } while(0) -#else -# define LOG_DELAY() -# define DEBUG_LOG(x) do { printf x; } while(0) -#endif - -#else - -#define DIE() -#define LOG_DELAY() -#define DEBUG_LOG(x) - -#endif - -// OSObject symbol prefixes and suffixes -#define kCPPSymbolPrefix "_Z" -#define kVTablePrefix "_" kCPPSymbolPrefix "TV" -#define kOSObjPrefix "_" kCPPSymbolPrefix "N" -#define kReservedNamePrefix "_RESERVED" -#define k29SuperClassSuffix "superClass" -#define k31SuperClassSuffix "10superClassE" -#define kGMetaSuffix "10gMetaClassE" -#define kLinkEditSegName SEG_LINKEDIT - -// GCC 2.95 drops 2 leading constants in the vtable -#define kVTablePreambleLen 2 - -// Last address that I'm willing to try find vm in -#define kTopAddr ((unsigned char *) (1024 * 1024 * 1024)) - -// Size in bytes that Data Ref object's get increased in size -// Must be a power of 2 -#define kDataCapacityIncrement 128 - -// My usual set of helper macros. I personally find these macros -// easier to read in the code rather than an explicit error condition -// check. If I don't make it easy then I may get lazy ond not check -// everything. I'm sorry if you find this code harder to read. - -// break_if will evaluate the expression and if it is true -// then it will print the msg, which is enclosed in parens -// and then break. Usually used in loops are do { } while (0) -#define break_if(expr, msg) \ - if (expr) { \ - errprintf msg; \ - break; \ - } - -// return_if will evaluate expr and if true it will log the -// msg, which is enclosed in parens, and then it will return -// with the return code of ret. -#define return_if(expr, ret, msg) do { \ - if (expr) { \ - errprintf msg; \ - return ret; \ - } \ -} while (0) - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif /* MIN */ -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif /* MAX */ - -typedef struct Data { - unsigned long fLength, fCapacity; - unsigned char *fData; -} Data, *DataRef; - -struct sectionRecord { - const struct section *fSection; - DataRef fRelocCache; -}; - -enum patchState { - kSymbolIdentical, - kSymbolLocal, - kSymbolPadUpdate, - kSymbolSuperUpdate, - kSymbolMismatch -}; - -struct patchRecord { - struct nlist *fSymbol; - enum patchState fType; -}; - -struct relocRecord { - void *fValue; - const struct nlist *fSymbol; - struct relocation_info *fRInfo; - void *reserved; -}; - -struct metaClassRecord { - char *fSuperName; - struct fileRecord *fFile; - const struct nlist *fVTableSym; - struct patchRecord *fPatchedVTable; - char fClassName[1]; -}; - -struct fileRecord { - size_t fMapSize, fMachOSize; - unsigned char *fMap, *fMachO, *fPadEnd; - DataRef fClassList; - DataRef fSectData; - DataRef fNewSymbols, fNewStringBlocks; - DataRef fSym2Strings; - struct symtab_command *fSymtab; - struct sectionRecord *fSections; - struct segment_command *fLinkEditSeg; - const char **fSymbToStringTable; - char *fStringBase; - struct nlist *fSymbolBase; - const struct nlist *fLocalSyms; - unsigned int fNSects; - int fNLocal; - Boolean fIsKernel, fNoKernelExecutable, fIsKmem; - Boolean fImageDirty, fSymbolsDirty; - Boolean fRemangled, fFoundOSObject; - const char fPath[1]; -}; - -static DataRef sFilesTable; -static struct fileRecord *sKernelFile; - -static DataRef sMergedFiles; -static DataRef sMergeMetaClasses; -static Boolean sMergedKernel; - -static void errprintf(const char *fmt, ...) -{ - extern void kld_error_vprintf(const char *format, va_list ap); - - va_list ap; - - va_start(ap, fmt); - kld_error_vprintf(fmt, ap); - va_end(ap); - -DIE(); -} - -static __inline__ unsigned long DataGetLength(DataRef data) -{ - return data->fLength; -} - -static __inline__ unsigned char *DataGetPtr(DataRef data) -{ - return data->fData; -} - -static __inline__ unsigned char *DataGetEndPtr(DataRef data) -{ - return data->fData + data->fLength; -} - -static __inline__ unsigned long DataRemaining(DataRef data) -{ - return data->fCapacity - data->fLength; -} - -static __inline__ Boolean DataContainsAddr(DataRef data, void *vAddr) -{ - vm_offset_t offset = (vm_address_t) vAddr; - - if (!data) - return false; - - offset = (vm_address_t) vAddr - (vm_address_t) data->fData; - return (offset < data->fLength); -} - -static Boolean DataEnsureCapacity(DataRef data, unsigned long capacity) -{ - // Don't bother to ever shrink a data object. - if (capacity > data->fCapacity) { - unsigned char *newData; - - capacity += kDataCapacityIncrement - 1; - capacity &= ~(kDataCapacityIncrement - 1); - newData = (unsigned char *) realloc(data->fData, capacity); - if (!newData) - return false; - - bzero(newData + data->fCapacity, capacity - data->fCapacity); - data->fData = newData; - data->fCapacity = capacity; - } - - return true; -} - -static __inline__ Boolean DataSetLength(DataRef data, unsigned long length) -{ - if (DataEnsureCapacity(data, length)) { - data->fLength = length; - return true; - } - else - return false; -} - -static __inline__ Boolean DataAddLength(DataRef data, unsigned long length) -{ - return DataSetLength(data, data->fLength + length); -} - -static __inline__ Boolean -DataAppendBytes(DataRef data, const void *addr, unsigned int len) -{ - unsigned long size = DataGetLength(data); - - if (!DataAddLength(data, len)) - return false; - - bcopy(addr, DataGetPtr(data) + size, len); - return true; -} - -static __inline__ Boolean DataAppendData(DataRef dst, DataRef src) -{ - return DataAppendBytes(dst, DataGetPtr(src), DataGetLength(src)); -} - -static DataRef DataCreate(unsigned long capacity) -{ - DataRef data = (DataRef) malloc(sizeof(Data)); - - if (data) { - if (!capacity) - data->fCapacity = kDataCapacityIncrement; - else { - data->fCapacity = capacity + kDataCapacityIncrement - 1; - data->fCapacity &= ~(kDataCapacityIncrement - 1); - } - - data->fData = (unsigned char *) malloc(data->fCapacity); - if (!data->fData) { - free(data); - return NULL; - } - - bzero(data->fData, data->fCapacity); - data->fLength = 0; - } - return data; -} - -static void DataRelease(DataRef data) -{ - if (data) { - if (data->fData) - free(data->fData); - data->fData = 0; - free(data); - } -} - -static __inline__ const char * -symNameByIndex(const struct fileRecord *file, unsigned int symInd) -{ - return file->fSymbToStringTable[symInd]; -} - -static __inline__ const char * -symbolname(const struct fileRecord *file, const struct nlist *sym) -{ - unsigned int index; - - index = sym - file->fSymbolBase; - if (index < file->fSymtab->nsyms) - return symNameByIndex(file, index); - - if (-1 == sym->n_un.n_strx) - return (const char *) sym->n_value; - - // If the preceding tests fail then we have a getNewSymbol patch and - // the file it refers to has already been patched as the n_strx is set - // to -1 temporarily while we are still processing a file. - // Once we have finished with a file then we repair the 'strx' offset - // to be valid for the repaired file's string table. - return file->fStringBase + sym->n_un.n_strx; -} - -static struct fileRecord * -getFile(const char *path) -{ - if (sFilesTable) { - int i, nfiles; - struct fileRecord **files; - - // Check to see if we have already merged this file - nfiles = DataGetLength(sFilesTable) / sizeof(struct fileRecord *); - files = (struct fileRecord **) DataGetPtr(sFilesTable); - for (i = 0; i < nfiles; i++) { - if (!strcmp(path, files[i]->fPath)) - return files[i]; - } - } - - return NULL; -} - -static struct fileRecord * -addFile(struct fileRecord *file, const char *path) -{ - struct fileRecord *newFile; - - if (!sFilesTable) { - sFilesTable = DataCreate(0); - if (!sFilesTable) - return NULL; - } - - newFile = (struct fileRecord *) - malloc(sizeof(struct fileRecord) + strlen(path)); - if (!newFile) - return NULL; - - if (!DataAppendBytes(sFilesTable, &newFile, sizeof(newFile))) { - free(newFile); - return NULL; - } - - bcopy(file, newFile, sizeof(struct fileRecord) - 1); - strcpy((char *) newFile->fPath, path); - - return newFile; -} - -// @@@ gvdl: need to clean up the sMergeMetaClasses -// @@@ gvdl: I had better fix the object file up again -static void unmapFile(struct fileRecord *file) -{ - if (file->fSectData) { - struct sectionRecord *section; - unsigned int i, nsect; - - nsect = file->fNSects; - section = file->fSections; - for (i = 0; i < nsect; i++, section++) { - if (section->fRelocCache) { - DataRelease(section->fRelocCache); - section->fRelocCache = 0; - } - } - - DataRelease(file->fSectData); - file->fSectData = 0; - file->fSections = 0; - file->fNSects = 0; - } - - if (file->fSym2Strings) { - DataRelease(file->fSym2Strings); - file->fSym2Strings = 0; - } - - if (file->fMap) { -#if KERNEL - if (file->fIsKmem) - kmem_free(kernel_map, (vm_address_t) file->fMap, file->fMapSize); -#else /* !KERNEL */ - if (file->fPadEnd) { - vm_address_t padVM; - vm_size_t padSize; - - padVM = round_page((vm_address_t) file->fMap + file->fMapSize); - padSize = (vm_size_t) ((vm_address_t) file->fPadEnd - padVM); - (void) vm_deallocate(mach_task_self(), padVM, padSize); - file->fPadEnd = 0; - } - - (void) munmap((caddr_t) file->fMap, file->fMapSize); -#endif /* !KERNEL */ - file->fMap = 0; - } -} - -static void removeFile(struct fileRecord *file) -{ - if (file->fClassList) { - DataRelease(file->fClassList); - file->fClassList = 0; - } - - unmapFile(file); - - free(file); -} - -#if !KERNEL -static Boolean -mapObjectFile(struct fileRecord *file, const char *pathName) -{ - Boolean result = false; - static unsigned char *sFileMapBaseAddr = 0; - - int fd = 0; - - if (!sFileMapBaseAddr) { - kern_return_t ret; - vm_address_t probeAddr; - - // If we don't already have a base addr find any random chunk - // of 32 meg of VM and to use the 16 meg boundrary as a base. - ret = vm_allocate(mach_task_self(), &probeAddr, - 32 * 1024 * 1024, VM_FLAGS_ANYWHERE); - return_if(KERN_SUCCESS != ret, false, - ("Unable to allocate base memory %s\n", mach_error_string(ret))); - (void) vm_deallocate(mach_task_self(), probeAddr, 32 * 1024 * 1024); - - // Now round to the next 16 Meg boundrary - probeAddr = (probeAddr + (16 * 1024 * 1024 - 1)) - & ~(16 * 1024 * 1024 - 1); - sFileMapBaseAddr = (unsigned char *) probeAddr; - } - - fd = open(pathName, O_RDONLY, 0); - return_if(fd == -1, false, ("Can't open %s for reading - %s\n", - pathName, strerror(errno))); - - do { - kern_return_t ret; - struct stat sb; - int retaddr = -1; - - break_if(fstat(fd, &sb) == -1, - ("Can't stat %s - %s\n", file->fPath, strerror(errno))); - - file->fMapSize = sb.st_size; - file->fMap = sFileMapBaseAddr; - ret = KERN_SUCCESS; - while (file->fMap < kTopAddr) { - vm_address_t padVM; - vm_address_t padVMEnd; - vm_size_t padSize; - - padVM = round_page((vm_address_t) file->fMap + file->fMapSize); - retaddr = (int) mmap(file->fMap, file->fMapSize, - PROT_READ|PROT_WRITE, - MAP_FIXED|MAP_FILE|MAP_PRIVATE, - fd, 0); - if (-1 == retaddr) { - break_if(ENOMEM != errno, - ("mmap failed %d - %s\n", errno, strerror(errno))); - - file->fMap = (unsigned char *) padVM; - continue; - } - - - // Round up padVM to the next page after the file and assign at - // least another fMapSize more room rounded up to the next page - // boundary. - padVMEnd = round_page(padVM + file->fMapSize); - padSize = padVMEnd - padVM; - ret = vm_allocate( - mach_task_self(), &padVM, padSize, VM_FLAGS_FIXED); - if (KERN_SUCCESS == ret) { - file->fPadEnd = (unsigned char *) padVMEnd; - break; - } - else { - munmap(file->fMap, file->fMapSize); - break_if(KERN_INVALID_ADDRESS != ret, - ("Unable to allocate pad vm for %s - %s\n", - pathName, mach_error_string(ret))); - - file->fMap = (unsigned char *) padVMEnd; - continue; // try again wherever the vm system wants - } - } - - if (-1 == retaddr || KERN_SUCCESS != ret) - break; - - break_if(file->fMap >= kTopAddr, - ("Unable to map memory %s\n", file->fPath)); - - sFileMapBaseAddr = file->fPadEnd; - result = true; - } while(0); - - close(fd); - return result; -} -#endif /* !KERNEL */ - -static Boolean findBestArch(struct fileRecord *file, const char *pathName) -{ - unsigned long magic; - struct fat_header *fat; - - - file->fMachOSize = file->fMapSize; - file->fMachO = file->fMap; - magic = ((const struct mach_header *) file->fMachO)->magic; - fat = (struct fat_header *) file->fMachO; - - // Try to figure out what type of file this is - return_if(file->fMapSize < sizeof(unsigned long), false, - ("%s isn't a valid object file - no magic\n", pathName)); - -#if KERNEL - - // CIGAM is byte-swapped MAGIC - if (magic == FAT_MAGIC || magic == FAT_CIGAM) { - - load_return_t load_return; - struct fat_arch fatinfo; - - load_return = fatfile_getarch(NULL, (vm_address_t) fat, &fatinfo); - return_if(load_return != LOAD_SUCCESS, false, - ("Extension \"%s\": has no code for this computer\n", pathName)); - - file->fMachO = file->fMap + fatinfo.offset; - file->fMachOSize = fatinfo.size; - magic = ((const struct mach_header *) file->fMachO)->magic; - } - -#else /* !KERNEL */ - - // Do we need to in-place swap the endianness of the fat header? - if (magic == FAT_CIGAM) { - unsigned long i; - struct fat_arch *arch; - - fat->nfat_arch = NXSwapBigLongToHost(fat->nfat_arch); - return_if(file->fMapSize < sizeof(struct fat_header) - + fat->nfat_arch * sizeof(struct fat_arch), - false, ("%s is too fat\n", file->fPath)); - - arch = (struct fat_arch *) &fat[1]; - for (i = 0; i < fat->nfat_arch; i++) { - arch[i].cputype = NXSwapBigLongToHost(arch[i].cputype); - arch[i].cpusubtype = NXSwapBigLongToHost(arch[i].cpusubtype); - arch[i].offset = NXSwapBigLongToHost(arch[i].offset); - arch[i].size = NXSwapBigLongToHost(arch[i].size); - arch[i].align = NXSwapBigLongToHost(arch[i].align); - } - - magic = NXSwapBigLongToHost(fat->magic); - } - - // Now see if we can find any valid architectures - if (magic == FAT_MAGIC) { - const NXArchInfo *myArch; - unsigned long fatsize; - struct fat_arch *arch; - - fatsize = sizeof(struct fat_header) - + fat->nfat_arch * sizeof(struct fat_arch); - return_if(file->fMapSize < fatsize, - false, ("%s isn't a valid fat file\n", pathName)); - - myArch = NXGetLocalArchInfo(); - arch = NXFindBestFatArch(myArch->cputype, myArch->cpusubtype, - (struct fat_arch *) &fat[1], fat->nfat_arch); - return_if(!arch, - false, ("%s hasn't got arch for %s\n", pathName, myArch->name)); - return_if(arch->offset + arch->size > file->fMapSize, - false, ("%s's %s arch is incomplete\n", pathName, myArch->name)); - file->fMachO = file->fMap + arch->offset; - file->fMachOSize = arch->size; - magic = ((const struct mach_header *) file->fMachO)->magic; - } - -#endif /* KERNEL */ - - return_if(magic != MH_MAGIC, - false, ("%s isn't a valid mach-o\n", pathName)); - - return true; -} - -static Boolean -parseSegments(struct fileRecord *file, struct segment_command *seg) -{ - struct sectionRecord *sections; - int i, nsects = seg->nsects; - const struct segmentMap { - struct segment_command seg; - const struct section sect[1]; - } *segMap; - - if (!file->fSectData) { - file->fSectData = DataCreate(0); - if (!file->fSectData) - return false; - } - - // Increase length of section DataRef and cache data pointer - if (!DataAddLength(file->fSectData, nsects * sizeof(struct sectionRecord))) - return false; - file->fSections = (struct sectionRecord *) DataGetPtr(file->fSectData); - - // Initialise the new sections - sections = &file->fSections[file->fNSects]; - file->fNSects += nsects; - for (i = 0, segMap = (struct segmentMap *) seg; i < nsects; i++) - sections[i].fSection = &segMap->sect[i]; - - return true; -} - -static Boolean -remangleExternSymbols(struct fileRecord *file, const char *pathName) -{ - const struct nlist *sym; - int i, nsyms, len; - DataRef strings = NULL; - - DEBUG_LOG(("Remangling %s\n", pathName)); - - file->fNewStringBlocks = DataCreate(0); - return_if(!file->fNewStringBlocks, false, - ("Unable to allocate new string table for %s\n", pathName)); - - nsyms = file->fSymtab->nsyms; - for (i = 0, sym = file->fSymbolBase; i < nsyms; i++, sym++) { - Rem3Return ret; - const char *symname; - char *newname; - unsigned char n_type = sym->n_type; - - // Not an external symbol or it is a stab in any case don't bother - if ((n_type ^ N_EXT) & (N_STAB | N_EXT)) - continue; - - symname = symNameByIndex(file, i); - -tryRemangleAgain: - if (!strings) { - strings = DataCreate(16 * 1024); // Arbitrary block size - return_if(!strings, false, - ("Unable to allocate new string block for %s\n", pathName)); - } - - len = DataRemaining(strings); - newname = DataGetEndPtr(strings); - ret = rem3_remangle_name(newname, &len, symname); - switch (ret) { - case kR3InternalNotRemangled: - errprintf("Remangler fails on %s in %s\n", symname, pathName); - /* No break */ - case kR3NotRemangled: - break; - - case kR3Remangled: - file->fSymbToStringTable[i] = newname; - file->fRemangled = file->fSymbolsDirty = true; - DataAddLength(strings, len + 1); // returns strlen - break; - - case kR3BufferTooSmallRemangled: - return_if(!DataAppendBytes - (file->fNewStringBlocks, &strings, sizeof(strings)), - false, ("Unable to allocate string table for %s\n", pathName)); - strings = NULL; - goto tryRemangleAgain; - - case kR3BadArgument: - default: - return_if(true, false, - ("Internal error - remangle of %s\n", pathName)); - } - } - - if (strings) { - return_if(!DataAppendBytes - (file->fNewStringBlocks, &strings, sizeof(strings)), - false, ("Unable to allocate string table for %s\n", pathName)); - } - - return true; -} - -static Boolean parseSymtab(struct fileRecord *file, const char *pathName) -{ - const struct nlist *sym; - unsigned int i, firstlocal, nsyms; - unsigned long strsize; - const char *strbase; - Boolean foundOSObject, found295CPP; - - // we found a link edit segment so recompute the bases - if (file->fLinkEditSeg) { - struct segment_command *link = file->fLinkEditSeg; - - file->fSymbolBase = (struct nlist *) - (link->vmaddr + (file->fSymtab->symoff - link->fileoff)); - file->fStringBase = (char *) - (link->vmaddr + (file->fSymtab->stroff - link->fileoff)); - return_if( ( (caddr_t) file->fStringBase + file->fSymtab->strsize - > (caddr_t) link->vmaddr + link->vmsize ), false, - ("%s isn't a valid mach-o le, bad symbols\n", pathName)); - } - else { - file->fSymbolBase = (struct nlist *) - (file->fMachO + file->fSymtab->symoff); - file->fStringBase = (char *) - (file->fMachO + file->fSymtab->stroff); - return_if( ( file->fSymtab->stroff + file->fSymtab->strsize - > file->fMachOSize ), false, - ("%s isn't a valid mach-o, bad symbols\n", pathName)); - } - - nsyms = file->fSymtab->nsyms; - - // If this file the kernel and do we have an executable image - file->fNoKernelExecutable = (vm_page_size == file->fSymtab->symoff) - && (file->fSections[0].fSection->size == 0); - - // Generate a table of pointers to strings indexed by the symbol number - - file->fSym2Strings = DataCreate(nsyms * sizeof(const char *)); - DataSetLength(file->fSym2Strings, nsyms * sizeof(const char *)); - return_if(!file->fSym2Strings, false, - ("Unable to allocate memory - symbol string trans\n", pathName)); - file->fSymbToStringTable = (const char **) DataGetPtr(file->fSym2Strings); - - // Search for the first non-stab symbol in table - strsize = file->fSymtab->strsize; - strbase = file->fStringBase; - firstlocal = 0; - found295CPP = foundOSObject = false; - for (i = 0, sym = file->fSymbolBase; i < nsyms; i++, sym++) { - long strx = sym->n_un.n_strx; - const char *symname = strbase + strx; - unsigned char n_type; - - return_if(((unsigned long) strx > strsize), false, - ("%s has an illegal string offset in symbol %d\n", pathName, i)); - - // Load up lookup symbol look table with sym names - file->fSymbToStringTable[i] = symname; - - n_type = sym->n_type & (N_TYPE | N_EXT); - - // Find the first exported symbol - if ( !firstlocal && (n_type & N_EXT) ) { - firstlocal = i; - file->fLocalSyms = sym; - } - - // Find the a OSObject based subclass by searching for symbols - // that have a suffix of '10superClassE' - symname++; // Skip leading '_' - - if (!foundOSObject - && (n_type == (N_SECT | N_EXT) || n_type == (N_ABS | N_EXT)) - && strx) { - const char *suffix, *endSym; - - endSym = symname + strlen(symname); - - // Find out if this symbol has the superclass suffix. - if (symname[0] == kCPPSymbolPrefix[0] - && symname[1] == kCPPSymbolPrefix[1]) { - - suffix = endSym - sizeof(k31SuperClassSuffix) + 1; - - // Check for a gcc3 OSObject subclass - if (suffix > symname - && !strcmp(suffix, k31SuperClassSuffix)) - foundOSObject = true; - } - else { - suffix = endSym - sizeof(k29SuperClassSuffix); - - // Check for a gcc295 OSObject subclass - if (suffix > symname - && ('.' == *suffix || '$' == *suffix) - && !strcmp(suffix+1, k29SuperClassSuffix)) { - found295CPP = foundOSObject = true; - } - else if (!found295CPP) { - // Finally just check if we need to remangle - symname++; // skip leading '__' - while (*symname) { - if ('_' == *symname++ && '_' == *symname++) { - found295CPP = true; - break; - } - } - } - } - } - else if (sym->n_type == (N_EXT | N_UNDF)) { - if ( !file->fNLocal) // Find the last local symbol - file->fNLocal = i - firstlocal; - if (!found295CPP) { - symname++; // Skip possible second '_' at start. - while (*symname) { - if ('_' == *symname++ && '_' == *symname++) { - found295CPP = true; - break; - } - } - } - } - // Note symname is trashed at this point - } - return_if(i < nsyms, false, - ("%s isn't a valid mach-o, bad symbol strings\n", pathName)); - - return_if(!file->fLocalSyms, false, ("%s has no symbols?\n", pathName)); - - // If we don't have any undefined symbols then all symbols - // must be local so just compute it now if necessary. - if ( !file->fNLocal ) - file->fNLocal = i - firstlocal; - - file->fFoundOSObject = foundOSObject; - - if (found295CPP && !remangleExternSymbols(file, pathName)) - return false; - - return true; -} - -// @@@ gvdl: These functions need to be hashed they are -// going to be way too slow for production code. -static const struct nlist * -findSymbolByAddress(const struct fileRecord *file, void *entry) -{ - // not quite so dumb linear search of all symbols - const struct nlist *sym; - int i, nsyms; - - // First try to find the symbol in the most likely place which is the - // extern symbols - sym = file->fLocalSyms; - for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) { - if (sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) ) - return sym; - } - - // Didn't find it in the external symbols so try to local symbols before - // giving up. - sym = file->fSymbolBase; - for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) { - if ( (sym->n_type & N_EXT) ) - return NULL; - if ( sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) ) - return sym; - } - - return NULL; -} - -struct searchContext { - const char *fSymname; - const struct fileRecord *fFile; -}; - -static int symbolSearch(const void *vKey, const void *vSym) -{ - const struct searchContext *key = (const struct searchContext *) vKey; - const struct nlist *sym = (const struct nlist *) vSym; - - return strcmp(key->fSymname + 1, symbolname(key->fFile, sym) + 1); -} - -static const struct nlist * -findSymbolByName(struct fileRecord *file, const char *symname) -{ - if (file->fRemangled) { - // @@@ gvdl: Performance problem - // Linear search as we don't sort after remangling - const struct nlist *sym; - int i = file->fLocalSyms - file->fSymbolBase; - int nLocal = file->fNLocal + i; - - for (sym = file->fLocalSyms; i < nLocal; i++, sym++) - if (!strcmp(symNameByIndex(file, i) + 1, symname + 1)) - return sym; - return NULL; - } - else { - struct searchContext context; - - context.fSymname = symname; - context.fFile = file; - return (struct nlist *) - bsearch(&context, - file->fLocalSyms, file->fNLocal, sizeof(struct nlist), - symbolSearch); - } -} - -static Boolean -relocateSection(const struct fileRecord *file, struct sectionRecord *sectionRec) -{ - const struct nlist *symbol; - const struct section *section; - struct relocRecord *rec; - struct relocation_info *rinfo; - unsigned long i; - unsigned long r_address, r_symbolnum, r_length; - enum reloc_type_generic r_type; - UInt8 *sectionBase; - void **entry; - - sectionRec->fRelocCache = DataCreate( - sectionRec->fSection->nreloc * sizeof(struct relocRecord)); - if (!sectionRec->fRelocCache) - return false; - - section = sectionRec->fSection; - sectionBase = file->fMachO + section->offset; - - rec = (struct relocRecord *) DataGetPtr(sectionRec->fRelocCache); - rinfo = (struct relocation_info *) (file->fMachO + section->reloff); - for (i = 0; i < section->nreloc; i++, rec++, rinfo++) { - - // Totally uninterested in scattered relocation entries - if ( (rinfo->r_address & R_SCATTERED) ) - continue; - - r_address = rinfo->r_address; - entry = (void **) (sectionBase + r_address); - - /* - * The r_address field is really an offset into the contents of the - * section and must reference something inside the section (Note - * that this is not the case for PPC_RELOC_PAIR entries but this - * can't be one with the above checks). - */ - return_if(r_address >= section->size, false, - ("Invalid relocation entry in %s - not in section\n", file->fPath)); - - // If we don't have a VANILLA entry or the Vanilla entry isn't - // a 'long' then ignore the entry and try the next. - r_type = (enum reloc_type_generic) rinfo->r_type; - r_length = rinfo->r_length; - if (r_type != GENERIC_RELOC_VANILLA || r_length != 2) - continue; - - r_symbolnum = rinfo->r_symbolnum; - - /* - * If rinfo->r_extern is set this relocation entry is an external entry - * else it is a local entry. - */ - if (rinfo->r_extern) { - /* - * This is an external relocation entry. - * r_symbolnum is an index into the input file's symbol table - * of the symbol being refered to. The symbol must be - * undefined to be used in an external relocation entry. - */ - return_if(r_symbolnum >= file->fSymtab->nsyms, false, - ("Invalid relocation entry in %s - no symbol\n", file->fPath)); - - /* - * If this is an indirect symbol resolve indirection (all chains - * of indirect symbols have been resolved so that they point at - * a symbol that is not an indirect symbol). - */ - symbol = file->fSymbolBase; - if ((symbol[r_symbolnum].n_type & N_TYPE) == N_INDR) - r_symbolnum = symbol[r_symbolnum].n_value; - symbol = &symbol[r_symbolnum]; - - return_if(symbol->n_type != (N_EXT | N_UNDF), false, - ("Invalid relocation entry in %s - extern\n", file->fPath)); - } - else { - /* - * If the symbol is not in any section then it can't be a - * pointer to a local segment and I don't care about it. - */ - if (r_symbolnum == R_ABS) - continue; - - // Note segment references are offset by 1 from 0. - return_if(r_symbolnum > file->fNSects, false, - ("Invalid relocation entry in %s - local\n", file->fPath)); - - // Find the symbol, if any, that backs this entry - symbol = findSymbolByAddress(file, *entry); - } - - rec->fValue = *entry; // Save the previous value - rec->fRInfo = rinfo; // Save a pointer to the reloc - rec->fSymbol = symbol; // Record the current symbol - - *entry = (void *) rec; // Save pointer to record in object image - } - - DataSetLength(sectionRec->fRelocCache, i * sizeof(struct relocRecord)); - ((struct fileRecord *) file)->fImageDirty = true; - - return true; -} - -static const struct nlist * -findSymbolRefAtLocation(const struct fileRecord *file, - struct sectionRecord *sctn, void **loc) -{ - if (file->fIsKernel) { - if (*loc) - return findSymbolByAddress(file, *loc); - } - else if (sctn->fRelocCache || relocateSection(file, sctn)) { - struct relocRecord *reloc = (struct relocRecord *) *loc; - - if (DataContainsAddr(sctn->fRelocCache, reloc)) - return reloc->fSymbol; - } - - return NULL; -} - -static Boolean -addClass(struct fileRecord *file, - struct metaClassRecord *inClass, - const char *cname) -{ - Boolean result = false; - struct metaClassRecord *newClass = NULL; - struct metaClassRecord **fileClasses = NULL; - int len; - - if (!file->fClassList) { - file->fClassList = DataCreate(0); - if (!file->fClassList) - return false; - } - - do { - // Attempt to allocate all necessary resource first - len = strlen(cname) + 1 - + (int) (&((struct metaClassRecord *) 0)->fClassName); - newClass = (struct metaClassRecord *) malloc(len); - if (!newClass) - break; - - if (!DataAddLength(file->fClassList, sizeof(struct metaClassRecord *))) - break; - fileClasses = (struct metaClassRecord **) - (DataGetPtr(file->fClassList) + DataGetLength(file->fClassList)); - - // Copy the meta Class structure and string name into newClass and - // insert object at end of the file->fClassList and sMergeMetaClasses - *newClass = *inClass; - strcpy(newClass->fClassName, cname); - fileClasses[-1] = newClass; - - return true; - } while (0); - - if (fileClasses) - DataAddLength(file->fClassList, -sizeof(struct metaClassRecord *)); - - if (newClass) - free(newClass); - - return result; -} - -static struct metaClassRecord *getClass(DataRef classList, const char *cname) -{ - if (classList) { - int i, nclass; - struct metaClassRecord **classes, *thisClass; - - nclass = DataGetLength(classList) / sizeof(struct metaClassRecord *); - classes = (struct metaClassRecord **) DataGetPtr(classList); - for (i = 0; i < nclass; i++) { - thisClass = classes[i]; - if (!strcmp(thisClass->fClassName, cname)) - return thisClass; - } - } - - return NULL; -} - -// Add the class 'cname' to the list of known OSObject based classes -// Note 'sym' is the 10superClassE symbol. -static Boolean -recordClass(struct fileRecord *file, const char *cname, const struct nlist *sym) -{ - Boolean result = false; - char *supername = NULL; - const char *classname = NULL; - struct metaClassRecord newClass; - char strbuffer[1024]; - - // Only do the work to find the super class if we are - // not currently working on the kernel. The kernel is the end - // of all superclass chains by definition as the kernel must be binary - // compatible with itself. - if (!file->fIsKernel) { - const char *suffix; - const struct nlist *supersym; - const struct section *section; - struct sectionRecord *sectionRec; - unsigned char sectind = sym->n_sect; - const char *superstr; - void **location; - int snamelen; - - // We can't resolve anything that isn't in a real section - // Note that the sectind is starts at one to make room for the - // NO_SECT flag but the fNSects field isn't offset so we have a - // '>' test. Which means this isn't an OSObject based class - if (sectind == NO_SECT || sectind > file->fNSects) { - result = true; - goto finish; - } - sectionRec = file->fSections + sectind - 1; - section = sectionRec->fSection; - location = (void **) ( file->fMachO + section->offset - + sym->n_value - section->addr ); - - supersym = findSymbolRefAtLocation(file, sectionRec, location); - if (!supersym) { - result = true; // No superclass symbol then it isn't an OSObject. - goto finish; - } - - // Find string in file and skip leading '_' and then find the suffix - superstr = symbolname(file, supersym) + 1; - suffix = superstr + strlen(superstr) - sizeof(kGMetaSuffix) + 1; - if (suffix <= superstr || strcmp(suffix, kGMetaSuffix)) { - result = true; // Not an OSObject superclass so ignore it.. - goto finish; - } - - // Got a candidate so hand it over for class processing. - snamelen = suffix - superstr - sizeof(kOSObjPrefix) + 2; - supername = (char *) malloc(snamelen + 1); - bcopy(superstr + sizeof(kOSObjPrefix) - 2, supername, snamelen); - supername[snamelen] = '\0'; - } - - do { - break_if(getClass(file->fClassList, cname), - ("Duplicate class %s in %s\n", cname, file->fPath)); - - snprintf(strbuffer, sizeof(strbuffer), "%s%s", kVTablePrefix, cname); - newClass.fVTableSym = findSymbolByName(file, strbuffer); - break_if(!newClass.fVTableSym, - ("Can't find vtable %s in %s\n", cname, file->fPath)); - - newClass.fFile = file; - newClass.fSuperName = supername; - newClass.fPatchedVTable = NULL; - - // Can't use cname as it may be a stack variable - // However the vtable's string has the class name as a suffix - // so why don't we use that rather than mallocing a string. - classname = symbolname(file, newClass.fVTableSym) - + sizeof(kVTablePrefix) - 1; - break_if(!addClass(file, &newClass, classname), - ("recordClass - no memory?\n")); - - supername = NULL; - result = true; - } while (0); - -finish: - if (supername) - free(supername); - - return result; -} - - -static Boolean getMetaClassGraph(struct fileRecord *file) -{ - const struct nlist *sym; - int i, nsyms; - - // Search the symbol table for the local symbols that are generated - // by the metaclass system. There are three metaclass variables - // that are relevant. - // - // .metaClass A pointer to the meta class structure. - // .superClass A pointer to the super class's meta class. - // .gMetaClass The meta class structure itself. - // ___vt The VTable for the class . - // - // In this code I'm going to search for any symbols that - // ends in k31SuperClassSuffix as this indicates this class is a conforming - // OSObject subclass and will need to be patched, and it also - // contains a pointer to the super class's meta class structure. - sym = file->fLocalSyms; - for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) { - const char *symname; - const char *suffix; - char classname[1024]; - unsigned char n_type = sym->n_type & (N_TYPE | N_EXT); - int cnamelen; - - // Check that the symbols is a global and that it has a name. - if (((N_SECT | N_EXT) != n_type && (N_ABS | N_EXT) != n_type) - || !sym->n_un.n_strx) - continue; - - // Only search from the last *sep* in the symbol. - // but skip the leading '_' in all symbols first. - symname = symbolname(file, sym) + 1; - if (symname[0] != kCPPSymbolPrefix[0] - || symname[1] != kCPPSymbolPrefix[1]) - continue; - - suffix = symname + strlen(symname) - sizeof(k31SuperClassSuffix) + 1; - if (suffix <= symname || strcmp(suffix, k31SuperClassSuffix)) - continue; - - // Got a candidate so hand it over for class processing. - cnamelen = suffix - symname - sizeof(kOSObjPrefix) + 2; - return_if(cnamelen + 1 >= (int) sizeof(classname), - false, ("Symbol %s is too long", symname)); - - bcopy(symname + sizeof(kOSObjPrefix) - 2, classname, cnamelen); - classname[cnamelen] = '\0'; - if (!recordClass(file, classname, sym)) - return false; - } - - return_if(!file->fClassList, false, ("Internal error, " - "getMetaClassGraph(%s) found no classes", file->fPath)); - - DEBUG_LOG(("Found %ld classes in %p for %s\n", - DataGetLength(file->fClassList)/sizeof(void*), - file->fClassList, file->fPath)); - - return true; -} - -static Boolean mergeOSObjectsForFile(const struct fileRecord *file) -{ - int i, nmerged; - Boolean foundDuplicates = false; - - DEBUG_LOG(("Merging file %s\n", file->fPath)); // @@@ gvdl: - - if (!file->fClassList) - return true; - - if (!sMergedFiles) { - sMergedFiles = DataCreate(0); - return_if(!sMergedFiles, false, - ("Unable to allocate memory metaclass list\n", file->fPath)); - } - - // Check to see if we have already merged this file - nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *); - for (i = 0; i < nmerged; i++) { - if (file == ((void **) DataGetPtr(sMergedFiles))[i]) - return true; - } - - if (!sMergeMetaClasses) { - sMergeMetaClasses = DataCreate(0); - return_if(!sMergeMetaClasses, false, - ("Unable to allocate memory metaclass list\n", file->fPath)); - } - else { /* perform a duplicate check */ - int i, j, cnt1, cnt2; - struct metaClassRecord **list1, **list2; - - list1 = (struct metaClassRecord **) DataGetPtr(file->fClassList); - cnt1 = DataGetLength(file->fClassList) / sizeof(*list1); - list2 = (struct metaClassRecord **) DataGetPtr(sMergeMetaClasses); - cnt2 = DataGetLength(sMergeMetaClasses) / sizeof(*list2); - - for (i = 0; i < cnt1; i++) { - for (j = 0; j < cnt2; j++) { - if (!strcmp(list1[i]->fClassName, list2[j]->fClassName)) { - errprintf("duplicate class %s in %s & %s\n", - list1[i]->fClassName, - file->fPath, list2[j]->fFile->fPath); - } - } - } - } - if (foundDuplicates) - return false; - - return_if(!DataAppendBytes(sMergedFiles, &file, sizeof(file)), false, - ("Unable to allocate memory to merge %s\n", file->fPath)); - - return_if(!DataAppendData(sMergeMetaClasses, file->fClassList), false, - ("Unable to allocate memory to merge %s\n", file->fPath)); - - if (file == sKernelFile) - sMergedKernel = true; - - return true; -} - -// Returns a pointer to the base of the section offset by the sections -// base address. The offset is so that we can add nlist::n_values directly -// to this address and get a valid pointer in our memory. -static unsigned char * -getSectionForSymbol(const struct fileRecord *file, const struct nlist *symb, - void ***endP) -{ - const struct section *section; - unsigned char sectind; - unsigned char *base; - - sectind = symb->n_sect; // Default to symbols section - if ((symb->n_type & N_TYPE) == N_ABS && file->fIsKernel) { - // Absolute symbol so we have to iterate over our sections - for (sectind = 1; sectind <= file->fNSects; sectind++) { - unsigned long start, end; - - section = file->fSections[sectind - 1].fSection; - start = section->addr; - end = start + section->size; - if (start <= symb->n_value && symb->n_value < end) { - // Found the relevant section - break; - } - } - } - - // Is the vtable in a valid section? - return_if(sectind == NO_SECT || sectind > file->fNSects, - (unsigned char *) -1, - ("%s isn't a valid kext, bad section reference\n", file->fPath)); - - section = file->fSections[sectind - 1].fSection; - - // for when we start walking the vtable so compute offset's now. - base = file->fMachO + section->offset; - *endP = (void **) (base + section->size); - - return base - section->addr; // return with addr offset -} - -static Boolean resolveKernelVTable(struct metaClassRecord *metaClass) -{ - const struct fileRecord *file; - struct patchRecord *patchedVTable; - void **curEntry, **vtableEntries, **endSection; - unsigned char *sectionBase; - struct patchRecord *curPatch; - int classSize; - - // Should never occur but it doesn't cost us anything to check. - if (metaClass->fPatchedVTable) - return true; - - DEBUG_LOG(("Kernel vtable %s\n", metaClass->fClassName)); // @@@ gvdl: - - // Do we have a valid vtable to patch? - return_if(!metaClass->fVTableSym, - false, ("Internal error - no class vtable symbol?\n")); - - file = metaClass->fFile; - - // If the metaClass we are being to ask is in the kernel then we - // need to do a quick scan to grab the fPatchList in a reliable format - // however we don't need to check the superclass in the kernel - // as the kernel vtables are always correct wrt themselves. - // Note this ends the superclass chain recursion. - return_if(!file->fIsKernel, - false, ("Internal error - resolveKernelVTable not kernel\n")); - - if (file->fNoKernelExecutable) { - // Oh dear attempt to map the kernel's VM into my memory space - return_if(file->fNoKernelExecutable, false, - ("Internal error - fNoKernelExecutable not implemented yet\n")); - } - - // We are going to need the base and the end - sectionBase = getSectionForSymbol(file, metaClass->fVTableSym, &endSection); - if (-1 == (long) sectionBase) - return false; - - vtableEntries = (void **) (sectionBase + metaClass->fVTableSym->n_value); - curEntry = vtableEntries + kVTablePreambleLen; - for (classSize = 0; curEntry < endSection && *curEntry; classSize++) - curEntry++; - - return_if(*curEntry, false, ("Bad kernel image, short section\n")); - - patchedVTable = (struct patchRecord *) - malloc((classSize + 1) * sizeof(struct patchRecord)); - return_if(!patchedVTable, false, ("resolveKernelVTable - no memory\n")); - - // Copy the vtable of this class into the patch table - curPatch = patchedVTable; - curEntry = vtableEntries + kVTablePreambleLen; - for (; *curEntry; curEntry++, curPatch++) { - curPatch->fSymbol = (struct nlist *) - findSymbolByAddress(file, *curEntry); - curPatch->fType = kSymbolLocal; - } - - // Tag the end of the patch vtable - curPatch->fSymbol = NULL; - metaClass->fPatchedVTable = patchedVTable; - - return true; -} - -static const char *addNewString(struct fileRecord *file, - const char *strname, int namelen) -{ - DataRef strings = 0; - const char *newStr; - - namelen++; // Include terminating '\0'; - - // Make sure we have a string table as well for this symbol - if (file->fNewStringBlocks) { - DataRef *blockTable = (DataRef *) DataGetPtr(file->fNewStringBlocks); - int index = DataGetLength(file->fNewStringBlocks) / sizeof(DataRef*); - strings = blockTable[index - 1]; - if (DataRemaining(strings) < namelen) - strings = 0; - } - else - { - file->fNewStringBlocks = DataCreate(0); - return_if(!file->fNewStringBlocks, NULL, - ("Unable to allocate new string table %s\n", file->fPath)); - } - - if (!strings) { - int size = (namelen + 1023) & ~1023; - if (size < 16 * 1024) - size = 16 * 1024; - strings = DataCreate(size); - return_if(!strings, NULL, - ("Unable to allocate new string block %s\n", file->fPath)); - return_if( - !DataAppendBytes(file->fNewStringBlocks, &strings, sizeof(strings)), - false, ("Unable to allocate string table for %s\n", file->fPath)); - } - - newStr = DataGetEndPtr(strings); - DataAppendBytes(strings, strname, namelen); - return newStr; -} - -// reloc->fPatch must contain a valid pointer -static struct nlist * -getNewSymbol(struct fileRecord *file, - const struct relocRecord *reloc, const char *supername) -{ - unsigned int size, i; - struct nlist **sym; - struct nlist *msym; - struct relocation_info *rinfo; - const char *newStr; - - if (!file->fNewSymbols) { - file->fNewSymbols = DataCreate(0); - return_if(!file->fNewSymbols, NULL, - ("Unable to allocate new symbol table for %s\n", file->fPath)); - } - - rinfo = (struct relocation_info *) reloc->fRInfo; - size = DataGetLength(file->fNewSymbols) / sizeof(struct nlist *); - sym = (struct nlist **) DataGetPtr(file->fNewSymbols); - for (i = 0; i < size; i++, sym++) { - int symnum = i + file->fSymtab->nsyms; - newStr = symNameByIndex(file, symnum); - if (!strcmp(newStr, supername)) { - rinfo->r_symbolnum = symnum; - file->fSymbolsDirty = true; - return *sym; - } - } - - // Assert that this is a vaild symbol. I need this condition to be true - // for the later code to make non-zero. So the first time through I'd - // better make sure that it is 0. - return_if(reloc->fSymbol->n_sect, NULL, - ("Undefined symbol entry with non-zero section %s:%s\n", - file->fPath, symbolname(file, reloc->fSymbol))); - - // If we are here we didn't find the symbol so create a new one now - msym = (struct nlist *) malloc(sizeof(struct nlist)); - return_if(!msym, - NULL, ("Unable to create symbol table entry for %s", file->fPath)); - return_if(!DataAppendBytes(file->fNewSymbols, &msym, sizeof(msym)), - NULL, ("Unable to grow symbol table for %s\n", file->fPath)); - - newStr = addNewString(file, supername, strlen(supername)); - if (!newStr) - return NULL; - // If we are here we didn't find the symbol so create a new one now - return_if(!DataAppendBytes(file->fSym2Strings, &newStr, sizeof(newStr)), - NULL, ("Unable to grow symbol table for %s\n", file->fPath)); - file->fSymbToStringTable = (const char **) DataGetPtr(file->fSym2Strings); - - // Offset the string index by the original string table size - // and negate the address to indicate that this is a 'new' symbol - msym->n_un.n_strx = -1; - msym->n_type = (N_EXT | N_UNDF); - msym->n_sect = NO_SECT; - msym->n_desc = 0; - msym->n_value = (unsigned long) newStr; - - // Mark the old symbol as being potentially deletable I can use the - // n_sect field as the input symbol must be of type N_UNDF which means - // that the n_sect field must be set to NO_SECT otherwise it is an - // in valid input file. - ((struct nlist *) reloc->fSymbol)->n_un.n_strx - = -reloc->fSymbol->n_un.n_strx; - ((struct nlist *) reloc->fSymbol)->n_sect = (unsigned char) -1; - - rinfo->r_symbolnum = i + file->fSymtab->nsyms; - file->fSymbolsDirty = true; - return msym; -} - -static struct nlist * -fixOldSymbol(struct fileRecord *file, - const struct relocRecord *reloc, const char *supername) -{ - unsigned int namelen; - struct nlist *sym = (struct nlist *) reloc->fSymbol; - const char *oldname = symbolname(file, sym); - - // assert(sym->n_un.n_strx >= 0); - - namelen = strlen(supername); - - sym->n_un.n_strx = -sym->n_un.n_strx; - if (oldname && namelen < strlen(oldname)) - { - // Overwrite old string in string table - strcpy((char *) oldname, supername); - file->fSymbolsDirty = true; - return sym; - } - - oldname = addNewString(file, supername, namelen); - if (!oldname) - return NULL; - - file->fSymbToStringTable[sym - file->fSymbolBase] = oldname; - file->fSymbolsDirty = true; - return sym; -} - -static enum patchState -symbolCompare(const struct fileRecord *file, - const struct nlist *classsym, - const char *supername) -{ - const char *classname; - - - // Check to see if the target function is locally defined - // if it is then we can assume this is a local vtable override - if ((classsym->n_type & N_TYPE) != N_UNDF) - return kSymbolLocal; - - // Check to see if both symbols point to the same symbol name - // if so then we are still identical. - classname = symbolname(file, classsym); - if (!strcmp(classname, supername)) - return kSymbolIdentical; - - // We know that the target's vtable entry is different from the - // superclass' vtable entry. This means that we will have to apply a - // patch to the current entry, however before returning lets check to - // see if we have a _RESERVEDnnn field 'cause we can use this as a - // registration point that must align between vtables. - if (strstr(supername, kReservedNamePrefix)) - return kSymbolMismatch; - - // OK, we have a superclass difference where the superclass doesn't - // reference a pad function so assume that the superclass is correct. - if (strstr(classname, kReservedNamePrefix)) - return kSymbolPadUpdate; - else - return kSymbolSuperUpdate; -} - -static Boolean patchVTable(struct metaClassRecord *metaClass) -{ - struct metaClassRecord *super = NULL; - struct fileRecord *file; - struct patchRecord *patchedVTable; - struct relocRecord **curReloc, **vtableRelocs, **endSection; - unsigned char *sectionBase; - int classSize; - - // Should never occur but it doesn't cost us anything to check. - if (metaClass->fPatchedVTable) - return true; - - // Do we have a valid vtable to patch? - return_if(!metaClass->fVTableSym, - false, ("Internal error - no class vtable symbol?\n")); - - file = metaClass->fFile; - - // If the metaClass we are being to ask is in the kernel then we - // need to do a quick scan to grab the fPatchList in a reliable format - // however we don't need to check the superclass in the kernel - // as the kernel vtables are always correct wrt themselves. - // Note this ends the superclass chain recursion. - return_if(file->fIsKernel, - false, ("Internal error - patchVTable shouldn't used for kernel\n")); - - if (!metaClass->fSuperName) - return false; - - // The class isn't in the kernel so make sure that the super class - // is patched before patching ouselves. - super = getClass(sMergeMetaClasses, metaClass->fSuperName); - return_if(!super, false, ("Can't find superclass for %s : %s\n", - metaClass->fClassName, metaClass->fSuperName)); - - // Superclass recursion if necessary - if (!super->fPatchedVTable) { - Boolean res; - - if (super->fFile->fIsKernel) - res = resolveKernelVTable(super); - else - res = patchVTable(super); - if (!res) - return false; - } - - DEBUG_LOG(("Patching %s\n", metaClass->fClassName)); // @@@ gvdl: - - // We are going to need the base and the end - - sectionBase = getSectionForSymbol(file, - metaClass->fVTableSym, (void ***) &endSection); - if (-1 == (long) sectionBase) - return false; - - vtableRelocs = (struct relocRecord **) - (sectionBase + metaClass->fVTableSym->n_value); - curReloc = vtableRelocs + kVTablePreambleLen; - for (classSize = 0; curReloc < endSection && *curReloc; classSize++) - curReloc++; - - return_if(*curReloc, false, - ("%s isn't a valid kext, short section\n", file->fPath)); - - patchedVTable = (struct patchRecord *) - malloc((classSize + 1) * sizeof(struct patchRecord)); - return_if(!patchedVTable, false, ("patchedVTable - no memory\n")); - - do { - struct patchRecord *curPatch; - struct nlist *symbol; - - curPatch = patchedVTable; - curReloc = vtableRelocs + kVTablePreambleLen; - - // Grab the super table patches if necessary - // Can't be patching a kernel table as we don't walk super - // class chains in the kernel symbol space. - if (super && super->fPatchedVTable) { - const struct patchRecord *spp; - - spp = super->fPatchedVTable; - - for ( ; spp->fSymbol; curReloc++, spp++, curPatch++) { - const char *supername = - symbolname(super->fFile, spp->fSymbol); - - symbol = (struct nlist *) (*curReloc)->fSymbol; - - curPatch->fType = symbolCompare(file, symbol, supername); - switch (curPatch->fType) { - case kSymbolIdentical: - case kSymbolLocal: - break; - - case kSymbolSuperUpdate: - symbol = getNewSymbol(file, (*curReloc), supername); - break; - - case kSymbolPadUpdate: - symbol = fixOldSymbol(file, (*curReloc), supername); - break; - - case kSymbolMismatch: - errprintf("%s is not compatible with its superclass, " - "%s superclass changed?\n", - metaClass->fClassName, super->fClassName); - goto abortPatch; - - default: - errprintf("Internal error - unknown patch type\n"); - goto abortPatch; - } - if (symbol) { - curPatch->fSymbol = symbol; - (*curReloc)->fSymbol = symbol; - } - else - goto abortPatch; - } - } - - // Copy the remainder of this class' vtable into the patch table - for (; *curReloc; curReloc++, curPatch++) { - // Local reloc symbols - curPatch->fType = kSymbolLocal; - curPatch->fSymbol = (struct nlist *) (*curReloc)->fSymbol; - } - - // Tag the end of the patch vtable - curPatch->fSymbol = NULL; - - metaClass->fPatchedVTable = patchedVTable; - return true; - } while(0); - -abortPatch: - if (patchedVTable) - free(patchedVTable); - - return false; -} - -static Boolean growImage(struct fileRecord *file, vm_size_t delta) -{ -#if !KERNEL - file->fMachOSize += delta; - return (file->fMachO + file->fMachOSize <= file->fPadEnd); -#else /* KERNEL */ - vm_address_t startMachO, endMachO, endMap; - vm_offset_t newMachO; - vm_size_t newsize; - unsigned long i, last = 0; - struct metaClassRecord **classes = NULL; - struct sectionRecord *section; - kern_return_t ret; - - startMachO = (vm_address_t) file->fMachO; - endMachO = startMachO + file->fMachOSize + delta; - endMap = (vm_address_t) file->fMap + file->fMapSize; - - // Do we have room in the current mapped image - if (endMachO < round_page(endMap)) { - file->fMachOSize += delta; - return true; - } - - newsize = endMachO - startMachO; - if (newsize < round_page(file->fMapSize)) { - DEBUG_LOG(("Growing image %s by moving\n", file->fPath)); - - // We have room in the map if we shift the macho image within the - // current map. We will have to patch up pointers into the object. - newMachO = (vm_offset_t) file->fMap; - bcopy((char *) startMachO, (char *) newMachO, file->fMachOSize); - } - else if (file->fIsKmem) { - // kmem_alloced mapping so we can try a kmem_realloc - ret = kmem_realloc(kernel_map, - (vm_address_t) file->fMap, - (vm_size_t) file->fMapSize, - &newMachO, - newsize); - if (KERN_SUCCESS != ret) - return false; - - // If the mapping didn't move then just return - if ((vm_address_t) file->fMap == newMachO) { - file->fMachOSize = file->fMapSize = newsize; - return true; - } - - DEBUG_LOG(("Growing image %s by reallocing\n", file->fPath)); - // We have relocated the kmem image so we are going to have to - // move all of the pointers into the image around. - } - else { - DEBUG_LOG(("Growing image %s by allocating\n", file->fPath)); - // The image doesn't have room for us and I can't kmem_realloc - // then I just have to bite the bullet and copy the object code - // into a bigger memory segment - ret = kmem_alloc(kernel_map, &newMachO, newsize); - - if (KERN_SUCCESS != ret) - return false; - bcopy((char *) startMachO, (void *) newMachO, file->fMachOSize); - file->fIsKmem = true; - } - - - file->fMap = file->fMachO = (unsigned char *) newMachO; - file->fMapSize = newsize; - file->fMachOSize += delta; // Increment the image size - - // If we are here then we have shifted the object image in memory - // I really should change all of my pointers into the image to machO offsets - // but I have run out of time. So I'm going to very quickly go over the - // cached data structures and add adjustments to the addresses that are - // affected. I wonder how long it will take me to get them all. - // - // For every pointer into the MachO I need to add an adjustment satisfying - // the following simultanous equations - // addr_old = macho_old + fixed_offset - // addr_new = macho_new + fixed_offset therefore: - // addr_new = addr_old + (macho_new - macho_old) -#define REBASE(addr, delta) ( ((vm_address_t) (addr)) += (delta) ) - delta = newMachO - startMachO; - - // Rebase the cached-in object 'struct symtab_command' pointer - REBASE(file->fSymtab, delta); - - // Rebase the cached-in object 'struct nlist' pointer for all symbols - REBASE(file->fSymbolBase, delta); - - // Rebase the cached-in object 'struct nlist' pointer for local symbols - REBASE(file->fLocalSyms, delta); - - // Rebase the cached-in object 'char' pointer for the string table - REBASE(file->fStringBase, delta); - - // Ok now we have to go over all of the relocs one last time - // to clean up the pad updates which had their string index negated - // to indicate that we have finished with them. - section = file->fSections; - for (i = 0, last = file->fNSects; i < last; i++, section++) - REBASE(section->fSection, delta); - - // We only ever grow images that contain class lists so dont bother - // the check if file->fClassList is non-zero 'cause it can't be - // assert(file->fClassList); - last = DataGetLength(file->fClassList) - / sizeof(struct metaClassRecord *); - classes = (struct metaClassRecord **) DataGetPtr(file->fClassList); - for (i = 0; i < last; i++) { - struct patchRecord *patch; - - for (patch = classes[i]->fPatchedVTable; patch->fSymbol; patch++) { - vm_address_t symAddr = (vm_address_t) patch->fSymbol; - - // Only need to rebase if the symbol is part of the image - // If this is a new symbol then it was independantly allocated - if (symAddr >= startMachO && symAddr < endMachO) - REBASE(patch->fSymbol, delta); - } - } - - // Finally rebase all of the string table pointers - last = file->fSymtab->nsyms; - for (i = 0; i < last; i++) - REBASE(file->fSymbToStringTable[i], delta); - -#undef REBASE - - return true; - -#endif /* KERNEL */ -} - -static Boolean -prepareFileForLink(struct fileRecord *file) -{ - unsigned long i, last, numnewsyms, newsymsize, newstrsize; - struct sectionRecord *section; - struct nlist **symp, *sym; - DataRef newStrings, *stringBlocks; - - // If we didn't even do a pseudo 'relocate' and dirty the image - // then we can just return now. - if (!file->fImageDirty) - return true; - -DEBUG_LOG(("Linking 2 %s\n", file->fPath)); // @@@ gvdl: - - // We have to go over all of the relocs to repair the damage - // that we have done to the image when we did our 'relocation' - section = file->fSections; - for (i = 0, last = file->fNSects; i < last; i++, section++) { - unsigned char *sectionBase; - struct relocRecord *rec; - unsigned long j, nreloc; - - if (section->fRelocCache) { - sectionBase = file->fMachO + section->fSection->offset; - nreloc = section->fSection->nreloc; - rec = (struct relocRecord *) DataGetPtr(section->fRelocCache); - - // We will need to repair the reloc list - for (j = 0; j < nreloc; j++, rec++) { - void **entry; - struct nlist *sym; - - // Repair Damage to object image - entry = (void **) (sectionBase + rec->fRInfo->r_address); - *entry = rec->fValue; - - // Check if the symbol that this relocation entry points - // to is marked as erasable - sym = (struct nlist *) rec->fSymbol; - if (sym && sym->n_type == (N_EXT | N_UNDF) - && sym->n_sect == (unsigned char) -1) { - // It is in use so we better clear the mark - sym->n_un.n_strx = -sym->n_un.n_strx; - sym->n_sect = NO_SECT; - } - } - - // Clean up the fRelocCache we don't need it any more. - DataRelease(section->fRelocCache); - section->fRelocCache = 0; - } - } - file->fImageDirty = false; // Image is clean - - // If we didn't dirty the symbol table then just return - if (!file->fSymbolsDirty) - return true; - - // calculate total file size increase and check against padding - if (file->fNewSymbols) { - numnewsyms = DataGetLength(file->fNewSymbols); - symp = (struct nlist **) DataGetPtr(file->fNewSymbols); - } - else { - numnewsyms = 0; - symp = 0; - } - numnewsyms /= sizeof(struct nlist *); - file->fSymtab->nsyms += numnewsyms; - - // old sting size + 30% rounded up to nearest page - newstrsize = file->fSymtab->strsize * 21 / 16; - newstrsize = (newstrsize + PAGE_MASK) & ~PAGE_MASK; - newStrings = DataCreate(newstrsize); - return_if(!newStrings, false, - ("Unable to allocate a copy aside buffer, no memory\n")); - - newsymsize = numnewsyms * sizeof(struct nlist); - file->fStringBase += newsymsize; - file->fSymtab->stroff += newsymsize; - - last = file->fSymtab->nsyms - numnewsyms; - newstrsize = 0; - DataAppendBytes(newStrings, &newstrsize, 4); // Leading nuls - sym = file->fSymbolBase; - - // Pre-compute an already offset new symbol pointer. The offset is the - // orignal symbol table. - symp -= last; - for (i = 0; i < file->fSymtab->nsyms; i++, sym++) { - const char *str = symNameByIndex(file, i); - int len = strlen(str) + 1; - unsigned int strx; - - // Rebase sym in the new symbol region - if (i >= last) - sym = symp[i]; - - if (sym->n_un.n_strx < 0 && sym->n_type == (N_EXT | N_UNDF) - && (unsigned char) -1 == sym->n_sect) { - // after patching we find that this symbol is no longer in - // use. So invalidate it by converting it into an N_ABS - // symbol, remove the external bit and null out the name. - bzero(sym, sizeof(*sym)); - sym->n_type = N_ABS; - } - else { - // Repair the symbol for the getNewSymbol case. - if (-1 == sym->n_un.n_strx) - sym->n_value = 0; - - // Record the offset of the string in the new table - strx = DataGetLength(newStrings); - return_if(!DataAppendBytes(newStrings, str, len), false, - ("Unable to append string, no memory\n")); - - sym->n_un.n_strx = strx; - file->fSymbToStringTable[i] = file->fStringBase + strx; - } - } - - // Don't need the new strings any more - last = DataGetLength(file->fNewStringBlocks) / sizeof(DataRef); - stringBlocks = (DataRef *) DataGetPtr(file->fNewStringBlocks); - for (i = 0; i < last; i++) - DataRelease(stringBlocks[i]); - - DataRelease(file->fNewStringBlocks); - file->fNewStringBlocks = 0; - - newstrsize = DataGetLength(newStrings); - newstrsize = (newstrsize + 3) & ~3; // Round to nearest word - return_if( - !growImage(file, newsymsize + newstrsize - file->fSymtab->strsize), - false, ("Unable to patch the extension, no memory\n", file->fPath)); - - // Push out the new symbol table if necessary - if (numnewsyms) { - caddr_t base; - - // Append the new symbols to the original symbol table. - base = (caddr_t) file->fSymbolBase - + (file->fSymtab->nsyms - numnewsyms) * sizeof(struct nlist); - symp = (struct nlist **) DataGetPtr(file->fNewSymbols); - for (i = 0; i < numnewsyms; i++, base += sizeof(struct nlist), symp++) - bcopy(*symp, base, sizeof(struct nlist)); - - DataRelease(file->fNewSymbols); - file->fNewSymbols = 0; - } - - // Push out the new string table if necessary - if (newStrings) { - unsigned long *base = (unsigned long *) file->fStringBase; - unsigned long actuallen = DataGetLength(newStrings); - - // Set the last word in string table to zero before copying data - base[(newstrsize / sizeof(unsigned long)) - 1] = 0; - - // Now copy the new strings back to the end of the file - bcopy((caddr_t) DataGetPtr(newStrings), file->fStringBase, actuallen); - - file->fSymtab->strsize = newstrsize; - - DataRelease(newStrings); - } - - file->fSymbolsDirty = false; - - return true; -} - -Boolean -#if KERNEL -kld_file_map(const char *pathName, - unsigned char *map, - size_t mapSize, - Boolean isKmem) -#else -kld_file_map(const char *pathName) -#endif /* KERNEL */ -{ - struct fileRecord file, *fp = 0; - - // Already done no need to repeat - fp = getFile(pathName); - if (fp) - return true; - - bzero(&file, sizeof(file)); - -#if KERNEL - file.fMap = map; - file.fMapSize = mapSize; - file.fIsKmem = isKmem; -#else - if (!mapObjectFile(&file, pathName)) - return false; -#endif /* KERNEL */ - - do { - const struct machOMapping { - struct mach_header h; - struct load_command c[1]; - } *machO; - const struct load_command *cmd; - int i; - - if (!findBestArch(&file, pathName)) - break; - - machO = (const struct machOMapping *) file.fMachO; - if (file.fMachOSize < machO->h.sizeofcmds) - break; - - file.fIsKernel = (MH_EXECUTE == machO->h.filetype); - - // If the file type is MH_EXECUTE then this must be a kernel - // as all Kernel extensions must be of type MH_OBJECT - for (i = 0, cmd = &machO->c[0]; i < machO->h.ncmds; i++) { - if (cmd->cmd == LC_SYMTAB) - file.fSymtab = (struct symtab_command *) cmd; - else if (cmd->cmd == LC_SEGMENT) { - struct segment_command *seg = (struct segment_command *) cmd; - int nsects = seg->nsects; - - if (nsects) - return_if(!parseSegments(&file, seg), - false, ("%s isn't a valid mach-o, bad segment", - pathName)); - else if (file.fIsKernel) { -#if KERNEL - // We don't need to look for the LinkEdit segment unless - // we are running in the kernel environment. - if (!strcmp(kLinkEditSegName, seg->segname)) - file.fLinkEditSeg = seg; -#endif - } - } - - cmd = (struct load_command *) ((UInt8 *) cmd + cmd->cmdsize); - } - break_if(!file.fSymtab, - ("%s isn't a valid mach-o, no symbols\n", pathName)); - - if (!parseSymtab(&file, pathName)) - break; - - fp = addFile(&file, pathName); - if (!fp) - break; - - if (file.fFoundOSObject && !getMetaClassGraph(fp)) - break; - - if (file.fIsKernel) - sKernelFile = fp; - -#if KERNEL - // Automatically load the kernel's link edit segment if we are - // attempting to load a driver. - if (!sKernelFile) { - extern struct mach_header _mh_execute_header; - extern struct segment_command *getsegbyname(char *seg_name); - - struct segment_command *sg; - size_t kernelSize; - Boolean ret; - - sg = (struct segment_command *) getsegbyname(kLinkEditSegName); - break_if(!sg, ("Can't find kernel link edit segment\n")); - - kernelSize = sg->vmaddr + sg->vmsize - (size_t) &_mh_execute_header; - ret = kld_file_map(kld_basefile_name, - (unsigned char *) &_mh_execute_header, kernelSize, - /* isKmem */ false); - break_if(!ret, ("kld can't map kernel file")); - } -#endif /* KERNEL */ - - return true; - } while(0); - - // Failure path, then clean up - if (fp) - // @@@ gvdl: for the time being leak the file ref in the file table - removeFile(fp); - else - unmapFile(&file); - - return false; -} - -void *kld_file_getaddr(const char *pathName, long *size) -{ - struct fileRecord *file = getFile(pathName); - - if (!file) - return 0; - - if (size) - *size = file->fMachOSize; - - return file->fMachO; -} - -void *kld_file_lookupsymbol(const char *pathName, const char *symname) -{ - struct fileRecord *file = getFile(pathName); - const struct nlist *sym; - const struct section *section; - unsigned char *sectionBase; - unsigned char sectind; - - return_if(!file, - NULL, ("Unknown file %s\n", pathName)); - - sym = findSymbolByName(file, symname); - - // May be a non-extern symbol so look for it there - if (!sym) { - unsigned int i, nsyms; - - sym = file->fSymbolBase; - for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) { - if ( (sym->n_type & N_EXT) ) { - sym = 0; - break; // Terminate search when we hit an extern - } - if ( (sym->n_type & N_STAB) ) - continue; - if ( !strcmp(symname, symNameByIndex(file, i)) ) - break; - } - } - - return_if(!sym, - NULL, ("Unknown symbol %s in %s\n", symname, pathName)); - - // Is the vtable in a valid section? - sectind = sym->n_sect; - return_if(sectind == NO_SECT || sectind > file->fNSects, NULL, - ("Malformed object file, invalid section reference for %s in %s\n", - symname, pathName)); - - section = file->fSections[sectind - 1].fSection; - sectionBase = file->fMachO + section->offset - section->addr; - - return (void *) (sectionBase + sym->n_value); -} - -Boolean kld_file_merge_OSObjects(const char *pathName) -{ - struct fileRecord *file = getFile(pathName); - - return_if(!file, - false, ("Internal error - unable to find file %s\n", pathName)); - - return mergeOSObjectsForFile(file); -} - -Boolean kld_file_patch_OSObjects(const char *pathName) -{ - struct fileRecord *file = getFile(pathName); - struct metaClassRecord **classes; - unsigned long i, last; - - return_if(!file, - false, ("Internal error - unable to find file %s\n", pathName)); - - DEBUG_LOG(("Patch file %s\n", pathName)); // @@@ gvdl: - - // If we don't have any classes we can return now. - if (!file->fClassList) - return true; - - // If we haven't alread merged the kernel then do it now - if (!sMergedKernel && sKernelFile) - mergeOSObjectsForFile(sKernelFile); - return_if(!sMergedKernel, false, ("Internal error no kernel?\n")); - - if (!mergeOSObjectsForFile(file)) - return false; - - // Patch all of the classes in this executable - last = DataGetLength(file->fClassList) / sizeof(void *); - classes = (struct metaClassRecord **) DataGetPtr(file->fClassList); - for (i = 0; i < last; i++) { - if (!patchVTable(classes[i])) - return false; - } - - return true; -} - -Boolean kld_file_prepare_for_link() -{ - if (sMergedFiles) { - unsigned long i, nmerged = 0; - struct fileRecord **files; - - // Check to see if we have already merged this file - nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *); - files = (struct fileRecord **) DataGetPtr(sMergedFiles); - for (i = 0; i < nmerged; i++) { - if (!prepareFileForLink(files[i])) - return false; - } - } - - // Clear down the meta class table and merged file lists - DataRelease(sMergeMetaClasses); - DataRelease(sMergedFiles); - sMergedFiles = sMergeMetaClasses = NULL; - sMergedKernel = false; - - return true; -} - -void kld_file_cleanup_all_resources() -{ - unsigned long i, nfiles; - -#if KERNEL // @@@ gvdl: - // Debugger("kld_file_cleanup_all_resources"); -#endif - - if (!sFilesTable || !(nfiles = DataGetLength(sFilesTable))) - return; // Nothing to do just return now - - nfiles /= sizeof(struct fileRecord *); - for (i = 0; i < nfiles; i++) - removeFile(((void **) DataGetPtr(sFilesTable))[i]); - - DataRelease(sFilesTable); - sFilesTable = NULL; - - // Don't really have to clean up anything more as the whole - // malloc engine is going to be released and I couldn't be bothered. -} - - -#if !KERNEL -#if 0 -static const struct fileRecord *sortFile; -static int symCompare(const void *vSym1, const void *vSym2) -{ - const struct nlist *sym1 = vSym1; - const struct nlist *sym2 = vSym2; - - { - unsigned int ind1, ind2; - - ind1 = sym1->n_type & N_TYPE; - ind2 = sym2->n_type & N_TYPE; - if (ind1 != ind2) { - // if sym1 is undefined then sym1 must come later than sym2 - if (ind1 == N_UNDF) - return 1; - // if sym2 is undefined then sym1 must come earlier than sym2 - if (ind2 == N_UNDF) - return -1; - /* drop out if neither are undefined */ - } - } - - { - const struct fileRecord *file = sortFile; - const char *name1, *name2; - - name1 = file->fStringBase + sym1->n_un.n_strx; - name2 = file->fStringBase + sym2->n_un.n_strx; - return strcmp(name1, name2); - } -} -#endif /* 0 */ - -Boolean kld_file_debug_dump(const char *pathName, const char *outName) -{ - const struct fileRecord *file = getFile(pathName); - int fd; - Boolean ret = false; - - return_if(!file, false, ("Unknown file %s for dumping\n", pathName)); - - fd = open(outName, O_WRONLY|O_CREAT|O_TRUNC, 0666); - return_if(-1 == fd, false, ("Can't create output file %s - %s(%d)\n", - outName, strerror(errno), errno)); - - do { -#if 0 - // Sorting doesn't work until I fix the relocs too? - - // sort the symbol table appropriately - unsigned int nsyms = file->fSymtab->nsyms - - (file->fLocalSyms - file->fSymbolBase); - sortFile = file; - heapsort((void *) file->fLocalSyms, nsyms, sizeof(struct nlist), - symCompare); -#endif - - break_if(-1 == write(fd, file->fMachO, file->fMachOSize), - ("Can't dump output file %s - %s(%d)\n", - outName, strerror(errno), errno)); - ret = true; - } while(0); - - close(fd); - - return ret; -} - -#endif /* !KERNEL */ - diff --git a/kmodload.tproj/kld_patch.h b/kmodload.tproj/kld_patch.h deleted file mode 100644 index b0e6058..0000000 --- a/kmodload.tproj/kld_patch.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* - * History: - * 2001-05-30 gvdl Initial implementation of the vtable patcher. - */ - -#include - -__BEGIN_DECLS - -#if KERNEL -extern Boolean kld_file_map(const char *pathName, - unsigned char *map, size_t mapSize, - Boolean isKmem); -#else -extern Boolean kld_file_map(const char *pathName); - -extern void * - kld_file_lookupsymbol(const char *pathName, const char *symbolname); - -Boolean kld_file_debug_dump(const char *pathName, const char *outName); -#endif /* KERNEL */ - -extern void *kld_file_getaddr(const char *pathName, long *size); - -extern Boolean kld_file_merge_OSObjects(const char *pathName); - -extern Boolean kld_file_patch_OSObjects(const char *pathName); - -extern Boolean kld_file_prepare_for_link(); - -extern void kld_file_cleanup_all_resources(); - -__END_DECLS diff --git a/kmodload.tproj/kmodload.8 b/kmodload.tproj/kmodload.8 deleted file mode 100644 index 2df8de3..0000000 --- a/kmodload.tproj/kmodload.8 +++ /dev/null @@ -1,103 +0,0 @@ -.\" -.\" Copyright (c) 1997 Doug Rabson -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id: kmodload.8,v 1.4 2002/01/30 22:44:21 lindak Exp $ -.\" -.Dd April 8, 1999 -.Dt KMODLOAD 8 -.Os FreeBSD -.Sh NAME -.Nm kmodload -.Nd loads and starts a kernel module -.Sh SYNOPSIS -.Nm kmodload -.Op Fl v -.Op Fl k Ar kernel_file -.Op Fl d Ar dependency_file -.Op Fl o Ar symbol_file -.Ar module_file -.Sh DESCRIPTION -.Nm kmodload -is deprecated; use -.Xr kextload 8 , -instead. -.Pp -The -.Nm kmodload -command loads the file -.Ar module_file -into the kernel and starts its execution. -.Pp -The following options are available: -.Bl -tag -width indent -.\" ========== -.It Fl d Ar dependency_file -Add symbols from -.Ar dependency_file -to kernel symbols, prior to linking of -.Ar module_file . -The file -.Ar dependency_file -must already be loaded. -.\" ========== -.It Fl k Ar kernel_file -Use an alternate file -.Ar kernel_file , -instead of the default file (/mach), for linking -.Ar module_file . -.\" ========== -.It Fl o Ar symbol_file -Create a file named -.Ar symbol_file -that contains statically-linked output suitable -for remote debugging use with -.Xr gdb 1 . -.\" ========== -.It Fl v -Be more verbose. -.El -.Sh FILES -.Bl -tag -width /modules -compact -.It Pa /System/Library/Extensions -directory containing loadable kernel modules. -.Sh DIAGNOSTICS -The -.Nm kmodload -utility exits with a status of 0 on success. -A status of 1 indicates a usage error. -A status of 2 indicates a indicates a permissions error. -A status of 3 indicates a problem with linking the module. -A status of 4 indicates a internal or system error. -A status of 5 indicates the module has already been loaded. -.Sh SEE ALSO -.Xr gdb 1 , -.Xr kmodstat 8 , -.Xr kmodsyms 8 , -.Xr kmodunload 8 -.Sh HISTORY -The -.Nm kmodload -command is based on the command kldload written by -.An Doug Rabson Aq dfr@FreeBSD.org diff --git a/kmodload.tproj/kmodload.c b/kmodload.tproj/kmodload.c deleted file mode 100644 index 7d817b6..0000000 --- a/kmodload.tproj/kmodload.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * Copyright (c) 1997 Doug Rabson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Original code from: - * "kldload.c,v 1.5 1998/07/06 06:58:32 charnier Exp" - */ -#ifndef lint -static const char rcsid[] = - "$Id: kmodload.c,v 1.14 2002/04/15 20:28:30 lindak Exp $"; -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include "kld_patch.h" -#include "vers_rsrc.h" - -#define KMOD_ERROR_USAGE 1 -#define KMOD_ERROR_PERMS 2 -#define KMOD_ERROR_LOADING 3 -#define KMOD_ERROR_INTERNAL 4 -#define KMOD_ERROR_ALREADY 5 - -#define kKMOD_INFO_SYMBOLNAME "_kmod_info" -#define kKmodsymsName "kmodsyms" - -static mach_port_t kernel_port; -static mach_port_t kernel_priv_port; - -static kmod_info_t *module_dependencies = 0; -static vm_address_t kernel_alloc_address = 0; -static unsigned long kernel_alloc_size = 0; -static vm_address_t kernel_load_address = 0; -static unsigned long kernel_load_size = 0; -static unsigned long kernel_hdr_size = 0; -static unsigned long kernel_hdr_pad = 0; -static unsigned long faked_kernel_load_address = 0; - -static kmod_info_t *loaded_modules = 0; -static int loaded_count = 0; - -static char *progname = "program name?"; -static int kmodsyms = 0; -static int link_addrs_set = 0; -static int verbose = 0; - -static char *debugdumpfile = NULL; - -// must not be static; kld library calls -extern void kld_error_vprintf(const char *format, va_list ap); -static void e_printf(const char *fmt, ...); -static void v_printf(const char *fmt, ...); - -static void machwarn(int error, const char *message); -static void macherr(int error, const char *message); - -static unsigned long linkedit_address(unsigned long size, - unsigned long headers_size); -static void abort_load(int exitcode, const char *fmt, ...); -static void map_and_patch(const char *base, - const char **library_paths, - const char *module); -static void link_base(const char *base, - const char **dependency_paths, - const vm_address_t *dependency_addrs); -static void clear_globals(void); -static kmod_info_t *map_module(const char *filename); -static struct mach_header *link_module(const char *filename, - const char *output); -static vm_address_t update_kmod_info(struct mach_header *mach_header); -static kmod_t load_module(struct mach_header *mach_header, - vm_address_t info); -static void set_module_dependencies(kmod_t id); -static void start_module(kmod_t id); - -static void -usage(void) -{ - if (kmodsyms) { - fprintf(stderr, "usage: %s [-v] [-k kernelfile] [-d dependencyfile] -o symbolfile modulefile\n", progname); - fprintf(stderr, " %s [-v] -k kernelfile [-d dependencyfile@address] -o symbolfile modulefile@address\n", - progname); - } else { - fprintf(stderr, "usage: %s [-v] [-k kernelfile] [-d dependencyfile] [-o symbolfile] modulefile\n", progname); - } - fflush(stderr); - exit(KMOD_ERROR_USAGE); -} - -int -main(int argc, char** argv) -{ - int c, r, i; - char * kernel = _PATH_UNIX; - int kernel_set = 0; - char * gdbfile = 0; -#define MAX_DEPENDANCIES 128 - char * dependencies[MAX_DEPENDANCIES]; - vm_address_t loaded_addresses[MAX_DEPENDANCIES]; - int dependency_count = 0; - struct mach_header *rld_header; - - char * module_path = ""; - vm_address_t module_info = 0; - vm_address_t module_faked_address = 0; - kmod_t module_id = 0; - kmod_info_t *file_kinfo; - - if ((progname = strrchr(argv[0], '/')) == NULL) - progname = argv[0]; - else - ++progname; - - kmodsyms = !strcmp(progname, kKmodsymsName); - - fprintf(stderr, "%s is deprecated; use kextload(8) instead\n", progname); - sleep(5); - - // XXX things to add: - // -p data string to send as outofband data on start - // -P data file to send as outofband data on start - - while ((c = getopt(argc, argv, "D:d:o:k:v")) != -1) - switch (c) { - case 'd': - dependencies[dependency_count] = optarg; - if (kmodsyms) { - char *address; - if ((address = strrchr(optarg, '@'))) { - *address++ = 0; - loaded_addresses[dependency_count] = strtoul(address, NULL, 0); - link_addrs_set++; - } else { - loaded_addresses[dependency_count] = 0; - } - } - if (++dependency_count == MAX_DEPENDANCIES) { - abort_load(KMOD_ERROR_INTERNAL, - "internal error, dependency count overflow."); - } - break; - case 'o': - gdbfile = optarg; - break; - case 'k': - kernel_set++; - kernel = optarg; - break; - case 'v': - verbose = 1; - break; - case 'D': - debugdumpfile = optarg; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - dependencies[dependency_count] = 0; - loaded_addresses[dependency_count] = 0; - - if (argc != 1) usage(); - - module_path = argv[0]; - - if (kmodsyms) { - char *address; - - if (!gdbfile) usage(); - - // check for @address - if ((address = strrchr(module_path, '@'))) { - *address++ = 0; - module_faked_address = strtoul(address, NULL, 0); - link_addrs_set++; - } else { - module_faked_address = 0; - } - - // if any arg uses @address then they all must be and the kernel must be set - if (link_addrs_set) { - if (!kernel_set) usage(); - if (!module_faked_address) usage(); - for (i=0; i < dependency_count; i++) { - if (!loaded_addresses[i]) usage(); - } - } - } - - // map the module if possible, map_module will fail if there is a problem - file_kinfo = map_module(module_path); - - if (!link_addrs_set) { - kmod_info_t *k; - - // we only need the kernel port if we need to lookup loaded kmods - r = task_for_pid(mach_task_self(), 0, &kernel_port); - machwarn(r, "unable to get kernel task port"); - if (KERN_SUCCESS != r) { - abort_load(KMOD_ERROR_PERMS, - "You must be running as root to load modules in the kernel."); - } - - //get loaded modules - r = kmod_get_info(kernel_port, (void *)&loaded_modules, &loaded_count); // never freed - macherr(r, "kmod_get_info() failed"); - - // check to see if the module has been loaded - k = loaded_modules; - while (k) { - if (!strcmp(k->name, file_kinfo->name)) { - if (!kmodsyms) { - abort_load(KMOD_ERROR_ALREADY, - "the module named '%s' is already loaded.", k->name); - } else { - module_faked_address = k->address; - } - break; - } - k = (k->next) ? (k + 1) : 0; - } - - if (kmodsyms && !module_faked_address) { - abort_load(KMOD_ERROR_USAGE, - "the module named '%s' has not been loaded.", file_kinfo->name); - } - - //XXX it would be nice to be able to verify this is the correct kernel - //XXX by comparing the kernel version strings (once we have them) - } - - map_and_patch(kernel, dependencies, module_path); - - // Tell the kld linker where to get its load address from - kld_address_func(linkedit_address); - - // link the kernel along with any dependencies - link_base(kernel, dependencies, loaded_addresses); - - if (kmodsyms) { - faked_kernel_load_address = module_faked_address; - - if (!faked_kernel_load_address) { - abort_load(KMOD_ERROR_INTERNAL, - "internal error, fell thru without setting module load address."); - } - } - - rld_header = link_module(module_path, gdbfile); - module_info = update_kmod_info(rld_header); - - if (debugdumpfile) - kld_file_debug_dump(module_path, debugdumpfile); - - if (kmodsyms) return 0; - - // we need the priv port to load modules into the kernel - kernel_priv_port = mach_host_self(); /* if we are privileged */ - - module_id = load_module(rld_header, module_info); - set_module_dependencies(module_id); - start_module(module_id); - - return 0; -} - -static void -machwarn(int error, const char *message) -{ - if (KERN_SUCCESS != error) - e_printf("%s: %s", message, mach_error_string(error)); -} - -static void -macherr(int error, const char *message) -{ - if (KERN_SUCCESS != error) - abort_load(KMOD_ERROR_INTERNAL, - "%s: %s", message, mach_error_string(error)); -} - -static kmod_info_t *map_module(const char *filename) -{ - kmod_info_t *file_kinfo; - - if (!kld_file_map(filename)) - exit(KMOD_ERROR_LOADING); - - file_kinfo = kld_file_lookupsymbol(filename, kKMOD_INFO_SYMBOLNAME); - if (!file_kinfo) { - abort_load(KMOD_ERROR_USAGE, - "%s is not a valid kernel module.", filename); - } - - return file_kinfo; -} - -static void -map_and_patch(const char *base, const char **library_paths, const char *module) -{ - if (!kld_file_map(base)) - exit(KMOD_ERROR_INTERNAL); - if (!kld_file_merge_OSObjects(base)) - abort_load(KMOD_ERROR_LOADING, NULL); - - if (*library_paths) { - char **library; - for (library = library_paths; *library; library++) { - map_module(*library); - if (!kld_file_patch_OSObjects(*library)) - abort_load(KMOD_ERROR_LOADING, NULL); - } - } - - // Patch the vtables of the object module we are about to load - // The module has already been mapped in the main() routine as part - // of validation - if (!kld_file_patch_OSObjects(module)) - abort_load(KMOD_ERROR_LOADING, NULL); - - // During the patch up process the mapped images were modified - // to avoid having to allocate more data than necessary. - // Now we have to give the patcher a chance to clean up after itself. - if (!kld_file_prepare_for_link()) - abort_load(KMOD_ERROR_LOADING, NULL); -} - -static void -link_base(const char *base, - const char **dependency_paths, - const vm_address_t *dependency_addrs) -{ - struct mach_header *rld_header; - char *base_addr; - long base_size; - int ok; - - // Get the address and size of the base, usually the kernel - base_addr = kld_file_getaddr(base, &base_size); - if (!base_addr) - exit(KMOD_ERROR_INTERNAL); // Error reported by kld library. - - ok = kld_load_basefile_from_memory(base, base_addr, base_size); - fflush(stdout); - if (!ok) - abort_load(KMOD_ERROR_LOADING, "kld_load_basefile(%s) failed.", base); - - if (*dependency_paths) { - char **dependency = dependency_paths; - const vm_address_t *load_addr = dependency_addrs; - - while (*dependency) { - kmod_info_t *file_kinfo; - - // Find the kmod_info structure in the image. - file_kinfo = - kld_file_lookupsymbol(*dependency, kKMOD_INFO_SYMBOLNAME); - if (!file_kinfo) { - abort_load(KMOD_ERROR_USAGE, - "%s is not a valid kernel module.", *dependency); - } - - // find the address that this dependency is loaded at - if (kmodsyms && *load_addr) { - faked_kernel_load_address = *load_addr; - } else { - kmod_info_t *k; - kmod_info_t *tmp; - int found_it = 0; - - // match up file version of kmod_info with kernel version - k = loaded_modules; - while (k) { - if (!strcmp(k->name, file_kinfo->name)) { - UInt32 kernel_kmod_version; - UInt32 file_kmod_version; - - if (!VERS_parse_string(k->version, &kernel_kmod_version)) { - e_printf("can't parse version string \"%s\" in kernel kmod", - k->version); - abort_load(KMOD_ERROR_LOADING, - "can't parse kernel kmod version string \"%s\"", k->version); - } - - if (!VERS_parse_string(file_kinfo->version, & file_kmod_version)) { - e_printf("can't parse version string \"%s\" in kmod file %s", - file_kinfo->version, *dependency); - abort_load(KMOD_ERROR_LOADING, - "can't parse version string \"%s\" in kmod file %s", - file_kinfo->version, *dependency); - } - - if (kernel_kmod_version != file_kmod_version) { - e_printf("loaded kernel module '%s' version differs.", *dependency); - abort_load(KMOD_ERROR_LOADING, - "loaded version '%s', file version '%s'.", - k->version, file_kinfo->version); - } - found_it++; - break; - } - k = (k->next) ? (k + 1) : 0; - } - if (!found_it) { - abort_load(KMOD_ERROR_USAGE, - "kernel module '%s' is not loaded.", *dependency); - } - - tmp = malloc(sizeof(kmod_info_t)); - if (!tmp) - abort_load(KMOD_ERROR_LOADING, "no memory."); - - *tmp = *k; - tmp->next = module_dependencies; - module_dependencies = tmp; - - faked_kernel_load_address = k->address; - } - - rld_header = link_module(*dependency, 0); - - (void) update_kmod_info(rld_header); - - dependency++; load_addr++; - } - /* make sure we clear these so clean up does the right thing. */ - clear_globals(); - } -} - -#if !defined(page_round) -#define page_trunc(p) ((int)(p)&~(vm_page_size-1)) -#define page_round(p) page_trunc((int)(p)+vm_page_size-1) -#endif - -static unsigned long -linkedit_address(unsigned long size, unsigned long headers_size) -{ - int r; - unsigned long round_segments_size; - unsigned long round_headers_size; - unsigned long round_size; - - kernel_load_size = size; // The actual size allocated by kld_load... - - round_headers_size = page_round(headers_size); - round_segments_size = page_round(size - headers_size); - round_size = round_headers_size + round_segments_size; - - kernel_alloc_size = round_size; - kernel_hdr_size = headers_size; // will need to be rounded to page *after* link. - kernel_hdr_pad = round_headers_size - headers_size; - - if (faked_kernel_load_address) { - kernel_load_address = faked_kernel_load_address + kernel_hdr_pad; - v_printf("Returning fake load address of 0x%8x", kernel_load_address); - return kernel_load_address; - } - if (kmodsyms) { - abort_load(KMOD_ERROR_INTERNAL, - "internal error, almost tried to alloc kernel memory."); - } - - r = vm_allocate(kernel_port, &kernel_alloc_address, - kernel_alloc_size, TRUE); - macherr(r, "unable to allocate kernel memory"); - - v_printf("allocated %ld bytes in kernel space at 0x%8x", - kernel_alloc_size, kernel_alloc_address); - - kernel_load_address = kernel_alloc_address + kernel_hdr_pad; - - v_printf("Returning load address of 0x%x", kernel_load_address); - - return kernel_load_address; -} - -static void -clear_globals(void) -{ - faked_kernel_load_address = 0; - kernel_alloc_address = 0; - kernel_alloc_size = 0; - kernel_load_address = 0; - kernel_load_size = 0; - kernel_hdr_size = 0; - kernel_hdr_pad = 0; - return; -} - -static struct mach_header * -link_module(const char *filename, const char *output) -{ - struct mach_header *rld_header; - char *object_addr; - long object_size; - int ok; - - // Get the address of the thined MachO image. - object_addr = kld_file_getaddr(filename, &object_size); - if (!object_addr) - abort_load(KMOD_ERROR_LOADING, NULL); - - ok = kld_load_from_memory(&rld_header, filename, - object_addr, object_size, output); - fflush(stdout); - if (!ok) - abort_load(KMOD_ERROR_LOADING, "kld_load() failed."); - - return rld_header; -} - -// Update the kmod_info_t structure in the image to be laoded -// Side effect of removing the kKMOD_INFO_SYMBOLNAME from the -// loaded symbol name space, otherwise we would have a duplicate -// defined symbol failure -vm_address_t -update_kmod_info(struct mach_header *mach_header) -{ - char * symbol = kKMOD_INFO_SYMBOLNAME; - kmod_info_t *info; - unsigned long value; - int ok; - - ok = kld_lookup(symbol, &value); fflush(stdout); - if (!ok) - abort_load(KMOD_ERROR_LOADING, "kld_lookup(%s) failed.", symbol); - - ok = kld_forget_symbol(symbol); fflush(stdout); - if (!ok) - abort_load(KMOD_ERROR_LOADING, "kld_forget_symbol(%s) failed.", symbol); - - /* Get the kmod info by translating from the kernel address at value. - */ - info = (kmod_info_t *)(value - (unsigned long)kernel_load_address + (unsigned long)mach_header); - v_printf("kmod name: %s", info->name); - v_printf("kmod start @ 0x%x", (vm_address_t)info->start); - v_printf("kmod stop @ 0x%x", (vm_address_t)info->stop); - - /* Record link info in kmod info struct, rounding the hdr_size to fit - * the adjustment that was made. - */ - info->address = kernel_alloc_address; - info->size = kernel_alloc_size; - info->hdr_size = page_round(kernel_hdr_size); - - if (!info->start) - abort_load(KMOD_ERROR_LOADING, "invalid start address?"); - else if (!info->stop) - abort_load(KMOD_ERROR_LOADING, "invalid stop address?"); - - return (vm_address_t)value; -} - -static kmod_t -load_module(struct mach_header *mach_header, vm_address_t info) -{ - int r; - kmod_t id; - vm_address_t vm_buffer = 0; - - r = vm_allocate(mach_task_self(), &vm_buffer, - kernel_alloc_size, TRUE); - macherr(r, "unable to vm_allocate() copy buffer"); - - /* Copy the linked segment data into the page-aligned buffer. - * Do not round the header size here. - */ - bzero((void *)vm_buffer, kernel_alloc_size); - memcpy((void *)vm_buffer, mach_header, kernel_hdr_size); - memcpy((void *)vm_buffer + page_round(kernel_hdr_size), - (void *)((unsigned long)mach_header + kernel_hdr_size), - kernel_load_size - kernel_hdr_size); - - // copy linked header into kernel address space - r = vm_write(kernel_port, kernel_alloc_address, - vm_buffer, kernel_alloc_size); - macherr(r, "unable to write module into kernel memory"); - - // let the kernel know about it - r = kmod_create(kernel_priv_port, info, &id); - macherr(r, "unable to register module with kernel"); - - v_printf("kmod id %d successfully created at 0x%x size %ld.\n", - id, kernel_alloc_address, kernel_alloc_size); - - // FIXME: make sure this happens even on failure - - vm_deallocate(mach_task_self(), vm_buffer, kernel_alloc_size); - return id; -} - -static void -set_module_dependencies(kmod_t id) -{ - int r; - void * args = 0; - int argsCount= 0; - kmod_info_t *module = module_dependencies; - - while (module) { - - r = kmod_control(kernel_priv_port, KMOD_PACK_IDS(id, module->id), KMOD_CNTL_RETAIN, &args, &argsCount); - machwarn(r, "kmod_control(retain) failed"); - if (r) { - clear_globals(); - r = kmod_destroy(kernel_priv_port, id); - macherr(r, "kmod_destroy failed"); - } - - v_printf("kmod id %d reference count was sucessfully incremented.", module->id); - - module = module->next; - } -} - -static void -start_module(kmod_t id) -{ - int r; - void * args = 0; - int argsCount= 0; - - r = kmod_control(kernel_priv_port, id, KMOD_CNTL_START, &args, &argsCount); - machwarn(r, "kmod_control(start) failed"); - if (r) { - clear_globals(); - kmod_destroy(kernel_priv_port, id); - macherr(r, "kmod_destroy failed"); - } - - v_printf("kmod id %d successfully started.", id); -} - -static void e_printf(const char *fmt, ...) -{ - va_list ap; - char msg[1024]; - - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - - fprintf(stderr, "%s: %s\n", progname, msg); -} - -static void v_printf(const char *fmt, ...) -{ - va_list ap; - char msg[1024]; - - if (!verbose) return; - - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - - printf("%s: %s\n", progname, msg); -} - -static void abort_load(int exitcode, const char *fmt, ...) -{ - if (fmt) { - va_list ap; - char msg[1024]; - - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - - fprintf(stderr, "%s: %s\n", progname, msg); - } - - if (!faked_kernel_load_address - && (kernel_alloc_address || kernel_alloc_size)) { - int r; - - v_printf("freeing %ld bytes in kernel space at 0x%x", - kernel_alloc_size, kernel_alloc_address); - r = vm_deallocate(kernel_port, kernel_alloc_address, kernel_alloc_size); - machwarn(r, "unable to cleanup kernel memory"); - } - - exit(exitcode); -} - -__private_extern__ void -kld_error_vprintf(const char *fmt, va_list ap) -{ - vfprintf(stderr, fmt, ap); - fflush(stderr); -} diff --git a/kmodload.tproj/kmodsyms.8 b/kmodload.tproj/kmodsyms.8 deleted file mode 100644 index 5de1320..0000000 --- a/kmodload.tproj/kmodsyms.8 +++ /dev/null @@ -1,119 +0,0 @@ -.\" -.\" Copyright (c) 1997 Doug Rabson -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id: kmodsyms.8,v 1.3 2002/04/15 20:28:31 lindak Exp $ -.\" -.Dd April 8, 1999 -.Dt KMODSYMS 8 -.Os FreeBSD -.Sh NAME -.Nm kmodsyms -.Nd creates a statically-linked symbol file for remote debugging -.Sh SYNOPSIS -.Nm kmodsyms -.Op Fl v -.Op Fl k Ar kernel_file -.Op Fl d Ar dependency_file -.Fl o Ar symbol_file -.Ar module_file -.Nm kmodsyms -.Op Fl v -.Fl k Ar kernel_file -.Op Fl d Ar dependency_file@address -.Fl o Ar symbol_file -.Ar module_file@address -.Sh DESCRIPTION -.Nm kmodsyms -is deprecated; use -.Xr kextload 8 , -instead. -.Pp -The -.Nm kmodsyms -creates a statically-linked symbol file for remote debugging using -.Ar module_file[@address] . -If an address is specified for either the -.Ar module_file -or -.Ar dependency_file -they both must have the address tag. -If addresses are specified, -it is assumed that the command is being run on a different machine -with a potentially different kernel. -Thus, the -.Ar kernel_file -argument is also required. -If addresses are not specified, -they taken from the currently running host machine. -.Pp -The following options are available: -.Bl -tag -width indent -.\" ========== -.It Fl d Ar dependency_file[@address] -Add symbols from -.Ar dependency_file -to kernel symbols prior to linking of -.Ar module_file . -The file -.Ar dependency_file -must already be loaded. -.\" ========== -.It Fl k Ar kernel_file -Use an alternate file -.Ar kernel_file , -instead of the default file (/mach) for linking -.Ar module_file . -.\" ========== -.It Fl o Ar symbol_file -Creates file named -.Ar symbol_file -that contains statically linked output suitable -for remote debugging use with -.Xr gdb 1 . -.\" ========== -.It Fl v -Be more verbose. -.El -.Sh FILES -.Bl -tag -width /modules -compact -.It Pa /System/Library/Extensions -directory containing loadable kernel modules. -.Sh DIAGNOSTICS -The -.Nm kmodsyms -utility exits with a status of 0 on success. -A status of 1 indicates a usage error. -A status of 2 indicates a indicates a permissions error. -A status of 3 indicates a problem with linking the module. -A status of 4 indicates a internal or system error. -.Sh SEE ALSO -.Xr kmodload 8 , -.Xr kmodstat 8 , -.Xr kmodunload 8 -.Sh HISTORY -The -.Nm kmodsyms -command is based on the command kldload, written by -.An Doug Rabson Aq dfr@FreeBSD.org diff --git a/kmodload.tproj/vers_rsrc.c b/kmodload.tproj/vers_rsrc.c deleted file mode 100644 index c10f288..0000000 --- a/kmodload.tproj/vers_rsrc.c +++ /dev/null @@ -1,425 +0,0 @@ -#include "vers_rsrc.h" - -int vers_isdigit(char c) { - return (c == '0' || - c == '1' || c == '2' || c == '3' || - c == '4' || c == '5' || c == '6' || - c == '7' || c == '8' || c == '9'); -} - -int vers_isspace(char c) { - return (c == ' ' || - c == '\t' || - c == '\r' || - c == '\n'); -} - - -int isreleasestate(char c) { - return (c == 'd' || c == 'a' || c == 'b' || c == 'f'); -} - - -UInt8 BCD_digit_for_char(char c) { - switch (c) { - case '0': return 0; break; - case '1': return 1; break; - case '2': return 2; break; - case '3': return 3; break; - case '4': return 4; break; - case '5': return 5; break; - case '6': return 6; break; - case '7': return 7; break; - case '8': return 8; break; - case '9': return 9; break; - default: return BCD_illegal; break; - } - return BCD_illegal; -} - - -char BCD_char_for_digit(UInt8 digit) { - switch (digit) { - case 0: return '0'; break; - case 1: return '1'; break; - case 2: return '2'; break; - case 3: return '3'; break; - case 4: return '4'; break; - case 5: return '5'; break; - case 6: return '6'; break; - case 7: return '7'; break; - case 8: return '8'; break; - case 9: return '9'; break; - default: return '?'; break; - } - return '?'; -} - - -VERS_revision VERS_revision_for_string(char ** string_p) { - char * string; - - if (!string_p || !*string_p) { - return VERS_invalid; - } - - string = *string_p; - - if (vers_isspace(string[0]) || string[0] == '\0') { - return VERS_release; - } else { - switch (string[0]) { - case 'd': - if (vers_isdigit(string[1])) { - *string_p = &string[1]; - return VERS_development; - } - break; - case 'a': - if (vers_isdigit(string[1])) { - *string_p = &string[1]; - return VERS_alpha; - } - break; - case 'b': - if (vers_isdigit(string[1])) { - *string_p = &string[1]; - return VERS_beta; - } - break; - case 'f': - if (vers_isdigit(string[1])) { - *string_p = &string[1]; - return VERS_candidate; - } else if (string[1] == 'c' && vers_isdigit(string[2])) { - *string_p = &string[2]; - return VERS_candidate; - } else { - return VERS_invalid; - } - break; - default: - return VERS_invalid; - break; - } - } - - return VERS_invalid; -} - - -int VERS_parse_string(char * vers_string, UInt32 * version_num) { - int result = 1; - VERS_version vers; - char * current_char_p; - UInt8 scratch; - - if (!vers_string || *vers_string == '\0') { - return 0; - } - - vers.vnum = 0; - - current_char_p = &vers_string[0]; - - - /***** - * Check for an initial digit of the major release number. - */ - vers.bytes[0] = BCD_digit_for_char(*current_char_p); - if (vers.bytes[0] == BCD_illegal) { - return 0; - } - - current_char_p++; - - - /***** - * Check for a second digit of the major release number. - */ - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (vers_isdigit(*current_char_p)) { - scratch = BCD_digit_for_char(*current_char_p); - if (scratch == BCD_illegal) { - return 0; - } - vers.bytes[0] = BCD_combine(vers.bytes[0], scratch); - current_char_p++; - - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (isreleasestate(*current_char_p)) { - goto release_state; - } else if (*current_char_p == '.') { - current_char_p++; - } else { - return 0; - } - } else if (isreleasestate(*current_char_p)) { - goto release_state; - } else if (*current_char_p == '.') { - current_char_p++; - } else { - return 0; - } - - - /***** - * Check for the minor release number. - */ - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (vers_isdigit(*current_char_p)) { - vers.bytes[1] = BCD_digit_for_char(*current_char_p); - if (vers.bytes[1] == BCD_illegal) { - return 0; - } - - // Make sure its the first nibble of byte 1! - vers.bytes[1] = BCD_combine(vers.bytes[1], 0); - - current_char_p++; - - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (isreleasestate(*current_char_p)) { - goto release_state; - } else if (*current_char_p == '.') { - current_char_p++; - } else { - return 0; - } - } else { - return 0; - } - - - /***** - * Check for the bugfix number. - */ - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (vers_isdigit(*current_char_p)) { - scratch = BCD_digit_for_char(*current_char_p); - if (scratch == BCD_illegal) { - return 0; - } - - /* vers.bytes[1] has its left nibble set already */ - vers.bytes[1] = vers.bytes[1] | scratch; - - current_char_p++; - - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else if (isreleasestate(*current_char_p)) { - goto release_state; - } else { - return 0; - } - } else { - return 0; - } - - -release_state: - - /***** - * Check for the release state. - */ - if (*current_char_p == '\0') { - vers.bytes[2] = VERS_release; - vers.bytes[3] = 0xff; - goto finish; - } else { - vers.bytes[2] = VERS_revision_for_string(¤t_char_p); - if (vers.bytes[2] == VERS_invalid) { - return 0; - } - } - - - /***** - * Get the nonrelease revision number (0..255). - */ - if (vers.bytes[2] != VERS_release) { - UInt32 revision_num = 0; - int i; - - if (*current_char_p == '\0' || !vers_isdigit(*current_char_p)) { - return 0; - } - for (i = 0; i < 3 && *current_char_p != '\0'; i++, current_char_p++) { - UInt8 scratch_digit; - scratch_digit = BCD_digit_for_char(*current_char_p); - if (scratch_digit == BCD_illegal) { - return 0; - } - revision_num *= 10; - revision_num += scratch_digit; - } - if (vers_isdigit(*current_char_p) || revision_num > 255) { - return 0; - } - vers.bytes[3] = (UInt8)revision_num; - } - - if (vers.bytes[2] == VERS_release) { - vers.bytes[3] = 0xff; - } else { - if (vers.bytes[2] == VERS_candidate) { - if (vers.bytes[3] == 0) { - return 0; - } else { - vers.bytes[2] = VERS_release; - vers.bytes[3]--; - } - } - } - -finish: - *version_num = CFSwapInt32BigToHost(vers.vnum); - return result; -} - - -#define VERS_STRING_MAX_LEN (12) - -int VERS_string(char * buffer, UInt32 length, UInt32 vers) { - VERS_version version; - int cpos = 0; - int result = 1; // assume success - - char major1; - char major2; - char minor; - char bugfix; - - version.vnum = CFSwapInt32HostToBig(vers); - - /* No buffer or length less than longest possible vers string, - * return 0. - */ - if (!buffer || length < VERS_STRING_MAX_LEN) { - result = 0; - goto finish; - } - - bzero(buffer, length * sizeof(char)); - - - /***** - * Major version number. - */ - major1 = BCD_char_for_digit(BCD_get_left(version.bytes[0])); - if (major1 == '?') { - result = 0; - } /* this is not an 'else' situation */ - if (major1 != '0') { - buffer[cpos] = major1; - cpos++; - } - - major2 = BCD_char_for_digit(BCD_get_right(version.bytes[0])); - if (major2 == '?') { - result = 0; - } - - buffer[cpos] = major2; - cpos++; - - - /***** - * Minor & bug-fix version numbers. - */ - minor = BCD_char_for_digit(BCD_get_left(version.bytes[1])); - if (minor == '?') { - result = 0; - } - bugfix = BCD_char_for_digit(BCD_get_right(version.bytes[1])); - if (bugfix == '?') { - result = 0; - } - - - /* Always display the minor version number. - */ - buffer[cpos] = '.'; - cpos++; - buffer[cpos] = minor; - cpos++; - - - /* Only display the bugfix version number if it's nonzero. - */ - if (bugfix != '0') { - buffer[cpos] = '.'; - cpos++; - buffer[cpos] = bugfix; - cpos++; - } - - - /* If the release state is final, we're done! - */ - if (version.bytes[2] == VERS_release && version.bytes[3] == 255) { - goto finish; - } - - - /***** - * Do the release state and update level. - */ - switch (version.bytes[2]) { - case VERS_development: - buffer[cpos] = 'd'; - cpos++; - break; - case VERS_alpha: - buffer[cpos] = 'a'; - cpos++; - break; - case VERS_beta: - buffer[cpos] = 'b'; - cpos++; - break; - case VERS_release: - if (version.bytes[3] < 255) { - buffer[cpos] = 'f'; - buffer[cpos+1] = 'c'; - cpos += 2; - } else { - goto finish; - } - break; - default: - result = 0; - buffer[cpos] = '?'; - cpos++; - break; - } - - if (version.bytes[2] != VERS_release) { - sprintf(&buffer[cpos], "%d", version.bytes[3]); - } else { - if (version.bytes[3] < 255) { - sprintf(&buffer[cpos], "%d", version.bytes[3] + 1); - } - } - -finish: - return result; -} diff --git a/kmodload.tproj/vers_rsrc.h b/kmodload.tproj/vers_rsrc.h deleted file mode 100644 index db8f94b..0000000 --- a/kmodload.tproj/vers_rsrc.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _LIBSA_VERS_H_ -#define _LIBSA_VERS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -typedef union { - UInt32 vnum; - UInt8 bytes[4]; -} VERS_version; - -typedef enum { - VERS_development = 0x20, - VERS_alpha = 0x40, - VERS_beta = 0x60, - VERS_candidate = 0x70, // for interim usage only! - VERS_release = 0x80, - VERS_invalid = 0xff -} VERS_revision; - -#define BCD_combine(l, r) ( (((l) & 0xf) << 4) | ((r) & 0xf) ) -#define BCD_get_left(p) ( ((p) >> 4) & 0xf ) -#define BCD_get_right(p) ( (p) & 0xf ) - -#define BCD_illegal (0xff) // full byte, 11111111 - -int VERS_parse_string(char * vers_string, UInt32 * version_num); -int VERS_string(char * buffer, UInt32 length, UInt32 vers); - -#ifdef __cplusplus -} -#endif - -#endif _LIBSA_VERS_H_ diff --git a/kmodstat.tproj/Makefile b/kmodstat.tproj/Makefile deleted file mode 100644 index 2c9f9ed..0000000 --- a/kmodstat.tproj/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Generated by the NeXT Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = kmodstat - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Tool - -CFILES = kmodstat.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodstat.8 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = tool.make -NEXTSTEP_INSTALLDIR = /usr/sbin -WINDOWS_INSTALLDIR = /Library/Executables -PDO_UNIX_INSTALLDIR = /bin -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/kmodstat.tproj/kmodstat.8 b/kmodstat.tproj/kmodstat.8 deleted file mode 100644 index b334b37..0000000 --- a/kmodstat.tproj/kmodstat.8 +++ /dev/null @@ -1,71 +0,0 @@ -.\" -.\" Copyright (c) 1997 Doug Rabson -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id: kmodstat.8,v 1.2 2002/04/18 18:48:42 lindak Exp $ -.\" -.Dd April 17, 2002 -.Dt KMODSTAT 8 -.Os FreeBSD -.Sh NAME -.Nm kmodstat -.Nd display status of dynamically-loaded kernel modules -.Sh SYNOPSIS -.Nm kmodstat -.Op Fl i Ar id -.Op Fl n Ar name -.Sh DESCRIPTION -.Nm kmodstat -is deprecated; use -.Xr kextstat 8 , -instead. -.Pp -The -.Nm kmodstat -utility displays the status of any kernel modules -that are dynamically linked into the kernel. -.Pp -The following options are available: -.Bl -tag -width indentXX -.\" ========== -.It Fl i Ar id -Display the status of only the kernel module with this ID. -.\" ========== -.It Fl n Ar name -Display the status of only the kernel module with this name. -.El -.Sh DIAGNOSTICS -The -.Nm kmodstat -utility exits with a status of 0 on success -and with a nonzero status if an error occurs. -.Sh SEE ALSO -.Xr kmodload 8 , -.Xr kmodsyms 8 , -.Xr kmodunload 8 -.Sh HISTORY -The -.Nm kmodstat -command is based on the command kldstat, written by -.An Doug Rabson Aq dfr@FreeBSD.org diff --git a/kmodstat.tproj/kmodstat.c b/kmodstat.tproj/kmodstat.c deleted file mode 100644 index d1a744d..0000000 --- a/kmodstat.tproj/kmodstat.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * Copyright (c) 1997 Doug Rabson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Original code from: - * "kldstat.c,v 1.5 1998/11/07 00:29:09 des Exp"; - */ - -#ifndef lint -static const char rcsid[] = - "$Id: kmodstat.c,v 1.4 2002/04/18 18:48:42 lindak Exp $"; -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static void -machwarn(int error, const char *message) -{ - if (error == KERN_SUCCESS) return; - fprintf(stderr, "kmodstat: %s: %s\n", message, mach_error_string(error)); -} - -static void -macherr(int error, const char *message) -{ - if (error == KERN_SUCCESS) return; - fprintf(stderr, "kmodstat: %s: %s\n", message, mach_error_string(error)); - exit(1); -} - -static int -kmod_compare(const void *a, const void *b) -{ - return (((kmod_info_t *)a)->id - ((kmod_info_t *)b)->id); -} - -static void -usage(void) -{ - fprintf(stderr, "usage: kmodstat [-i id] [-n name]\n"); - exit(1); -} - -int -main(int argc, char** argv) -{ - int c, idset = 0, id = 0; - char* name = 0; - kmod_info_t *info, *k; - kmod_reference_t *r; - int i, j, rc, foundit, count, rcount; - mach_port_t kernel_port; - - fprintf(stderr, "%s is deprecated; use kextstat(8) instead\n", argv[0]); - sleep(5); - - while ((c = getopt(argc, argv, "i:n:")) != -1) - switch (c) { - case 'i': - idset++; - id = atoi(optarg); - break; - case 'n': - name = optarg; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - if (!idset && !name && (argc == 1)) { - name = *argv; - argc--; - } - - if (argc != 0) usage(); - - rc = task_for_pid(mach_task_self(), 0, &kernel_port); - machwarn(rc, "unable to get kernel task port"); - if (rc) { - fprintf(stderr, "kmodstat: Are you running as root?\n"); - exit(1); - } - - rc= kmod_get_info(kernel_port, (void *)&info, &count); - macherr(rc, "kmod_get_info() failed"); - - k = info; count = 0; - while (k) { - count++; - k = (k->next) ? (k + 1) : 0; - } - - k = info; r = (kmod_reference_t *)(info + count); - while (k) { - if ((rcount = (int)k->reference_list)) { - k->reference_list = r; - for (i=0; i < rcount; i++) { - foundit = 0; - for (j=0; j < count; j++) { - if (r->info == info[j].next) { - r->info = (kmod_info_t *)info[j].id; - foundit++; - break; - } - } - // force the id in here, the sorting below messes up the pointers - if (!foundit) r->info = (kmod_info_t *)info[count - 1].id; - r->next = r + 1; - r++; - } - k->reference_list[rcount - 1].next = 0; - } - k = (k->next) ? (k + 1) : 0; - } - - printf("Id Refs Address Size Wired Name (Version) \n"); - - if (!count) return 0; - - qsort(info, count, sizeof(kmod_info_t), kmod_compare); - - if (idset || name) { - kmod_info_t *k = info; - int match_count = 0; - for (i=0; i < count; i++, k++) { - if ((idset && id == k->id) || (name && !strcmp(k->name, name))) { - info[match_count++] = *k; - } - } - count = match_count; - } - for (i=0; i < count; i++, info++) { - printf("%2d %4d %-10p %-10p %-10p %s (%s)", - info->id, info->reference_count, (void *)info->address, - (void *)info->size, (void *)(info->size - info->hdr_size), - info->name, info->version); - - if ((r = info->reference_list)) { - printf(" <%d", (int)r->info); - r = r->next; - while (r) { - printf(" %d", (int)r->info); - r = r->next; - } - printf(">"); - } - printf("\n"); - } - - return 0; -} diff --git a/kmodunload.tproj/Makefile b/kmodunload.tproj/Makefile deleted file mode 100644 index 1700393..0000000 --- a/kmodunload.tproj/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Generated by the NeXT Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = kmodunload - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Tool - -CFILES = kmodunload.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodunload.8 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = tool.make -NEXTSTEP_INSTALLDIR = /sbin -WINDOWS_INSTALLDIR = /Library/Executables -PDO_UNIX_INSTALLDIR = /bin -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/kmodunload.tproj/kmodunload.8 b/kmodunload.tproj/kmodunload.8 deleted file mode 100644 index 64a8494..0000000 --- a/kmodunload.tproj/kmodunload.8 +++ /dev/null @@ -1,77 +0,0 @@ -.\" -.\" Copyright (c) 1997 Doug Rabson -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id: kmodunload.8,v 1.2 2002/04/15 20:28:33 lindak Exp $ -.\" -.Dd April 8, 1999 -.Dt KMODUNLOAD 8 -.Os FreeBSD -.Sh NAME -.Nm kmodunload -.Nd stops and unloads a kernel module -.Sh SYNOPSIS -.Nm kmodunload -.Op Fl v -.Fl i Ar id -.Nm kmodunload -.Op Fl v -.Fl n Ar name -.Sh DESCRIPTION -.Nm kmodunload -is deprecated; use -.Xr kextunload 8 , -instead. -.Pp -The -.Nm kmodunload -utility stops and unloads a kernel module which was previously loaded with -.Xr kmodload 8 . -.Pp -The following options are available: -.Bl -tag -width indentXX -.\" ========== -.It Fl i Ar id -Unload the kernel module with this ID. -.\" ========== -.It Fl n Ar name -Unload the kernel module with this name. -.\" ========== -.It Fl v -Be more verbose. -.El -.Sh DIAGNOSTICS -The -.Nm kmodunload -utility exits with a status of 0 on success -and with a nonzero status if an error occurs. -.Sh SEE ALSO -.Xr kmodload 8 , -.Xr kmodstat 8 , -.Xr kmodsyms 8 -.Sh HISTORY -The -.Nm kmodunload -command is based on the command kldunload, written by -.An Doug Rabson Aq dfr@FreeBSD.org diff --git a/kmodunload.tproj/kmodunload.c b/kmodunload.tproj/kmodunload.c deleted file mode 100644 index fcff465..0000000 --- a/kmodunload.tproj/kmodunload.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * Copyright (c) 1997 Doug Rabson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Original code from: - * "kldunload.c,v 1.7 1998/11/07 00:42:52 des Exp" - */ - -#ifndef lint -static const char rcsid[] = - "$Id: kmodunload.c,v 1.5 2002/04/24 20:03:48 lindak Exp $"; -#endif /* not lint */ - -#include -#include -#include -#include - -#include -#include -#include - -static int verbose = 0; -#define v_printf if (verbose) printf - -static void -machwarn(int error, const char *message) -{ - if (error == KERN_SUCCESS) return; - fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error)); -} - -static void -macherr(int error, const char *message) -{ - if (error == KERN_SUCCESS) return; - fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error)); - exit(1); -} - -static mach_port_t kernel_priv_port; - -static void -stop_module(kmod_t id) -{ - int r; - void * args = 0; - int argsCount= 0; - - r = kmod_control(kernel_priv_port, id, KMOD_CNTL_STOP, &args, &argsCount); - macherr(r, "kmod_control(stop) failed"); - - v_printf("kmodunload: kmod id %d successfully stopped.\n", id); -} - -static void -unload_module(kmod_t id) -{ - int r; - - r = kmod_destroy(kernel_priv_port, id); - macherr(r, "kmod_destroy() failed"); - - v_printf("kmodunload: kmod id %d successfully unloaded.\n", id); -} - -static void -usage(void) -{ - fprintf(stderr, "usage: kmodunload [-v] -i id\n"); - fprintf(stderr, " kmodunload [-v] -n name\n"); - exit(1); -} - -int -main(int argc, char** argv) -{ - int c; - int id = 0; - char* name = 0; - kmod_info_t *info; - int r; - int count; - mach_port_t kernel_port; - - fprintf(stderr, "%s is deprecated; use kextunload(8) instead\n", argv[0]); - sleep(5); - - while ((c = getopt(argc, argv, "i:n:v")) != -1) - switch (c) { - case 'i': - id = atoi(optarg); - break; - case 'n': - name = optarg; - break; - case 'v': - verbose = 1; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - if (!id && !name && (argc == 1)) { - name = *argv; - argc--; - } - - if ((argc != 0) || (id && name)) - usage(); - - if ((id == 0) && (name == 0)) - usage(); - - r = task_for_pid(mach_task_self(), 0, &kernel_port); - machwarn(r, "unable to get kernel task port"); - if (r) { - fprintf(stderr, "kmodunload: Are you running as root?\n"); - exit(1); - } - - r = kmod_get_info(kernel_port, (void *)&info, &count); - macherr(r, "kmod_get_info() failed"); - - if (count < 1) { - fprintf(stderr, "kmodunload: there is nothing to unload?\n"); - exit(1); - } - - if (name) { - kmod_info_t *k = info; - while (k) { - if (!strcmp(k->name, name)) { - id = k->id; - break; - } - k = (k->next) ? (k + 1) : 0; - } - if (!k) { - fprintf(stderr, "kmodunload: can't kmod named: %s.\n", name); - exit(1); - } - } else { - kmod_info_t *k = info; - while (k) { - if (id == k->id) { - name = k->name; - break; - } - k = (k->next) ? (k + 1) : 0; - } - if (!name) { - fprintf(stderr, "kmodunload: can't find kmod id %d.\n", id); - exit(1); - } - } - - v_printf("kmodunload: found kmod %s, id %d.\n", name, id); - kernel_priv_port = mach_host_self(); /* if we are privileged */ - - stop_module(id); - unload_module(id); - - return 0; -} - diff --git a/kvm_mkdb.tproj/Makefile b/kvm_mkdb.tproj/Makefile deleted file mode 100644 index 70c627c..0000000 --- a/kvm_mkdb.tproj/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# Generated by the NeXT Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = kvm_mkdb - -PROJECTVERSION = 2.6 -PROJECT_TYPE = Tool -LANGUAGE = English - -HFILES = extern.h - -CFILES = kvm_mkdb.c nlist.c testdb.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kvm_mkdb.8 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = tool.make -NEXTSTEP_INSTALLDIR = /usr/sbin -WINDOWS_INSTALLDIR = /usr/sbin -PDO_UNIX_INSTALLDIR = /usr/sbin -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/kvm_mkdb.tproj/extern.h b/kvm_mkdb.tproj/extern.h deleted file mode 100644 index 32c9204..0000000 --- a/kvm_mkdb.tproj/extern.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * 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. - * - * @(#)extern.h 8.1 (Berkeley) 6/6/93 - */ - -void create_knlist __P((char *, DB *)); -void error __P((char *)); -int testdb __P(()); diff --git a/kvm_mkdb.tproj/kvm_mkdb.c b/kvm_mkdb.tproj/kvm_mkdb.c deleted file mode 100644 index 68a677e..0000000 --- a/kvm_mkdb.tproj/kvm_mkdb.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * 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. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)kvm_mkdb.c 8.3 (Berkeley) 5/4/95"; -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "extern.h" - -static void usage __P((void)); - -HASHINFO openinfo = { - 4096, /* bsize */ - 128, /* ffactor */ - 1024, /* nelem */ - 2048 * 1024, /* cachesize */ - NULL, /* hash() */ - 0 /* lorder */ -}; - -int -main(argc, argv) - int argc; - char *argv[]; -{ - DB *db; - int ch; - char *p, *nlistpath, *nlistname, dbtemp[MAXPATHLEN], dbname[MAXPATHLEN]; - - while ((ch = getopt(argc, argv, "")) != EOF) - switch (ch) { - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc > 1) - usage(); - - /* If the existing db file matches the currently running kernel, exit */ - if (testdb()) - exit(0); - -#define basename(cp) ((p = rindex((cp), '/')) != NULL ? p + 1 : (cp)) - nlistpath = argc > 0 ? argv[0] : _PATH_UNIX; - nlistname = basename(nlistpath); - - (void)snprintf(dbtemp, sizeof(dbtemp), "%skvm_%s.tmp", - _PATH_VARDB, nlistname); - (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", - _PATH_VARDB, nlistname); - (void)umask(0); - db = dbopen(dbtemp, O_CREAT | O_EXLOCK | O_TRUNC | O_RDWR, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, DB_HASH, &openinfo); - if (db == NULL) - err(1, "%s", dbtemp); - create_knlist(nlistpath, db); - if (db->close(db)) - err(1, "%s", dbtemp); - if (rename(dbtemp, dbname)) - err(1, "rename %s to %s", dbtemp, dbname); - exit(0); -} - -void -usage() -{ - (void)fprintf(stderr, "usage: kvm_mkdb [file]\n"); - exit(1); -} diff --git a/kvm_mkdb.tproj/nlist.c b/kvm_mkdb.tproj/nlist.c deleted file mode 100644 index ba11b44..0000000 --- a/kvm_mkdb.tproj/nlist.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * 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. - */ - -#ifndef lint -static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ - -#include - -#ifdef __APPLE__ -#include -#include -#define _AOUT_INCLUDE_ -#else -#include -#endif /* NeXT */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "extern.h" - -typedef struct nlist NLIST; -#define _strx n_un.n_strx -#define _name n_un.n_name - -#define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE)) - -static void badread __P((int, char *)); - -static char *kfile; - -void -create_knlist(name, db) - char *name; - DB *db; -{ - register int nsyms; - struct exec ebuf; - FILE *fp; - NLIST nbuf; - DBT data, key; - int fd, nr, strsize; - char *strtab, buf[1024]; - - kfile = name; - if ((fd = open(name, O_RDONLY, 0)) < 0) - err(1, "%s", name); - - /* Read in exec structure. */ - nr = read(fd, &ebuf, sizeof(struct exec)); - if (nr != sizeof(struct exec)) - badfmt("no exec header"); - - /* Check magic number and symbol count. */ - if (N_BADMAG(ebuf)) - badfmt("bad magic number"); - if (!ebuf.a_syms) - badfmt("stripped"); - - /* Seek to string table. */ - if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1) - badfmt("corrupted string table"); - - /* Read in the size of the symbol table. */ - nr = read(fd, (char *)&strsize, sizeof(strsize)); - if (nr != sizeof(strsize)) - badread(nr, "no symbol table"); - - /* Read in the string table. */ - strsize -= sizeof(strsize); - if (!(strtab = malloc(strsize))) - err(1, NULL); - if ((nr = read(fd, strtab, strsize)) != strsize) - badread(nr, "corrupted symbol table"); - - /* Seek to symbol table. */ - if (!(fp = fdopen(fd, "r"))) - err(1, "%s", name); - if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1) - err(1, "%s", name); - - data.data = (u_char *)&nbuf; - data.size = sizeof(NLIST); - - /* Read each symbol and enter it into the database. */ - nsyms = ebuf.a_syms / sizeof(struct nlist); - while (nsyms--) { - if (fread((char *)&nbuf, sizeof (NLIST), 1, fp) != 1) { - if (feof(fp)) - badfmt("corrupted symbol table"); - err(1, "%s", name); - } - if (!nbuf._strx || nbuf.n_type&N_STAB) - continue; - - key.data = (u_char *)strtab + nbuf._strx - sizeof(long); - key.size = strlen((char *)key.data); - if (db->put(db, &key, &data, 0)) - err(1, "record enter"); - - if (strcmp((char *)key.data, VRS_SYM) == 0) { - long cur_off, voff; -#ifndef KERNTEXTOFF -#define KERNTEXTOFF KERNBASE -#endif - /* - * Calculate offset relative to a normal (non-kernel) - * a.out. KERNTEXTOFF is where the kernel is really - * loaded; N_TXTADDR is where a normal file is loaded. - * From there, locate file offset in text or data. - */ - voff = nbuf.n_value - KERNTEXTOFF + N_TXTADDR(ebuf); - if ((nbuf.n_type & N_TYPE) == N_TEXT) - voff += N_TXTOFF(ebuf) - N_TXTADDR(ebuf); - else - voff += N_DATOFF(ebuf) - N_DATADDR(ebuf); - cur_off = ftell(fp); - if (fseek(fp, voff, SEEK_SET) == -1) - badfmt("corrupted string table"); - - /* - * Read version string up to, and including newline. - * This code assumes that a newline terminates the - * version line. - */ - if (fgets(buf, sizeof(buf), fp) == NULL) - badfmt("corrupted string table"); - - key.data = (u_char *)VRS_KEY; - key.size = sizeof(VRS_KEY) - 1; - data.data = (u_char *)buf; - data.size = strlen(buf); - if (db->put(db, &key, &data, 0)) - err(1, "record enter"); - - /* Restore to original values. */ - data.data = (u_char *)&nbuf; - data.size = sizeof(NLIST); - if (fseek(fp, cur_off, SEEK_SET) == -1) - badfmt("corrupted string table"); - } - } - (void)fclose(fp); -} - -static void -badread(nr, p) - int nr; - char *p; -{ - if (nr < 0) - err(1, "%s", kfile); - badfmt(p); -} diff --git a/kvm_mkdb.tproj/testdb.c b/kvm_mkdb.tproj/testdb.c deleted file mode 100644 index e5f4a69..0000000 --- a/kvm_mkdb.tproj/testdb.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)testdb.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "extern.h" - -/* Return true if the db file is valid, else false */ -int -testdb() -{ - register DB *db; - register int cc, kd, ret, dbversionlen; - register char *cp, *uf; - DBT rec; - struct nlist nitem; - char dbname[MAXPATHLEN], dbversion[_POSIX2_LINE_MAX]; - char kversion[_POSIX2_LINE_MAX]; - - ret = 0; - db = NULL; - - if ((kd = open(_PATH_KMEM, O_RDONLY, 0)) < 0) - goto close; - - uf = _PATH_UNIX; - if ((cp = rindex(uf, '/')) != 0) - uf = cp + 1; - (void) snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf); - if ((db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL) - goto close; - - /* Read the version out of the database */ - rec.data = VRS_KEY; - rec.size = sizeof(VRS_KEY) - 1; - if ((db->get)(db, &rec, &rec, 0)) - goto close; - if (rec.data == 0 || rec.size > sizeof(dbversion)) - goto close; - bcopy(rec.data, dbversion, rec.size); - dbversionlen = rec.size; - - /* Read version string from kernel memory */ - rec.data = VRS_SYM; - rec.size = sizeof(VRS_SYM) - 1; - if ((db->get)(db, &rec, &rec, 0)) - goto close; - if (rec.data == 0 || rec.size != sizeof(struct nlist)) - goto close; - bcopy(rec.data, &nitem, sizeof(nitem)); - /* - * Theoretically possible for lseek to be seeking to -1. Not - * that it's something to lie awake nights about, however. - */ - errno = 0; - if (lseek(kd, (off_t)nitem.n_value, SEEK_SET) == -1 && errno != 0) - goto close; - cc = read(kd, kversion, sizeof(kversion)); - if (cc < 0 || cc != sizeof(kversion)) - goto close; - - /* If they match, we win */ - ret = bcmp(dbversion, kversion, dbversionlen) == 0; - -close: if (kd >= 0) - (void)close(kd); - if (db) - (void)(db->close)(db); - return (ret); -} diff --git a/latency.tproj/Makefile b/latency.tproj/Makefile index aa1db0d..a8377fa 100644 --- a/latency.tproj/Makefile +++ b/latency.tproj/Makefile @@ -4,7 +4,10 @@ Install_Dir = /usr/bin CFILES = latency.c MANPAGES = latency.1 -Extra_LD_Flags = -lcurses +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_LD_Flags += -lcurses -lutil Extra_CC_Flags = -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd diff --git a/latency.tproj/latency.c b/latency.tproj/latency.c index 63e92d5..65b3c9b 100644 --- a/latency.tproj/latency.c +++ b/latency.tproj/latency.c @@ -54,6 +54,8 @@ #include #endif /*KERNEL_PRIVATE*/ +#include + #include #include #include @@ -157,9 +159,9 @@ struct ct { #define NUMPARMS 23 struct th_info { - int thread; + uintptr_t thread; int type; - int child_thread; + uintptr_t child_thread; int arg1; double stime; long *pathptr; @@ -192,19 +194,19 @@ int cur_max = 0; #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) #define DBG_FUNC_MASK 0xfffffffc -#define CPU_NUMBER(ts) ((ts & KDBG_CPU_MASK) >> KDBG_CPU_SHIFT) +#define CPU_NUMBER(kp) kdbg_get_cpu(kp) -#define DBG_ZERO_FILL_FAULT 1 -#define DBG_PAGEIN_FAULT 2 -#define DBG_COW_FAULT 3 -#define DBG_CACHE_HIT_FAULT 4 -char *fault_name[5] = { +char *fault_name[9] = { "", "ZeroFill", "PageIn", "COW", "CacheHit", + "NoZeroFill", + "Guard", + "PageInFile", + "PageInAnon" }; char *pc_to_string(); @@ -749,9 +751,7 @@ exit_usage() int -main(argc, argv) -int argc; -char *argv[]; +main(int argc, char *argv[]) { uint64_t start, stop; uint64_t timestamp1; @@ -771,6 +771,11 @@ char *argv[]; void do_kernel_nm(); void open_logfile(); + if (0 != reexec_to_match_kernel()) { + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); + } + my_policy = THREAD_STANDARD_POLICY; policy_name = "TIMESHARE"; @@ -1111,7 +1116,7 @@ void read_command_map() } -void create_map_entry(int thread, char *command) +void create_map_entry(uintptr_t thread, char *command) { int i, n; kd_threadmap *map; @@ -1167,7 +1172,7 @@ void create_map_entry(int thread, char *command) } -kd_threadmap *find_thread_map(int thread) +kd_threadmap *find_thread_map(uintptr_t thread) { int i; kd_threadmap *map; @@ -1187,7 +1192,7 @@ kd_threadmap *find_thread_map(int thread) } void -kill_thread_map(int thread) +kill_thread_map(uintptr_t thread) { kd_threadmap *map; @@ -1204,7 +1209,7 @@ kill_thread_map(int thread) } -struct th_info *find_thread(int thread, int type1, int type2) { +struct th_info *find_thread(uintptr_t thread, int type1, int type2) { struct th_info *ti; for (ti = th_state; ti < &th_state[cur_max]; ti++) { @@ -1325,7 +1330,7 @@ void sample_sc(uint64_t start, uint64_t stop) void print_entry(); thread = kd->arg5; - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); debugid = kd->debugid; type = kd->debugid & DBG_FUNC_MASK; @@ -1354,7 +1359,7 @@ void sample_sc(uint64_t start, uint64_t stop) } if ((kd->debugid & DBG_FUNC_MASK) == DECR_TRAP) { - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); last_decrementer_kd[cpunum] = kd; } else @@ -1626,7 +1631,7 @@ enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double int cpunum; char *p; - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); if (print_info && fp) { if ((p = find_code(type))) { @@ -1697,7 +1702,7 @@ exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double t char *p; uint64_t user_addr; - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); ti = find_thread(thread, type, type); #if 0 @@ -1713,10 +1718,10 @@ exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double t if ((p = find_code(type))) { if (type == INTERRUPT) { fprintf(fp, "INTERRUPT %-8x %d %s\n", thread, cpunum, command); - } else if (type == MACH_vmfault && kd->arg4 <= DBG_CACHE_HIT_FAULT) { + } else if (type == MACH_vmfault && kd->arg4 <= DBG_PAGEIND_FAULT) { user_addr = ((uint64_t)kd->arg1 << 32) | (uint32_t)kd->arg2; - fprintf(fp, "%-28.28s %-8.8s %-16qx %-8x %d %s\n", + fprintf(fp, "%-28.28s %-10.10s %-16qx %-8x %d %s\n", p, fault_name[kd->arg4], user_addr, thread, cpunum, command); } else { @@ -1753,7 +1758,7 @@ print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, double ti if (!fp) return; - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); #if 0 fprintf(fp, "cur_max = %d, type = %x, thread = %x, cpunum = %d\n", cur_max, type, thread, cpunum); #endif @@ -1841,13 +1846,13 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d fprintf(log_fp, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n"); thread = kd_beg->arg5; - cpunum = CPU_NUMBER(kd_end->timestamp); + cpunum = CPU_NUMBER(kd_end); for (kd_count = 0, kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer); kd_start--, kd_count++) { if (kd_count == MAX_LOG_COUNT) break; - if (CPU_NUMBER(kd_start->timestamp) != cpunum) + if (CPU_NUMBER(kd_start) != cpunum) continue; if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP) @@ -1867,7 +1872,7 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d if ((kd_stop->debugid & DBG_FUNC_MASK) == DECR_TRAP) break; - if (CPU_NUMBER(kd_stop->timestamp) != cpunum) + if (CPU_NUMBER(kd_stop) != cpunum) continue; if (kd_stop->arg5 != thread) @@ -1892,7 +1897,7 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d int mode; thread = kd->arg5; - cpunum = CPU_NUMBER(kd->timestamp); + cpunum = CPU_NUMBER(kd); debugid = kd->debugid; type = kd->debugid & DBG_FUNC_MASK; @@ -2090,13 +2095,13 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d double handle_decrementer(kd_buf *kd) { double latency; - int elapsed_usecs; + long elapsed_usecs; - if ((int)(kd->arg1) >= 0) + if ((long)(kd->arg1) >= 0) latency = 1; else latency = (((double)(-1 - kd->arg1)) / divisor); - elapsed_usecs = (int)latency; + elapsed_usecs = (long)latency; if (elapsed_usecs < 100) i_usec_10_bins[elapsed_usecs/10]++; diff --git a/login.tproj/Makefile b/login.tproj/Makefile index be4e46b..958b2c5 100644 --- a/login.tproj/Makefile +++ b/login.tproj/Makefile @@ -3,16 +3,30 @@ Install_Dir = /usr/bin HFILES = pathnames.h -CFILES = klogin.c login.c +CFILES = login.c MANPAGES = login.1 Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) -ifeq "$(Embedded)" "NO" -Extra_LD_Flags = -lbsm -lpam -lpam_misc -Extra_CC_Flags = -DUSE_PAM -DUSE_BSM -no-cpp-precomp +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -D__FBSDID=__RCSID + +ifneq ($(Embedded),YES) +CFILES += login_audit.c +Extra_CC_Flags += -DUSE_PAM -DUSE_BSM_AUDIT +Extra_LD_Flags += -lbsm -lpam +else +Extra_CC_Flags += -Wno-deprecated-declarations endif include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make Install_Program_Mode = 04555 + +after_install: + $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d + $(INSTALL_FILE) login.pam "$(DSTROOT)"/private/etc/pam.d/login + sed -e '/pam_launchd.so/d' < login.pam > "$(OBJROOT)"/login.term + $(INSTALL_FILE) "$(OBJROOT)"/login.term "$(DSTROOT)"/private/etc/pam.d/login.term diff --git a/login.tproj/login.1 b/login.tproj/login.1 index a49fcb7..6edef05 100644 --- a/login.tproj/login.1 +++ b/login.tproj/login.1 @@ -30,41 +30,41 @@ .\" SUCH DAMAGE. .\" .\" @(#)login.1 8.2 (Berkeley) 5/5/94 +.\" $FreeBSD: src/usr.bin/login/login.1,v 1.33 2007/11/30 11:02:36 philip Exp $ .\" -.Dd May 5, 1994 +.Dd September 13, 2006 .Dt LOGIN 1 -.Os BSD 4 +.Os .Sh NAME .Nm login .Nd log into the computer .Sh SYNOPSIS -.Nm login +.Nm .Op Fl pq .Op Fl h Ar hostname .Op Ar user -.Nm login +.Nm .Fl f .Op Fl lpq .Op Fl h Ar hostname .Op Ar user Op Ar prog Op Ar args... .Sh DESCRIPTION The -.Nm login +.Nm utility logs users (and pseudo-users) into the computer system. .Pp If no user is specified, or if a user is specified and authentication of the user fails, -.Nm login +.Nm prompts for a user name. -Authentication of users is done via passwords. +Authentication of users is configurable via +.Xr pam 8 . +Password authentication is the default. .Pp -The options are as follows: -.Bl -tag -width Ds -.\" ========== +The following options are available: +.Bl -tag -width indent .It Fl f -The -.Fl f -option is used when a user name is specified to indicate that proper +When a user name is specified, this option indicates that proper authentication has already been done and that no password need be requested. This option may only be used by the super-user or when an already @@ -75,32 +75,26 @@ With the option, an alternate program (and any arguments) may be run instead of the user's default shell. The program and arguments follows the user name. -.\" ========== .It Fl h -The -.Fl h -option specifies the host from which the connection was received. +Specify the host from which the connection was received. It is used by various daemons such as -.Xr telnetd 8 . +.Xr telnetd 8 . This option may only be used by the super-user. -.\" ========== .It Fl l Tells the program executed by -.Nm login +.Nm that this is not a login session (by convention, a login session is signalled to the program with a hyphen as the first character of .Em argv[0] ; this option disables that), and prevents it from chdir(2)ing to the user's home directory. The default is to add the hyphen (this is a login session). -.\" ========== .It Fl p By default, -.Nm login +.Nm discards any previous environment. The .Fl p option disables this behavior. -.\" ========== .It Fl q This forces quiet logins, as if a .Pa .hushlogin @@ -110,24 +104,24 @@ is present. If the file .Pa /etc/nologin exists, -.Nm login +.Nm dislays its contents to the user and exits. This is used by .Xr shutdown 8 to prevent users from logging in when the system is about to go down. .Pp Immediately after logging a user in, -.Nm login +.Nm displays the system copyright notice, the date and time the user last logged in, the message of the day as well as other information. If the file -.Dq Pa .hushlogin -exists in the user's home directory or +.Pa .hushlogin +exists in the user's home directory, all of these messages are suppressed. .Fl q is specified, all of these messages are suppressed. This is to simplify logins for non-human users, such as .Xr uucp 1 . -.Nm Login +.Nm then records an entry in .Xr utmpx 5 and the like, and executes the user's command interpreter (or the program @@ -135,19 +129,27 @@ specified on the command line if .Fl f is specified). .Pp -Login enters information into the environment (see +The +.Nm +utility enters information into the environment (see .Xr environ 7 ) specifying the user's home directory (HOME), command interpreter (SHELL), search path (PATH), terminal type (TERM) and user name (both LOGNAME and USER). .Pp -The standard shells, -.Xr csh 1 -and -.Xr sh 1 , -do not fork before executing the -.Nm login -utility. +Some shells may provide a builtin +.Nm +command which is similar or identical to this utility. +Consult the +.Xr builtin 1 +manual page. +.Pp +The +.Nm +utility will submit an audit record when login succeeds or fails. +Failure to determine the current auditing state will +result in an error exit from +.Nm . .Sh FILES .Bl -tag -width /var/mail/userXXX -compact .It Pa /etc/motd @@ -160,9 +162,18 @@ current logins system mailboxes .It Pa \&.hushlogin makes login quieter +.It Pa /etc/pam.d/login +.Xr pam 8 +configuration file +.It Pa /etc/security/audit_user +user flags for auditing +.It Pa /etc/security/audit_control +global flags for auditing .El .Sh SEE ALSO +.Xr builtin 1 , .Xr chpass 1 , +.Xr newgrp 1 , .Xr passwd 1 , .Xr rlogin 1 , .Xr getpass 3 , @@ -170,6 +181,6 @@ makes login quieter .Xr environ 7 .Sh HISTORY A -.Nm login -appeared in +.Nm +utility appeared in .At v6 . diff --git a/login.tproj/login.c b/login.tproj/login.c index 8f290a1..a765c89 100644 --- a/login.tproj/login.c +++ b/login.tproj/login.c @@ -1,28 +1,14 @@ -/* - * Copyright (c) 1999, 2004, 2006 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, 1987, 1988, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technologies, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * Portions copyright (c) 1999-2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,8 +20,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -54,9 +40,13 @@ */ #if 0 -static char copyright[] = -"@(#) Copyright (c) Apple Computer, Inc. 1997\n\n"; +#ifndef lint +static char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; #endif +#endif + +#include +__FBSDID("$FreeBSD: src/usr.bin/login/login.c,v 1.106 2007/07/04 00:00:40 scf Exp $"); /* * login [ name ] @@ -64,16 +54,28 @@ static char copyright[] = * login -f name (for pre-authenticated login: datakit, xterm, etc.) */ +#ifndef __APPLE__ +#include +#include +#endif #include +#include #include #include #include -#include #include #include #include #include +#ifdef __APPLE__ +#include +#else +#include +#endif +#ifdef LOGIN_CAP +#include +#endif #include #include #include @@ -82,13 +84,16 @@ static char copyright[] = #include #include #include -#include #include -#ifdef USE_PAM +#ifdef __APPLE__ #include +#ifdef USE_PAM #else /* !USE_PAM */ -#include +#ifndef _UTX_USERSIZE +#define _UTX_USERSIZE MAXLOGNAME +#endif #endif /* USE_PAM */ +#endif /* __APPLE__ */ #include #include @@ -96,117 +101,181 @@ static char copyright[] = #include #include -#include - -#ifdef USE_BSM +#ifdef USE_BSM_AUDIT #include #include #endif -#ifdef USE_PAM -#include -#include -#endif - +#ifdef __APPLE__ #include - +#include +#include #include +#include +#include +#endif /* __APPLE__ */ + +#ifdef USE_PAM +#include +#include +#endif /* USE_PAM */ + +#include "login.h" #include "pathnames.h" -void badlogin __P((char *)); -void checknologin __P((void)); -void dolastlog __P((int)); -void getloginname __P((void)); -void motd __P((void)); -int rootterm __P((char *)); -void sigint __P((int)); -void sleepexit __P((int)); -char *stypeof __P((char *)); -void timedout __P((int)); -#ifdef KERBEROS -int klogin __P((struct passwd *, char *, char *, char *)); -#endif -void au_success(); -void au_fail(char *, int); +#ifdef USE_PAM +static int auth_pam(void); +#endif /* USE_PAM */ +static void bail(int, int); +#ifdef USE_PAM +static int export(const char *); +static void export_pam_environment(void); +#endif /* USE_PAM */ +static int motd(const char *); +static void badlogin(char *); +static char *getloginname(void); +#ifdef USE_PAM +static void pam_syslog(const char *); +static void pam_cleanup(void); +#endif /* USE_PAM */ +static void refused(const char *, const char *, int); +static const char *stypeof(char *); +static void sigint(int); +static void timedout(int); +static void usage(void); +#ifdef __APPLE__ +static void dolastlog(int); +static void handle_sighup(int); #ifndef USE_PAM -extern void login __P((struct utmp *)); +static void checknologin(void); +static int rootterm(const char *); #endif /* !USE_PAM */ -static void bail(int, int); -static void refused(const char *, const char *, int); - -#define TTYGRPNAME "tty" /* name of group to own ttys */ -#define NO_SLEEP_EXIT 0 -#define SLEEP_EXIT 5 +#endif /* __APPLE__ */ + +#define TTYGRPNAME "tty" /* group to own ttys */ +#define DEFAULT_BACKOFF 3 +#define DEFAULT_RETRIES 10 +#define DEFAULT_PROMPT "login: " +#define DEFAULT_PASSWD_PROMPT "Password:" +#define TERM_UNKNOWN "su" +#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ +#define NO_SLEEP_EXIT 0 +#define SLEEP_EXIT 5 /* * This bounds the time given to login. Not a define so it can * be patched on machines where it's too small. */ -u_int timeout = 300; +static u_int timeout = 300; + +/* Buffer for signal handling of timeout */ +static jmp_buf timeout_buf; + +struct passwd *pwd; +static int failures; + +static char *envinit[1]; /* empty environment list */ -#ifdef KERBEROS -int notickets = 1; -char *instance; -char *krbtkfile_env; -int authok; +/* + * Command line flags and arguments + */ +static int fflag; /* -f: do not perform authentication */ +#ifdef __APPLE__ +static int lflag; /* -l: login session to the commmand that follows username */ #endif +static int hflag; /* -h: login from remote host */ +static char *hostname; /* hostname from command line */ +static int pflag; /* -p: preserve environment */ + +/* + * User name + */ +static char *username; /* user name */ +static char *olduser; /* previous user name */ + +/* + * Prompts + */ +static char default_prompt[] = DEFAULT_PROMPT; +static const char *prompt; +static char default_passwd_prompt[] = DEFAULT_PASSWD_PROMPT; +static const char *passwd_prompt; + +static char *tty; + +/* + * PAM data + */ +#ifdef USE_PAM +static pam_handle_t *pamh = NULL; +static struct pam_conv pamc = { openpam_ttyconv, NULL }; +static int pam_err; +static int pam_silent = PAM_SILENT; +static int pam_cred_established; +static int pam_session_established; +#endif /* USE_PAM */ + +#ifdef __APPLE__ +pid_t pid; -struct passwd *pwd; -int failures; -char term[64], *hostname, *username = NULL, *tty; #ifdef USE_PAM -static pam_handle_t *pamh = NULL; -static struct pam_conv conv = { misc_conv, NULL }; -static int pam_err; -static int pam_silent = PAM_SILENT; -static int pam_cred_established; -static int pam_session_established; static struct lastlogx lastlog; #endif /* USE_PAM */ -int hflag; -#ifdef USE_BSM -#define NA_EVENT_STR_SIZE 25 +#ifdef USE_BSM_AUDIT au_tid_t tid; -#endif +#endif /* USE_BSM_AUDIT */ +#endif /* __APPLE__ */ int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { - extern char **environ; struct group *gr; struct stat st; - int prio; -#ifndef USE_PAM - struct utmp utmp; -#endif /* USE_PAM */ - int ask, ch, cnt, oflag = 0, fflag, lflag, pflag; - int quietlog = 0, rootlogin = 0; - uid_t uid; - uid_t euid; + int retries, backoff; + int ask, ch, cnt, quietlog = 0, rootlogin, rval; + uid_t uid, euid; gid_t egid; - char *domain, *p, *ttyn; - char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; - char localhost[MAXHOSTNAMELEN]; + char *term; + char *p, *ttyn; + char tname[sizeof(_PATH_TTY) + 10]; + char *arg0; + const char *tp; +#ifdef __APPLE__ + int prio; #ifdef USE_PAM - char **pmenv; - pid_t pid; + const char *name = "login"; /* PAM config */ #else - int rval; - char *salt; + struct utmpx utmp; +#endif /* USE_PAM */ + const char *shell = NULL; +#endif /* !__APPLE__ */ +#ifdef LOGIN_CAP + login_cap_t *lc = NULL; + login_cap_t *lc_user = NULL; +#endif /* LOGIN_CAP */ +#ifndef __APPLE__ + pid_t pid; #endif - +#ifdef USE_BSM_AUDIT char auditsuccess = 1; +#endif - (void)signal(SIGALRM, timedout); - (void)alarm(timeout); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGHUP, SIG_IGN); + if (setjmp(timeout_buf)) { + if (failures) + badlogin(username); + (void)fprintf(stderr, "Login timed out after %d seconds\n", + timeout); + bail(NO_SLEEP_EXIT, 0); + } + (void)signal(SIGALRM, timedout); + (void)alarm(timeout); #ifdef __APPLE__ prio = getpriority(PRIO_PROCESS, 0); #endif @@ -214,90 +283,111 @@ main(argc, argv) openlog("login", LOG_ODELAY, LOG_AUTH); - /* - * -p is used by getty to tell login not to destroy the environment - * -f is used to skip a second login authentication - * -l is used to indicate a login session to the command that - * follows username - * -h is used by other servers to pass the name of the remote - * host to login so that it may be placed in utmp and wtmp - * -q is used to force hushlogin - */ - domain = NULL; - if (gethostname(localhost, sizeof(localhost)) < 0) - syslog(LOG_ERR, "couldn't get local hostname: %m"); - else - domain = strchr(localhost, '.'); - + uid = getuid(); euid = geteuid(); egid = getegid(); - fflag = hflag = lflag = pflag = 0; - uid = getuid(); - while ((ch = getopt(argc, argv, "1fh:lpq")) != EOF) +#ifdef __APPLE__ + while ((ch = getopt(argc, argv, "1fh:lpq")) != -1) +#else + while ((ch = getopt(argc, argv, "fh:p")) != -1) +#endif switch (ch) { - case '1': - oflag = 1; - break; case 'f': fflag = 1; break; case 'h': - if (uid) + if (uid != 0) errx(1, "-h option: %s", strerror(EPERM)); + if (strlen(optarg) >= MAXHOSTNAMELEN) + errx(1, "-h option: %s: exceeds maximum " + "hostname size", optarg); hflag = 1; - if (domain && (p = strchr(optarg, '.')) && - strcasecmp(p, domain) == 0) - *p = 0; hostname = optarg; break; - case 'l': - lflag = 1; - break; case 'p': pflag = 1; break; +#ifdef __APPLE__ + case '1': + break; + case 'l': + lflag = 1; + break; case 'q': quietlog = 1; break; +#endif case '?': default: - if (!uid) + if (uid == 0) syslog(LOG_ERR, "invalid flag %c", ch); - (void)fprintf(stderr, - "usage: login [-pq] [-h hostname] [username]\n"); - (void)fprintf(stderr, - " login -f [-lpq] [-h hostname] [username [prog [arg ...]]]\n"); - exit(1); + usage(); } argc -= optind; argv += optind; - if (*argv) { - username = *argv++; + if (argc > 0) { + username = strdup(*argv); + if (username == NULL) + err(1, "strdup()"); ask = 0; - } else +#ifdef __APPLE__ + argv++; +#endif /* __APPLE__ */ + } else { ask = 1; + } + +#ifndef __APPLE__ + setproctitle("-%s", getprogname()); +#endif /* !__APPLE__ */ for (cnt = getdtablesize(); cnt > 2; cnt--) (void)close(cnt); + /* + * Get current TTY + */ ttyn = ttyname(STDIN_FILENO); if (ttyn == NULL || *ttyn == '\0') { (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); ttyn = tname; } - if (tty = strrchr(ttyn, '/')) + if ((tty = strrchr(ttyn, '/')) != NULL) ++tty; else tty = ttyn; -#ifdef USE_BSM +#ifdef LOGIN_CAP + /* + * Get "login-retries" & "login-backoff" from default class + */ + lc = login_getclass(NULL); + prompt = login_getcapstr(lc, "login_prompt", + default_prompt, default_prompt); + passwd_prompt = login_getcapstr(lc, "passwd_prompt", + default_passwd_prompt, default_passwd_prompt); + retries = login_getcapnum(lc, "login-retries", + DEFAULT_RETRIES, DEFAULT_RETRIES); + backoff = login_getcapnum(lc, "login-backoff", + DEFAULT_BACKOFF, DEFAULT_BACKOFF); + login_close(lc); + lc = NULL; +#else /* !LOGIN_CAP */ + prompt = default_prompt; + passwd_prompt = default_passwd_prompt; + retries = DEFAULT_RETRIES; + backoff = DEFAULT_BACKOFF; +#endif /* !LOGIN_CAP */ + +#ifdef __APPLE__ +#ifdef USE_BSM_AUDIT /* Set the terminal id */ audit_set_terminal_id(&tid); if (fstat(STDIN_FILENO, &st) < 0) { fprintf(stderr, "login: Unable to stat terminal\n"); - au_fail("Unable to stat terminal", 1); + au_login_fail("Unable to stat terminal", 1); exit(-1); } if (S_ISCHR(st.st_mode)) { @@ -305,293 +395,277 @@ main(argc, argv) } else { tid.port = 0; } -#endif - -#ifdef USE_PAM - pam_err = pam_start("login", username, &conv, &pamh); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM Error", 1); - exit(1); - } - pam_err = pam_set_item(pamh, PAM_TTY, tty); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM Error", 1); - exit(1); - } - - pam_err = pam_set_item(pamh, PAM_RHOST, hostname); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM Error", 1); - exit(1); - } - - pam_err = pam_set_item(pamh, PAM_USER_PROMPT, "login: "); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM Error", 1); - exit(1); - } - - if( !username ) - getloginname(); - pam_set_item(pamh, PAM_USER, username); - pwd = getpwnam(username); - if( (pwd != NULL) && (pwd->pw_uid == 0) ) - rootlogin = 1; - - if( (pwd != NULL) && fflag && ((uid == 0) || (uid == pwd->pw_uid)) ){ - pam_err = 0; - auditsuccess = 0; /* we've simply opened a terminal window */ - } else { - - pam_err = pam_authenticate(pamh, 0); - while( (!oflag) && (cnt++ < 10) && ((pam_err == PAM_AUTH_ERR) || - (pam_err == PAM_USER_UNKNOWN) || - (pam_err == PAM_CRED_INSUFFICIENT) || - (pam_err == PAM_AUTHINFO_UNAVAIL))) { - /* - * we are not exiting here, but this corresponds to - * a failed login event, so set exitstatus to 1 - */ - au_fail("Login incorrect", 1); - badlogin(username); - printf("Login incorrect\n"); - rootlogin = 0; - getloginname(); - pwd = getpwnam(username); - if( (pwd != NULL) && (pwd->pw_uid == 0) ) - rootlogin = 1; - pam_set_item(pamh, PAM_USER, username); - pam_err = pam_authenticate(pamh, 0); - } - - if( pam_err != PAM_SUCCESS ) { - pam_get_item(pamh, PAM_USER, (void *)&username); - badlogin(username); - printf("Login incorrect\n"); - au_fail("Login incorrect", 1); - exit(1); - } - - pam_err = pam_acct_mgmt(pamh, 0); - if( pam_err == PAM_NEW_AUTHTOK_REQD ) { - pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); - } - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM error", 1); - exit(1); - } - } - - pam_err = pam_get_item(pamh, PAM_USER, (void *)&username); - if( (pam_err == PAM_SUCCESS) && username && *username) - pwd = getpwnam(username); - - /* get lastlog info before PAM make a new entry */ - if (!quietlog) - getlastlogxbyname(username, &lastlog); - - pam_err = pam_open_session(pamh, 0); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM error", 1); - exit(1); - } - - pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED); - if( pam_err != PAM_SUCCESS ) { - fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err)); - au_fail("PAM error", 1); - exit(1); - } +#endif /* USE_BSM_AUDIT */ +#endif /* __APPLE__ */ -#else /* USE_PAM */ + /* + * Try to authenticate the user until we succeed or time out. + */ for (cnt = 0;; ask = 1) { if (ask) { fflag = 0; - getloginname(); + if (olduser != NULL) + free(olduser); + olduser = username; + username = getloginname(); } rootlogin = 0; -#ifdef KERBEROS - if ((instance = strchr(username, '.')) != NULL) { - if (strncmp(instance, ".root", 5) == 0) - rootlogin = 1; - *instance++ = '\0'; - } else - instance = ""; -#endif - if (strlen(username) > UT_NAMESIZE) - username[UT_NAMESIZE] = '\0'; + +#ifdef __APPLE__ + if (strlen(username) > _UTX_USERSIZE) + username[_UTX_USERSIZE] = '\0'; +#endif /* __APPLE__ */ /* * Note if trying multiple user names; log failures for * previous user name, but don't bother logging one failure * for nonexistent name (mistyped username). */ - if (failures && strcmp(tbuf, username)) { - if (failures > (pwd ? 0 : 1)) { - badlogin(tbuf); - } - failures = 0; + if (failures && strcmp(olduser, username) != 0) { + if (failures > (pwd ? 0 : 1)) + badlogin(olduser); } - (void)strcpy(tbuf, username); - if (pwd = getpwnam(username)) - salt = pwd->pw_passwd; - else - salt = "xx"; +#ifdef __APPLE__ +#ifdef USE_PAM + /* get lastlog info before PAM make a new entry */ + if (!quietlog) + getlastlogxbyname(username, &lastlog); +#endif /* USE_PAM */ +#endif /* __APPLE__ */ + + pwd = getpwnam(username); +#ifdef USE_PAM /* - * if we have a valid account name, and it doesn't have a - * password, or the -f option was specified and the caller - * is root or the caller isn't changing their uid, don't - * authenticate. + * Load the PAM policy and set some variables */ - if (pwd && (*pwd->pw_passwd == '\0' || - fflag && (uid == 0 || uid == pwd->pw_uid))) - break; - fflag = 0; - if (pwd && pwd->pw_uid == 0) - rootlogin = 1; +#ifdef __APPLE__ + if (fflag && (pwd != NULL) && (pwd->pw_uid == uid)) { + name = "login.term"; + } +#endif + pam_err = pam_start(name, username, &pamc, &pamh); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_start()"); +#ifdef USE_BSM_AUDIT + au_login_fail("PAM Error", 1); +#endif + bail(NO_SLEEP_EXIT, 1); + } + pam_err = pam_set_item(pamh, PAM_TTY, tty); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_set_item(PAM_TTY)"); +#ifdef USE_BSM_AUDIT + au_login_fail("PAM Error", 1); +#endif + bail(NO_SLEEP_EXIT, 1); + } + pam_err = pam_set_item(pamh, PAM_RHOST, hostname); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_set_item(PAM_RHOST)"); +#ifdef USE_BSM_AUDIT + au_login_fail("PAM Error", 1); +#endif + bail(NO_SLEEP_EXIT, 1); + } +#endif /* USE_PAM */ - (void)setpriority(PRIO_PROCESS, 0, -4); + if (pwd != NULL && pwd->pw_uid == 0) + rootlogin = 1; - p = getpass("Password:"); + /* + * If the -f option was specified and the caller is + * root or the caller isn't changing their uid, don't + * authenticate. + */ + if (pwd != NULL && fflag && + (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) { + /* already authenticated */ + rval = 0; +#ifdef USE_BSM_AUDIT + auditsuccess = 0; /* opened a terminal window only */ +#endif - if (pwd) { -#ifdef KERBEROS - rval = klogin(pwd, instance, localhost, p); - if (rval != 0 && rootlogin && pwd->pw_uid != 0) - rootlogin = 0; - if (rval == 0) - authok = 1; - else if (rval == 1) - rval = strcmp(crypt(p, salt), pwd->pw_passwd); +#ifdef __APPLE__ +#ifndef USE_PAM + /* If the account doesn't have a password, authenticate. */ + } else if (pwd != NULL && pwd->pw_passwd[0] == '\0') { + rval = 0; +#endif /* !USE_PAM */ +#endif /* __APPLE__ */ + } else { + fflag = 0; + (void)setpriority(PRIO_PROCESS, 0, -4); +#ifdef USE_PAM + rval = auth_pam(); #else + { + char* salt = pwd ? pwd->pw_passwd : "xx"; + char* p = getpass(passwd_prompt); rval = strcmp(crypt(p, salt), pwd->pw_passwd); + memset(p, 0, strlen(p)); + } #endif + (void)setpriority(PRIO_PROCESS, 0, 0); } - memset(p, 0, strlen(p)); - - (void)setpriority(PRIO_PROCESS, 0, 0); +#ifdef __APPLE__ +#ifndef USE_PAM /* - * If trying to log in as root without Kerberos, - * but with insecure terminal, refuse the login attempt. + * If trying to log in as root but with insecure terminal, + * refuse the login attempt. */ -#ifdef KERBEROS - if (authok == 0) -#endif if (pwd && rootlogin && !rootterm(tty)) { - (void)fprintf(stderr, - "%s login refused on this terminal.\n", - pwd->pw_name); - if (hostname) - syslog(LOG_NOTICE, - "LOGIN %s REFUSED FROM %s ON TTY %s", - pwd->pw_name, hostname, tty); - else - syslog(LOG_NOTICE, - "LOGIN %s REFUSED ON TTY %s", - pwd->pw_name, tty); - au_fail("Login refused on terminal", 0); + refused("root login refused on this terminal", "ROOTTERM", 0); +#ifdef USE_BSM_AUDIT + au_login_fail("Login refused on terminal", 0); +#endif continue; } +#endif /* !USE_PAM */ +#endif /* __APPLE__ */ - if (pwd && !rval) + if (pwd && rval == 0) break; +#ifdef USE_PAM + pam_cleanup(); +#endif /* USE_PAM */ + + /* + * We are not exiting here, but this corresponds to a failed + * login event, so set exitstatus to 1. + */ +#ifdef USE_BSM_AUDIT + au_login_fail("Login incorrect", 1); +#endif + (void)printf("Login incorrect\n"); failures++; - /* we allow 10 tries, but after 3 we start backing off */ - if (++cnt > 3) { - if (cnt >= 10) { + + pwd = NULL; + + /* + * Allow up to 'retry' (10) attempts, but start + * backing off after 'backoff' (3) attempts. + */ + if (++cnt > backoff) { + if (cnt >= retries) { badlogin(username); - au_fail("Login incorrect", 1); - sleepexit(1); + bail(SLEEP_EXIT, 1); } - au_fail("Login incorrect", 1); - sleep((u_int)((cnt - 3) * 5)); + sleep((u_int)((cnt - backoff) * 5)); } } -#endif /* committed to login -- turn off timeout */ (void)alarm((u_int)0); + (void)signal(SIGHUP, SIG_DFL); endpwent(); +#ifdef __APPLE__ if (!pwd) { fprintf(stderr, "login: Unable to find user: %s\n", username); exit(1); } +#ifndef USE_PAM /* if user not super-user, check for disabled logins */ if (!rootlogin) checknologin(); +#endif /* !USE_PAM */ +#endif /* APPLE */ - /* Audit successful login */ +#ifdef USE_BSM_AUDIT + /* Audit successful login. */ if (auditsuccess) - au_success(); + au_login_success(); +#endif - setegid(pwd->pw_gid); - seteuid(rootlogin ? 0 : pwd->pw_uid); +#ifdef LOGIN_CAP + /* + * Establish the login class. + */ + lc = login_getpwclass(pwd); + lc_user = login_getuserclass(pwd); - if (!lflag) { - /* First do a stat in case the homedir is automounted */ - stat(pwd->pw_dir,&st); + if (!(quietlog = login_getcapbool(lc_user, "hushlogin", 0))) + quietlog = login_getcapbool(lc, "hushlogin", 0); +#endif /* LOGIN_CAP */ - if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) { - printf("No home directory %s!\n", pwd->pw_dir); - if (chdir("/")) - refused("Cannot find root directory", "HOMEDIR", 1); - pwd->pw_dir = strdup("/"); - if (pwd->pw_dir == NULL) { - syslog(LOG_NOTICE, "strdup(): %m"); - bail(SLEEP_EXIT, 1); - } - printf("Logging in with home = \"/\".\n"); +#ifndef __APPLE__ + /* + * Switching needed for NFS with root access disabled. + * + * XXX: This change fails to modify the additional groups for the + * process, and as such, may restrict rights normally granted + * through those groups. + */ + (void)setegid(pwd->pw_gid); + (void)seteuid(rootlogin ? 0 : pwd->pw_uid); + + if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) { +#ifdef LOGIN_CAP + if (login_getcapbool(lc, "requirehome", 0)) + refused("Home directory not available", "HOMEDIR", 1); +#endif /* LOGIN_CAP */ + if (chdir("/") < 0) + refused("Cannot find root directory", "ROOTDIR", 1); + if (!quietlog || *pwd->pw_dir) + printf("No home directory.\nLogging in with home = \"/\".\n"); + pwd->pw_dir = strdup("/"); + if (pwd->pw_dir == NULL) { + syslog(LOG_NOTICE, "strdup(): %m"); + bail(SLEEP_EXIT, 1); } } - seteuid(euid); - setegid(egid); - if (!quietlog) + (void)seteuid(euid); + (void)setegid(egid); +#endif /* !__APPLE__ */ + if (!quietlog) { quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; +#ifdef USE_PAM + if (!quietlog) + pam_silent = 0; +#endif /* USE_PAM */ + } +#ifdef __APPLE__ /* Nothing else left to fail -- really log in. */ #ifndef USE_PAM memset((void *)&utmp, 0, sizeof(utmp)); - (void)time(&utmp.ut_time); - (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); + (void)gettimeofday(&utmp.ut_tv, NULL); + (void)strncpy(utmp.ut_user, username, sizeof(utmp.ut_user)); if (hostname) (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); - login(&utmp); + utmp.ut_type = USER_PROCESS | UTMPX_AUTOFILL_MASK; + utmp.ut_pid = getpid(); + pututxline(&utmp); #endif /* USE_PAM */ - dolastlog(quietlog); - - (void)chown(ttyn, pwd->pw_uid, - (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); - (void)chmod(ttyn, 0620); - (void)setgid(pwd->pw_gid); - - if (initgroups(username, pwd->pw_gid) == -1) - syslog(LOG_ERR, "login: initgroups() failed"); - + shell = ""; +#endif /* !__APPLE__ */ +#ifdef LOGIN_CAP + shell = login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell); +#endif /* !LOGIN_CAP */ if (*pwd->pw_shell == '\0') pwd->pw_shell = strdup(_PATH_BSHELL); - if (pwd->pw_shell == NULL) { - syslog(LOG_NOTICE, "strdup(): %m"); - bail(SLEEP_EXIT, 1); - } + if (pwd->pw_shell == NULL) { + syslog(LOG_NOTICE, "strdup(): %m"); + bail(SLEEP_EXIT, 1); + } + if (*shell == '\0') /* Not overridden */ + shell = pwd->pw_shell; + if ((shell = strdup(shell)) == NULL) { + syslog(LOG_NOTICE, "strdup(): %m"); + bail(SLEEP_EXIT, 1); + } -#if TARGET_OS_EMBEDDED +#if defined(__APPLE__) && TARGET_OS_EMBEDDED /* on embedded, allow a shell to live in /var/debug_mount/bin/sh */ #define _PATH_DEBUGSHELL "/var/debug_mount/bin/sh" if (stat(pwd->pw_shell, &st) != 0) { @@ -601,95 +675,250 @@ main(argc, argv) } #endif - /* Destroy environment unless user has requested its preservation. */ - if (!pflag) { - environ = malloc(sizeof(char *)); - *environ = NULL; - } - (void)setenv("HOME", pwd->pw_dir, 1); - (void)setenv("SHELL", pwd->pw_shell, 1); - if (term[0] == '\0') - (void)strncpy(term, stypeof(tty), sizeof(term)); - (void)setenv("TERM", term, 0); - (void)setenv("LOGNAME", pwd->pw_name, 1); - (void)setenv("USER", pwd->pw_name, 1); - (void)setenv("PATH", _PATH_DEFPATH, 0); -#ifdef KERBEROS - if (krbtkfile_env) - (void)setenv("KRBTKFILE", krbtkfile_env, 1); +#ifdef __APPLE__ + dolastlog(quietlog); #endif -#ifdef USE_PAM - pmenv = pam_getenvlist(pamh); - for( cnt = 0; pmenv && pmenv[cnt]; cnt++ ) - putenv(pmenv[cnt]); +#ifndef __APPLE__ + /* + * Set device protections, depending on what terminal the + * user is logged in. This feature is used on Suns to give + * console users better privacy. + */ + login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); +#endif /* !__APPLE__ */ - /* Ignore SIGHUP so that the parent's call to waitpid will - succeed and the tty ownership can be reset. */ - (void)signal(SIGHUP, SIG_IGN); + /* + * Clear flags of the tty. None should be set, and when the + * user sets them otherwise, this can cause the chown to fail. + * Since it isn't clear that flags are useful on character + * devices, we just clear them. + * + * We don't log in the case of EOPNOTSUPP because dev might be + * on NFS, which doesn't support chflags. + * + * We don't log in the EROFS because that means that /dev is on + * a read only file system and we assume that the permissions there + * are sane. + */ + if (ttyn != tname && chflags(ttyn, 0)) +#ifdef __APPLE__ + if (errno != EOPNOTSUPP && errno != ENOTSUP && errno != EROFS) +#else + if (errno != EOPNOTSUPP && errno != EROFS) +#endif + syslog(LOG_ERR, "chflags(%s): %m", ttyn); + if (ttyn != tname && chown(ttyn, pwd->pw_uid, + (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid)) + if (errno != EROFS) + syslog(LOG_ERR, "chown(%s): %m", ttyn); - pid = fork(); - if ( pid < 0 ) { - err(1, "fork"); - } else if( pid != 0 ) { - waitpid(pid, NULL, 0); - pam_setcred(pamh, PAM_DELETE_CRED); - pam_err = pam_close_session(pamh, 0); - pam_end(pamh,pam_err); - chown(ttyn, 0, 0); - chmod(ttyn, 0666); - exit(0); - } +#ifdef __APPLE__ + (void)chmod(ttyn, 0620); +#endif /* __APPLE__ */ - /* Restore the default SIGHUP handler for the child. */ - (void)signal(SIGHUP, SIG_DFL); +#ifndef __APPLE__ + /* + * Exclude cons/vt/ptys only, assume dialup otherwise + * TODO: Make dialup tty determination a library call + * for consistency (finger etc.) + */ + if (hflag && isdialuptty(tty)) + syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); +#endif /* !__APPLE__ */ +#ifdef LOGALL + /* + * Syslog each successful login, so we don't have to watch + * hundreds of wtmp or lastlogin files. + */ + if (hflag) + syslog(LOG_INFO, "login from %s on %s as %s", + hostname, tty, pwd->pw_name); + else + syslog(LOG_INFO, "login on %s as %s", + tty, pwd->pw_name); #endif - if (tty[sizeof("tty")-1] == 'd') - syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); - - /* If fflag is on, assume caller/authenticator has logged root login. */ - if (rootlogin && fflag == 0) - if (hostname) + /* + * If fflag is on, assume caller/authenticator has logged root + * login. + */ + if (rootlogin && fflag == 0) { + if (hflag) syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", username, tty, hostname); else - syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); + syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", + username, tty); + } -#ifdef KERBEROS - if (!quietlog && notickets == 1) - (void)printf("Warning: no Kerberos tickets issued.\n"); -#endif + /* + * Destroy environment unless user has requested its + * preservation - but preserve TERM in all cases + */ + term = getenv("TERM"); + if (!pflag) + environ = envinit; + if (term != NULL) + setenv("TERM", term, 0); - if (!quietlog) { - motd(); - (void)snprintf(tbuf, - sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name); - if (stat(tbuf, &st) == 0 && st.st_size != 0) - (void)printf("You have %smail.\n", - (st.st_mtime > st.st_atime) ? "new " : ""); +#ifndef __APPLE__ + /* + * PAM modules might add supplementary groups during pam_setcred(). + */ + if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) { + syslog(LOG_ERR, "setusercontext() failed - exiting"); + bail(NO_SLEEP_EXIT, 1); + } +#endif /* !__APPLE__ */ +#ifdef USE_PAM + pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_setcred()"); + bail(NO_SLEEP_EXIT, 1); } + pam_cred_established = 1; - (void)signal(SIGALRM, SIG_DFL); - (void)signal(SIGQUIT, SIG_DFL); - (void)signal(SIGINT, SIG_DFL); - (void)signal(SIGTSTP, SIG_IGN); + pam_err = pam_open_session(pamh, pam_silent); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_open_session()"); + bail(NO_SLEEP_EXIT, 1); + } + pam_session_established = 1; +#endif /* USE_PAM */ + +#ifdef __APPLE__ + /* + Install a signal handler that will forward SIGHUP to the + child and process group. The parent should not exit on + SIGHUP so that the tty ownership can be reset. */ + (void)signal(SIGHUP, handle_sighup); +#endif /* __APPLE__ */ - if (setlogin(pwd->pw_name) < 0) - syslog(LOG_ERR, "setlogin() failure: %m"); + /* + * We must fork() before setuid() because we need to call + * pam_close_session() as root. + */ + pid = fork(); + if (pid < 0) { + err(1, "fork"); + } else if (pid != 0) { + /* + * Parent: wait for child to finish, then clean up + * session. + */ + int status; +#ifndef __APPLE__ + setproctitle("-%s [pam]", getprogname()); +#endif /* !__APPLE__ */ +#ifdef __APPLE__ + /* Our SIGHUP handler may interrupt the wait */ + int res; + do { + res = waitpid(pid, &status, 0); + } while (res == -1 && errno == EINTR); +#else + waitpid(pid, &status, 0); +#endif +#ifdef __APPLE__ + chown(ttyn, 0, 0); + chmod(ttyn, 0666); +#endif /* __APPLE__ */ + bail(NO_SLEEP_EXIT, 0); + } + + /* + * NOTICE: We are now in the child process! + */ + +#ifdef __APPLE__ + /* Restore the default SIGHUP handler for the child. */ + (void)signal(SIGHUP, SIG_DFL); +#endif /* __APPLE__ */ + +#ifdef USE_PAM + /* + * Add any environment variables the PAM modules may have set. + */ + export_pam_environment(); + + /* + * We're done with PAM now; our parent will deal with the rest. + */ + pam_end(pamh, 0); + pamh = NULL; +#endif /* USE_PAM */ + /* + * We don't need to be root anymore, so set the login name and + * the UID. + */ + if (setlogin(username) != 0) { + syslog(LOG_ERR, "setlogin(%s): %m - exiting", username); + bail(NO_SLEEP_EXIT, 1); + } +#ifdef __APPLE__ /* restore process priority if not changing uids */ if (uid == (uid_t)pwd->pw_uid) { (void)setpriority(PRIO_PROCESS, 0, prio); } - - /* Discard permissions last so can't get killed and drop core. */ - if (rootlogin) - (void) setuid(0); + + (void)setgid(pwd->pw_gid); + if (initgroups(username, pwd->pw_gid) == -1) + syslog(LOG_ERR, "login: initgroups() failed"); + (void) setuid(rootlogin ? 0 : pwd->pw_uid); +#else /* !__APPLE__ */ + if (setusercontext(lc, pwd, pwd->pw_uid, + LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) { + syslog(LOG_ERR, "setusercontext() failed - exiting"); + exit(1); + } +#endif /* !__APPLE__ */ + +#ifdef __APPLE__ + /* We test for the home directory after pam_open_session(3) + * as the home directory may have been mounted by a session + * module, and after changing uid as the home directory may + * be NFS with root access disabled. */ + if (!lflag) { + /* First do a stat in case the homedir is automounted */ + stat(pwd->pw_dir,&st); + if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) { + printf("No home directory: %s\n", pwd->pw_dir); + if (chdir("/") < 0) { + refused("Cannot find root directory", "ROOTDIR", 0); + exit(1); + } + pwd->pw_dir = strdup("/"); + if (pwd->pw_dir == NULL) { + syslog(LOG_NOTICE, "strdup(): %m"); + exit(1); + } + } + } +#endif /* __APPLE__ */ + if (pwd->pw_shell) { + (void)setenv("SHELL", pwd->pw_shell, 1); + } else { + syslog(LOG_ERR, "pwd->pw_shell not set - exiting", username); + bail(NO_SLEEP_EXIT, 1); + } + if (pwd->pw_dir) { + (void)setenv("HOME", pwd->pw_dir, 1); + } else { + (void)setenv("HOME", "/", 1); + } + /* Overwrite "term" from login.conf(5) for any known TERM */ + if (term == NULL && (tp = stypeof(tty)) != NULL) + (void)setenv("TERM", tp, 1); else - (void) setuid(pwd->pw_uid); + (void)setenv("TERM", TERM_UNKNOWN, 0); + (void)setenv("LOGNAME", username, 1); + (void)setenv("USER", username, 1); + (void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0); +#ifdef __APPLE__ /* Re-enable crash reporter */ do { kern_return_t kr; @@ -698,8 +927,12 @@ main(argc, argv) #if defined(__ppc__) flavor = PPC_THREAD_STATE64; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__x86_64__) flavor = x86_THREAD_STATE; +#elif defined(__arm__) + flavor = ARM_THREAD_STATE; +#else +#error unsupported architecture #endif mts = mach_task_self(); @@ -725,257 +958,368 @@ main(argc, argv) break; } } while (0); +#endif __APPLE__ - if (fflag && *argv) { - char *arg0 = *argv; - if (lflag) - (void)strlcpy(tbuf, (p = strrchr(*argv, '/')) ? - p + 1 : *argv, sizeof(tbuf)); - else { - tbuf[0] = '-'; - (void)strlcpy(tbuf + 1, (p = strrchr(*argv, '/')) ? - p + 1 : *argv, sizeof(tbuf) - 1); - } - *argv = tbuf; - execvp(arg0, argv); - err(1, "%s", arg0); - } else { - if (lflag) - (void)strlcpy(tbuf, (p = strrchr(pwd->pw_shell, '/')) ? - p + 1 : pwd->pw_shell, sizeof(tbuf)); - else { - tbuf[0] = '-'; - (void)strlcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? - p + 1 : pwd->pw_shell, sizeof(tbuf) - 1); - } - execlp(pwd->pw_shell, tbuf, (char *)NULL); - err(1, "%s", pwd->pw_shell); - } -} + if (!quietlog) { +#ifdef LOGIN_CAP + const char *cw; -#ifdef KERBEROS -#define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */ -#else -#define NBUFSIZ (MAXLOGNAME + 1) -#endif + cw = login_getcapstr(lc, "copyright", NULL, NULL); + if (cw == NULL || motd(cw) == -1) + (void)printf("%s", copyright); -/* - * The following tokens are included in the audit record for successful login attempts - * header - * subject - * return - */ -void au_success() -{ -#ifdef USE_BSM - token_t *tok; - int aufd; - au_mask_t aumask; - auditinfo_t auinfo; - uid_t uid = pwd->pw_uid; - gid_t gid = pwd->pw_gid; - pid_t pid = getpid(); - long au_cond; - - /* If we are not auditing, don't cut an audit record; just return */ - if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { - fprintf(stderr, "login: Could not determine audit condition\n"); - exit(1); - } - if (au_cond == AUC_NOAUDIT) - return; + (void)printf("\n"); - /* Compute and Set the user's preselection mask */ - if(au_user_mask(pwd->pw_name, &aumask) == -1) { - fprintf(stderr, "login: Could not set audit mask\n"); - exit(1); + cw = login_getcapstr(lc, "welcome", NULL, NULL); + if (cw != NULL && access(cw, F_OK) == 0) + motd(cw); + else + motd(_PATH_MOTDFILE); + + if (login_getcapbool(lc_user, "nocheckmail", 0) == 0 && + login_getcapbool(lc, "nocheckmail", 0) == 0) { +#else /* !LOGIN_CAP */ + motd(_PATH_MOTDFILE); + { +#endif /* !LOGIN_CAP */ + char *cx; + + /* $MAIL may have been set by class. */ + cx = getenv("MAIL"); + if (cx == NULL) { + asprintf(&cx, "%s/%s", + _PATH_MAILDIR, pwd->pw_name); + } + if (cx && stat(cx, &st) == 0 && st.st_size != 0) + (void)printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); + if (getenv("MAIL") == NULL) + free(cx); + } } - /* Set the audit info for the user */ - auinfo.ai_auid = uid; - auinfo.ai_asid = pid; - bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); - bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); - if(setaudit(&auinfo) != 0) { - fprintf(stderr, "login: setaudit failed: %s\n", strerror(errno)); - exit(1); - } +#ifdef LOGIN_CAP + login_close(lc_user); + login_close(lc); +#endif /* LOGIN_CAP */ - if((aufd = au_open()) == -1) { - fprintf(stderr, "login: Audit Error: au_open() failed\n"); - exit(1); - } + (void)signal(SIGALRM, SIG_DFL); + (void)signal(SIGQUIT, SIG_DFL); + (void)signal(SIGINT, SIG_DFL); + (void)signal(SIGTSTP, SIG_IGN); - /* The subject that is created (euid, egid of the current process) */ - if((tok = au_to_subject32(uid, geteuid(), getegid(), - uid, gid, pid, pid, &tid)) == NULL) { - fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); - exit(1); - } - au_write(aufd, tok); +#ifdef __APPLE__ + if (fflag && *argv) pwd->pw_shell = *argv; +#endif /* __APPLE__ */ - if((tok = au_to_return32(0, 0)) == NULL) { - fprintf(stderr, "login: Audit Error: au_to_return32() failed\n"); - exit(1); + /* + * Login shells have a leading '-' in front of argv[0] + */ + p = strrchr(pwd->pw_shell, '/'); +#ifdef __APPLE__ + if (asprintf(&arg0, "%s%s", lflag ? "" : "-", p ? p + 1 : pwd->pw_shell) >= MAXPATHLEN) { +#else /* __APPLE__ */ + if (asprintf(&arg0, "-%s", p ? p + 1 : pwd->pw_shell) >= MAXPATHLEN) { +#endif /* __APPLE__ */ + syslog(LOG_ERR, "user: %s: shell exceeds maximum pathname size", + username); + errx(1, "shell exceeds maximum pathname size"); + } else if (arg0 == NULL) { + err(1, "asprintf()"); } - au_write(aufd, tok); - if(au_close(aufd, 1, AUE_login) == -1) { - fprintf(stderr, "login: Audit Record was not committed.\n"); - exit(1); +#ifdef __APPLE__ + if (fflag && *argv) { + *argv = arg0; + execvp(pwd->pw_shell, argv); + err(1, "%s", arg0); } -#endif +#endif /* __APPLE__ */ + execlp(shell, arg0, (char *)0); + err(1, "%s", shell); + + /* + * That's it, folks! + */ } +#ifdef USE_PAM /* - * The following tokens are included in the audit record for successful login attempts - * header - * subject - * text - * return - */ -void au_fail(char *errmsg, int na) + * Attempt to authenticate the user using PAM. Returns 0 if the user is + * authenticated, or 1 if not authenticated. If some sort of PAM system + * error occurs (e.g., the "/etc/pam.conf" file is missing) then this + * function returns -1. This can be used as an indication that we should + * fall back to a different authentication mechanism. + */ +static int +auth_pam(void) { -#ifdef USE_BSM - token_t *tok; - int aufd; - long au_cond; - uid_t uid; - gid_t gid; - pid_t pid = getpid(); - - /* If we are not auditing, don't cut an audit record; just return */ - if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { - fprintf(stderr, "login: Could not determine audit condition\n"); - exit(1); - } - if (au_cond == AUC_NOAUDIT) - return; - - if((aufd = au_open()) == -1) { - fprintf(stderr, "login: Audit Error: au_open() failed\n"); - exit(1); - } + const char *tmpl_user; + const void *item; + int rval; - if(na) { - /* Non attributable event */ - /* Assuming that login is not called within a users' session => auid,asid == -1 */ - if((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, - pid, -1, &tid)) == NULL) { + pam_err = pam_authenticate(pamh, pam_silent); + switch (pam_err) { - fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); - exit(1); + case PAM_SUCCESS: + /* + * With PAM we support the concept of a "template" + * user. The user enters a login name which is + * authenticated by PAM, usually via a remote service + * such as RADIUS or TACACS+. If authentication + * succeeds, a different but related "template" name + * is used for setting the credentials, shell, and + * home directory. The name the user enters need only + * exist on the remote authentication server, but the + * template name must be present in the local password + * database. + * + * This is supported by two various mechanisms in the + * individual modules. However, from the application's + * point of view, the template user is always passed + * back as a changed value of the PAM_USER item. + */ + pam_err = pam_get_item(pamh, PAM_USER, &item); + if (pam_err == PAM_SUCCESS) { + tmpl_user = (const char *)item; + if (strcmp(username, tmpl_user) != 0) + pwd = getpwnam(tmpl_user); + } else { + pam_syslog("pam_get_item(PAM_USER)"); } + rval = 0; + break; + + case PAM_AUTH_ERR: + case PAM_USER_UNKNOWN: + case PAM_MAXTRIES: + rval = 1; + break; + + default: + pam_syslog("pam_authenticate()"); + rval = -1; + break; } - else { - /* we know the subject -- so use its value instead */ - uid = pwd->pw_uid; - gid = pwd->pw_gid; - if((tok = au_to_subject32(uid, geteuid(), getegid(), - uid, gid, pid, pid, &tid)) == NULL) { - fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); - exit(1); + + if (rval == 0) { + pam_err = pam_acct_mgmt(pamh, pam_silent); + switch (pam_err) { + case PAM_SUCCESS: + break; + case PAM_NEW_AUTHTOK_REQD: + pam_err = pam_chauthtok(pamh, + pam_silent|PAM_CHANGE_EXPIRED_AUTHTOK); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_chauthtok()"); + rval = 1; + } + break; + default: + pam_syslog("pam_acct_mgmt()"); + rval = 1; + break; } } - au_write(aufd, tok); - /* Include the error message */ - if((tok = au_to_text(errmsg)) == NULL) { - fprintf(stderr, "login: Audit Error: au_to_text() failed\n"); - exit(1); + if (rval != 0) { + pam_end(pamh, pam_err); + pamh = NULL; } - au_write(aufd, tok); + return (rval); +} - if((tok = au_to_return32(1, errno)) == NULL) { - fprintf(stderr, "login: Audit Error: au_to_return32() failed\n"); - exit(1); +/* + * Export any environment variables PAM modules may have set + */ +static void +export_pam_environment() +{ + char **pam_env; + char **pp; + + pam_env = pam_getenvlist(pamh); + if (pam_env != NULL) { + for (pp = pam_env; *pp != NULL; pp++) { + (void)export(*pp); + free(*pp); + } } - au_write(aufd, tok); +} - if(au_close(aufd, 1, AUE_login) == -1) { - fprintf(stderr, "login: Audit Error: au_close() was not committed\n"); - exit(1); +/* + * Perform sanity checks on an environment variable: + * - Make sure there is an '=' in the string. + * - Make sure the string doesn't run on too long. + * - Do not export certain variables. This list was taken from the + * Solaris pam_putenv(3) man page. + * Then export it. + */ +static int +export(const char *s) +{ + static const char *noexport[] = { + "SHELL", "HOME", "LOGNAME", "MAIL", "CDPATH", + "IFS", "PATH", NULL + }; + char *p; + const char **pp; + size_t n; + + if (strlen(s) > 1024 || (p = strchr(s, '=')) == NULL) + return (0); + if (strncmp(s, "LD_", 3) == 0) + return (0); + for (pp = noexport; *pp != NULL; pp++) { + n = strlen(*pp); + if (s[n] == '=' && strncmp(s, *pp, n) == 0) + return (0); } + *p = '\0'; + (void)setenv(s, p + 1, 1); + *p = '='; + return (1); +} +#endif /* USE_PAM */ + +static void +usage() +{ +#ifdef __APPLE__ + (void)fprintf(stderr, "usage: login [-pq] [-h hostname] [username]\n"); + (void)fprintf(stderr, " login -f [-lpq] [-h hostname] [username [prog [arg ...]]]\n"); +#else + (void)fprintf(stderr, "usage: login [-fp] [-h hostname] [username]\n"); #endif + exit(1); } -void +/* + * Prompt user and read login name from stdin. + */ +static char * getloginname() { + char *nbuf, *p; int ch; - char *p; - static char nbuf[NBUFSIZ]; - for (;;) { - (void)printf("login: "); + nbuf = malloc(MAXLOGNAME); + if (nbuf == NULL) + err(1, "malloc()"); + do { + (void)printf("%s", prompt); for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin(username); - exit(0); + bail(NO_SLEEP_EXIT, 0); } - if (p < nbuf + (NBUFSIZ - 1)) + if (p < nbuf + MAXLOGNAME - 1) *p++ = ch; } - if (p > nbuf) { - if (nbuf[0] == '-') - (void)fprintf(stderr, - "login names may not start with '-'.\n"); - else { - *p = '\0'; - username = nbuf; - break; - } - } + } while (p == nbuf); + + *p = '\0'; + if (nbuf[0] == '-') { +#ifdef USE_PAM + pam_silent = 0; +#endif /* USE_PAM */ + memmove(nbuf, nbuf + 1, strlen(nbuf)); + } else { +#ifdef USE_PAM + pam_silent = PAM_SILENT; +#endif /* USE_PAM */ } + return nbuf; } -int -rootterm(ttyn) - char *ttyn; +#ifdef __APPLE__ +#ifndef USE_PAM +static int +rootterm(const char* ttyn) { struct ttyent *t; - return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); } +#endif /* !USE_PAM */ +#endif /* __APPLE__ */ -jmp_buf motdinterrupt; +/* + * SIGINT handler for motd(). + */ +static volatile int motdinterrupt; +static void +sigint(int signo __unused) +{ + motdinterrupt = 1; +} -void -motd() +/* + * Display the contents of a file (such as /etc/motd). + */ +static int +motd(const char *motdfile) { - int fd, nchars; sig_t oldint; - char tbuf[8192]; + FILE *f; + int ch; - if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) - return; + if ((f = fopen(motdfile, "r")) == NULL) + return (-1); + motdinterrupt = 0; oldint = signal(SIGINT, sigint); - if (setjmp(motdinterrupt) == 0) - while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) - (void)write(fileno(stdout), tbuf, nchars); - (void)signal(SIGINT, oldint); - (void)close(fd); + while ((ch = fgetc(f)) != EOF && !motdinterrupt) + putchar(ch); + signal(SIGINT, oldint); + if (ch != EOF || ferror(f)) { + fclose(f); + return (-1); + } + fclose(f); + return (0); } -/* ARGSUSED */ -void -sigint(signo) - int signo; +/* + * SIGHUP handler + * Forwards the SIGHUP to the child process and current process group. + */ +static void +handle_sighup(int signo) { - - longjmp(motdinterrupt, 1); + if (pid > 0) { + /* close the controlling terminal */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + /* Ignore SIGHUP to avoid tail-recursion on signaling + the current process group (of which we are a member). */ + (void)signal(SIGHUP, SIG_IGN); + /* Forward the signal to the current process group. */ + (void)kill(0, signo); + /* Forward the signal to the child if not a member of the current + * process group . */ + if (getpgid(pid) != getpgrp()) { + (void)kill(pid, signo); + } + } } -/* ARGSUSED */ -void -timedout(signo) - int signo; +/* + * SIGALRM handler, to enforce login prompt timeout. + * + * XXX This can potentially confuse the hell out of PAM. We should + * XXX instead implement a conversation function that returns + * XXX PAM_CONV_ERR when interrupted by a signal, and have the signal + * XXX handler just set a flag. + */ +static void +timedout(int signo __unused) { - (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); - exit(0); + longjmp(timeout_buf, signo); } +#ifdef __APPLE__ +#ifndef USE_PAM void checknologin() { @@ -985,10 +1329,14 @@ checknologin() if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) (void)write(fileno(stdout), tbuf, nchars); - au_fail("No login", 0); - sleepexit(0); +#ifdef USE_BSM_AUDIT + au_login_fail("No login", 0); +#endif + sleep(5); + exit(0); } } +#endif /* !USE_PAM */ void dolastlog(quiet) @@ -1010,56 +1358,31 @@ dolastlog(quiet) lastlog.ll_line); } #else /* !USE_PAM */ - struct lastlog ll; - int fd; - - /* HACK HACK HACK: This is because HFS doesn't support sparse files - * and seeking into the file too far is too slow. The "solution" - * is to just bail if the seek time for a large uid would be too - * slow. - */ - if(pwd->pw_uid > 100000) { - syslog(LOG_NOTICE, "User login %s (%d) not logged in lastlog. UID too large.", pwd->pw_name, pwd->pw_uid); - return; - } + struct lastlogx ll; - if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { - (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); - if (!quiet) { - if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && - ll.ll_time != 0) { - (void)printf("Last login: %.*s ", - 24-5, (char *)ctime(&ll.ll_time)); - if (*ll.ll_host != '\0') - (void)printf("from %.*s\n", - (int)sizeof(ll.ll_host), - ll.ll_host); - else - (void)printf("on %.*s\n", - (int)sizeof(ll.ll_line), - ll.ll_line); - } - (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); - } - memset((void *)&ll, 0, sizeof(ll)); - (void)time(&ll.ll_time); - (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); - if (hostname) - (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); - (void)write(fd, (char *)&ll, sizeof(ll)); - (void)close(fd); + if(!quiet && getlastlogx(pwd->pw_uid, &ll) != NULL) { + (void)printf("Last login: %.*s ", + 24-5, (char *)ctime(&ll.ll_tv.tv_sec)); + if (*ll.ll_host != '\0') + (void)printf("from %.*s\n", + (int)sizeof(ll.ll_host), + ll.ll_host); + else + (void)printf("on %.*s\n", + (int)sizeof(ll.ll_line), + ll.ll_line); } #endif /* USE_PAM */ } +#endif /* __APPLE__ */ -void -badlogin(name) - char *name; +static void +badlogin(char *name) { if (failures == 0) return; - if (hostname) { + if (hflag) { syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", failures, failures > 1 ? "S" : "", hostname); syslog(LOG_AUTHPRIV|LOG_NOTICE, @@ -1072,43 +1395,36 @@ badlogin(name) "%d LOGIN FAILURE%s ON %s, %s", failures, failures > 1 ? "S" : "", tty, name); } + failures = 0; } -#undef UNKNOWN -#define UNKNOWN "su" - -char * -stypeof(ttyid) - char *ttyid; +const char * +stypeof(char *ttyid) { struct ttyent *t; - return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); -} - -void -sleepexit(eval) - int eval; -{ - - (void)sleep(5); - exit(eval); + if (ttyid != NULL && *ttyid != '\0') { + t = getttynam(ttyid); + if (t != NULL && t->ty_type != NULL) + return (t->ty_type); + } + return (NULL); } static void refused(const char *msg, const char *rtype, int lout) { - if (msg != NULL) - printf("%s.\n", msg); - if (hflag) - syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s", - pwd->pw_name, rtype, hostname, tty); - else - syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) ON TTY %s", - pwd->pw_name, rtype, tty); - if (lout) - bail(SLEEP_EXIT, 1); + if (msg != NULL) + printf("%s.\n", msg); + if (hflag) + syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s", + pwd->pw_name, rtype, hostname, tty); + else + syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) ON TTY %s", + pwd->pw_name, rtype, tty); + if (lout) + bail(SLEEP_EXIT, 1); } #ifdef USE_PAM @@ -1118,7 +1434,7 @@ refused(const char *msg, const char *rtype, int lout) static void pam_syslog(const char *msg) { - syslog(LOG_ERR, "%s: %s", msg, pam_strerror(pamh, pam_err)); + syslog(LOG_ERR, "%s: %s", msg, pam_strerror(pamh, pam_err)); } /* @@ -1128,33 +1444,39 @@ static void pam_cleanup() { - if (pamh != NULL) { - if (pam_session_established) { - pam_err = pam_close_session(pamh, 0); - if (pam_err != PAM_SUCCESS) - pam_syslog("pam_close_session()"); - } - pam_session_established = 0; - if (pam_cred_established) { - pam_err = pam_setcred(pamh, pam_silent|PAM_DELETE_CRED); - if (pam_err != PAM_SUCCESS) - pam_syslog("pam_setcred()"); - } - pam_cred_established = 0; - pam_end(pamh, pam_err); - pamh = NULL; - } + if (pamh != NULL) { + if (pam_session_established) { + pam_err = pam_close_session(pamh, 0); + if (pam_err != PAM_SUCCESS) + pam_syslog("pam_close_session()"); + } + pam_session_established = 0; + if (pam_cred_established) { + pam_err = pam_setcred(pamh, pam_silent|PAM_DELETE_CRED); + if (pam_err != PAM_SUCCESS) + pam_syslog("pam_setcred()"); + } + pam_cred_established = 0; + pam_end(pamh, pam_err); + pamh = NULL; + } } #endif /* USE_PAM */ + /* * Exit, optionally after sleeping a few seconds */ void bail(int sec, int eval) { + #ifdef USE_PAM - pam_cleanup(); + pam_cleanup(); +#endif /* USE_PAM */ +#ifdef USE_BSM_AUDIT + if (pwd != NULL) + audit_logout(); #endif - (void)sleep(sec); - exit(eval); + (void)sleep(sec); + exit(eval); } diff --git a/login.tproj/login.h b/login.tproj/login.h new file mode 100644 index 0000000..1d0e72e --- /dev/null +++ b/login.tproj/login.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2001 FreeBSD, Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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/login/login.h,v 1.7 2007/05/07 11:01:36 dwmalone Exp $ + */ + +void login_fbtab(char *, uid_t, gid_t); + +#ifdef USE_BSM_AUDIT +void au_login_success(void); +void au_login_fail(const char *errmsg, int na); +void audit_logout(void); +#endif + +extern char **environ; +extern struct passwd *pwd; diff --git a/login.tproj/login.pam b/login.tproj/login.pam new file mode 100644 index 0000000..494813a --- /dev/null +++ b/login.tproj/login.pam @@ -0,0 +1,11 @@ +# login: auth account password session +auth optional pam_krb5.so +auth optional pam_mount.so +auth sufficient pam_serialnumber.so serverinstall legacy +auth required pam_opendirectory.so +account required pam_nologin.so +account required pam_opendirectory.so +password required pam_deny.so +session required pam_launchd.so +session required pam_uwtmp.so +session optional pam_mount.so diff --git a/login.tproj/login_audit.c b/login.tproj/login_audit.c new file mode 100644 index 0000000..4f6bb9d --- /dev/null +++ b/login.tproj/login_audit.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. + * All rights reserved. + * + * @APPLE_BSD_LICENSE_HEADER_START@ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce 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 Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @APPLE_BSD_LICENSE_HEADER_END@ + */ + +#include +__FBSDID("$FreeBSD: src/usr.bin/login/login_audit.c,v 1.2 2007/05/07 11:01:36 dwmalone Exp $"); + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "login.h" + +/* + * Audit data + */ +static au_tid_t tid; + +/* + * The following tokens are included in the audit record for a successful + * login: header, subject, return. + */ +void +au_login_success(void) +{ + token_t *tok; + int aufd; + au_mask_t aumask; + auditinfo_t auinfo; + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; + pid_t pid = getpid(); + long au_cond; + + /* If we are not auditing, don't cut an audit record; just return. */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno == ENOSYS) + return; + errx(1, "login: Could not determine audit condition"); + } + if (au_cond == AUC_NOAUDIT) + return; + + /* Compute and set the user's preselection mask. */ + if (au_user_mask(pwd->pw_name, &aumask) == -1) + errx(1, "login: Could not set audit mask\n"); + + /* Set the audit info for the user. */ + auinfo.ai_auid = uid; + auinfo.ai_asid = pid; + bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); + bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); + if (setaudit(&auinfo) != 0) + err(1, "login: setaudit failed"); + + if ((aufd = au_open()) == -1) + errx(1,"login: Audit Error: au_open() failed"); + + if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, + pid, &tid)) == NULL) + errx(1, "login: Audit Error: au_to_subject32() failed"); + au_write(aufd, tok); + + if ((tok = au_to_return32(0, 0)) == NULL) + errx(1, "login: Audit Error: au_to_return32() failed"); + au_write(aufd, tok); + + if (au_close(aufd, 1, AUE_login) == -1) + errx(1, "login: Audit Record was not committed."); +} + +/* + * The following tokens are included in the audit record for failed + * login attempts: header, subject, text, return. + */ +void +au_login_fail(const char *errmsg, int na) +{ + token_t *tok; + int aufd; + long au_cond; + uid_t uid; + gid_t gid; + pid_t pid = getpid(); + + /* If we are not auditing, don't cut an audit record; just return. */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno == ENOSYS) + return; + errx(1, "login: Could not determine audit condition"); + } + if (au_cond == AUC_NOAUDIT) + return; + + if ((aufd = au_open()) == -1) + errx(1, "login: Audit Error: au_open() failed"); + + if (na) { + /* + * Non attributable event. Assuming that login is not called + * within a user's session => auid,asid == -1. + */ + if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, + pid, -1, &tid)) == NULL) + errx(1, "login: Audit Error: au_to_subject32() failed"); + } else { + /* We know the subject -- so use its value instead. */ + uid = pwd->pw_uid; + gid = pwd->pw_gid; + if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, + gid, pid, pid, &tid)) == NULL) + errx(1, "login: Audit Error: au_to_subject32() failed"); + } + au_write(aufd, tok); + + /* Include the error message. */ + if ((tok = au_to_text(errmsg)) == NULL) + errx(1, "login: Audit Error: au_to_text() failed"); + au_write(aufd, tok); + + if ((tok = au_to_return32(1, errno)) == NULL) + errx(1, "login: Audit Error: au_to_return32() failed"); + au_write(aufd, tok); + + if (au_close(aufd, 1, AUE_login) == -1) + errx(1, "login: Audit Error: au_close() was not committed"); +} + +/* + * The following tokens are included in the audit record for a logout: + * header, subject, return. + */ +void +audit_logout(void) +{ + token_t *tok; + int aufd; + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; + pid_t pid = getpid(); + long au_cond; + + /* If we are not auditing, don't cut an audit record; just return. */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (errno == ENOSYS) + return; + errx(1, "login: Could not determine audit condition"); + } + if (au_cond == AUC_NOAUDIT) + return; + + if ((aufd = au_open()) == -1) + errx(1, "login: Audit Error: au_open() failed"); + + /* The subject that is created (euid, egid of the current process). */ + if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, + pid, &tid)) == NULL) + errx(1, "login: Audit Error: au_to_subject32() failed"); + au_write(aufd, tok); + + if ((tok = au_to_return32(0, 0)) == NULL) + errx(1, "login: Audit Error: au_to_return32() failed"); + au_write(aufd, tok); + + if (au_close(aufd, 1, AUE_logout) == -1) + errx(1, "login: Audit Record was not committed."); +} diff --git a/login.tproj/pathnames.h b/login.tproj/pathnames.h index b83bb9b..96da87e 100644 --- a/login.tproj/pathnames.h +++ b/login.tproj/pathnames.h @@ -1,27 +1,42 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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/9/93 + * $FreeBSD: src/usr.bin/login/pathnames.h,v 1.6 2006/03/06 12:38:42 yar Exp $ */ + #include -#define _PATH_HUSHLOGIN ".hushlogin" -#define _PATH_MOTDFILE "/etc/motd" +#define _PATH_HUSHLOGIN ".hushlogin" +#define _PATH_MOTDFILE "/etc/motd" +#define _PATH_FBTAB "/etc/fbtab" +#define _PATH_LOGINDEVPERM "/etc/logindevperm" diff --git a/makekey.tproj/Makefile b/makekey.tproj/Makefile index 619e6e2..c35c1f3 100644 --- a/makekey.tproj/Makefile +++ b/makekey.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/libexec CFILES = makekey.c MANPAGES = makekey.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/mkfile.tproj/Makefile b/mkfile.tproj/Makefile index 2e16616..7ca1598 100644 --- a/mkfile.tproj/Makefile +++ b/mkfile.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/sbin CFILES = mkfile.c MANPAGES = mkfile.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/mkfile.tproj/mkfile.c b/mkfile.tproj/mkfile.c index 0965ef5..19eadb9 100644 --- a/mkfile.tproj/mkfile.c +++ b/mkfile.tproj/mkfile.c @@ -57,11 +57,12 @@ main (argc, argv) char *b_num, *prog_name; char *options = "nv"; char c; - quad_t multiplier = 1; - quad_t file_size; + off_t multiplier = 1; + off_t file_size; int len; int empty = 0; int verbose = 0; + char* endptr = NULL; prog_name = argv[0]; /* Get program name */ if (1 == argc) @@ -118,8 +119,10 @@ main (argc, argv) if (*argv == NULL) /* Was a file name given? */ usage(prog_name, options); - if ((file_size = strtoq(b_num, NULL, 10)) == 0 ) + if ((file_size = strtoll(b_num, &endptr, 10)) == 0 && + (*endptr != 0 && endptr != &b_num[len])) { err(1, "Bad file size!"); + } while ( *argv != NULL ) { /* Create file for each file_name */ create_file(*argv, file_size*multiplier, empty, verbose); diff --git a/newgrp.tproj/Makefile b/newgrp.tproj/Makefile index 6f9b314..65aa49d 100644 --- a/newgrp.tproj/Makefile +++ b/newgrp.tproj/Makefile @@ -4,7 +4,9 @@ Install_Dir = /usr/bin CFILES = newgrp.c MANPAGES = newgrp.1 -Extra_CC_Flags = -D__FBSDID=__RCSID +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID +Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/newgrp.tproj/newgrp.1 b/newgrp.tproj/newgrp.1 index 2051365..af36e19 100644 --- a/newgrp.tproj/newgrp.1 +++ b/newgrp.tproj/newgrp.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/usr.bin/newgrp/newgrp.1,v 1.2 2002/05/30 13:57:35 ru Exp $ +.\" $FreeBSD: src/usr.bin/newgrp/newgrp.1,v 1.3 2005/01/17 07:44:25 ru Exp $ .\" .Dd May 23, 2002 .Dt NEWGRP 1 @@ -31,43 +31,43 @@ .Nm newgrp .Nd change to a new group .Sh SYNOPSIS -.Nm newgrp +.Nm .Op Fl l .Op Ar group .Sh DESCRIPTION The -.Nm newgrp -utility creates a new shell execution environment -with modified real and effective group IDs. +.Nm +utility creates a new shell execution environment with modified +real and effective group IDs. .Pp The options are as follows: .Bl -tag -width indent .It Fl l Simulate a full login. -The environment and umask are set to what would be expected -if the user actually logged in again. +The environment and umask are set to what would be expected if the user +actually logged in again. .El .Pp If the .Ar group -operand is present, a new shell is started -with the specified effective and real group IDs. -The user will be prompted for a password -if they are not a member of the specified group. +operand is present, a new shell is started with the specified effective +and real group IDs. +The user will be prompted for a password if they are not a member of the +specified group. .Pp -Otherwise, the real, effective, and supplementary group IDs -are restored to those from the current user's password database entry. -.Sh DIAGNOSTICS +Otherwise, the real, effective and supplementary group IDs are restored to +those from the current user's password database entry. +.Sh EXIT STATUS The -.Nm newgrp +.Nm utility attempts to start the shell regardless of whether group IDs were successfully changed. .Pp If an error occurs and the shell cannot be started, -.Nm newgrp +.Nm exits >0. Otherwise, the exit status of -.Nm newgrp +.Nm is the exit status of the shell. .Sh SEE ALSO .Xr csh 1 , @@ -81,16 +81,15 @@ is the exit status of the shell. .Xr environ 7 .Sh STANDARDS The -.Nm newgrp +.Nm utility conforms to .St -p1003.1-2001 . .Sh HISTORY A -.Nm newgrp +.Nm utility appeared in .At v6 . .Sh BUGS -Group passwords are inherently insecure, -as there is no way to stop users obtaining the encrypted passwords -from the group database. +Group passwords are inherently insecure as there is no way to stop +users obtaining the crypted passwords from the group database. Their use is discouraged. diff --git a/newgrp.tproj/newgrp.c b/newgrp.tproj/newgrp.c index 75bc63a..4c31fb7 100644 --- a/newgrp.tproj/newgrp.c +++ b/newgrp.tproj/newgrp.c @@ -260,6 +260,7 @@ loginshell(void) { char *args[2], **cleanenv, *term, *ticket; const char *shell; + char *prog, progbuf[PATH_MAX]; #ifndef __APPLE__ login_cap_t *lc; #endif /* !__APPLE__ */ @@ -292,7 +293,10 @@ loginshell(void) if (ticket != NULL) setenv("KRBTKFILE", ticket, 1); - if (asprintf(args, "-%s", basename(shell)) < 0) + strlcpy(progbuf, shell, sizeof(progbuf)); + prog = basename(progbuf); + + if (asprintf(args, "-%s", prog) < 0) err(1, "asprintf"); args[1] = NULL; @@ -304,10 +308,15 @@ static void doshell(void) { const char *shell; + char *prog, progbuf[PATH_MAX]; shell = pwd->pw_shell; if (*shell == '\0') shell = _PATH_BSHELL; - execl(shell, basename(shell), (char *)NULL); + + strlcpy(progbuf, shell, sizeof(progbuf)); + prog = basename(progbuf); + + execl(shell, prog, (char *)NULL); err(1, "%s", shell); } diff --git a/nologin.tproj/Makefile b/nologin.tproj/Makefile index d38cd3b..7332134 100644 --- a/nologin.tproj/Makefile +++ b/nologin.tproj/Makefile @@ -1,9 +1,11 @@ Project = nologin Install_Dir = /sbin -MANPAGES = nologin.8 +CFILES = nologin.c +MANPAGES = nologin.5 nologin.8 -include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID +Extra_LD_Flags = -dead_strip -after_install: - $(INSTALL_SCRIPT) nologin.sh $(DSTROOT)/$(Install_Dir)/nologin +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/kvm_mkdb.tproj/kvm_mkdb.8 b/nologin.tproj/nologin.5 similarity index 55% rename from kvm_mkdb.tproj/kvm_mkdb.8 rename to nologin.tproj/nologin.5 index c68340a..da3b73e 100644 --- a/kvm_mkdb.tproj/kvm_mkdb.8 +++ b/nologin.tproj/nologin.5 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1989, 1991, 1993 +.\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with 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. @@ -29,42 +25,72 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)kvm_mkdb.8 8.1 (Berkeley) 6/9/93 +.\" @(#)nologin.8 8.1 (Berkeley) 6/19/93 +.\" $FreeBSD: src/usr.sbin/nologin/nologin.5,v 1.15 2007/05/10 11:22:24 yar Exp $ .\" -.Dd June 9, 1993 -.Dt KVM_MKDB 8 +.Dd May 10, 2007 +.Dt NOLOGIN 5 .Os .Sh NAME -.Nm kvm_mkdb -.Nd create kernel database -.Sh SYNOPSIS -.Nm kvm_mkdb -.Op file +.Nm nologin +.Nd disallow logins .Sh DESCRIPTION -.Nm Kvm_mkdb -creates a database in -.Pa /var/db , -containing information about the specified file. -If no file is specified, -.Pa /vmunix -is used by default. -The file is named ``kvm_filename.db'', where ``filename'' is the -name of the file read. -Various library routines consult this database. +Programs such as +.Xr login 1 +disallow logins if the +.Nm +file exists. +The programs display the contents of +.Nm +to the user if possible and interrupt the login sequence. +This makes it simple to temporarily prevent incoming logins systemwide. .Pp -The only information currently stored is the kernel namelist, which is -used by the -.Xr kvm_nlist 3 -function, however, in the future the database may contain other static -information about the current system. +To disable logins on a per-account basis, +investigate +.Xr nologin 8 . +.Sh SECURITY +The +.Nm +file is ignored for user root by default. +.Sh IMPLEMENTATION NOTES +The +.Nm +feature is implemented through +.Xr login.conf 5 , +which allows to change the pathname of the +file and to extend the list of users +exempt from temporary login restriction. +.Pp +PAM-aware programs can be selectively configured to respect +.Nm +using the +.Xr pam_nologin 8 +module via +.Xr pam.conf 5 . +.Pp +The +.Nm +file will be removed at system boot if it resides in +.Pa /var/run +and +.Va cleanvar_enable +is set to +.Dq Li YES +in +.Xr rc.conf 5 , +which is default. +Therefore system reboot can effectively re-enable logins. .Sh FILES -.Bl -tag -width /var/db/kvm_vmunix.db -compact -.It Pa /vmunix -.It Pa /var/db/kvm_vmunix.db +.Bl -tag -width ".Pa /var/run/nologin" -compact +.It Pa /var/run/nologin +default location of +.Nm .El .Sh SEE ALSO -.Xr kvm_nlist 3 -.Sh HISTORY -The -.Nm kvm_mkdb -utility first appeared in 4.4BSD. +.Xr login 1 , +.Xr login.conf 5 , +.Xr pam.conf 5 , +.Xr rc.conf 5 , +.Xr nologin 8 , +.Xr pam_nologin 8 , +.Xr shutdown 8 diff --git a/nologin.tproj/nologin.8 b/nologin.tproj/nologin.8 index e2052a2..04078ff 100644 --- a/nologin.tproj/nologin.8 +++ b/nologin.tproj/nologin.8 @@ -1,6 +1,3 @@ -.\" $OpenBSD: nologin.8,v 1.3 1997/02/16 04:15:32 downsj Exp $ -.\" $NetBSD: nologin.8,v 1.3 1995/03/18 14:59:09 cgd Exp $ -.\" .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -12,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with 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. @@ -33,31 +26,32 @@ .\" SUCH DAMAGE. .\" .\" @(#)nologin.8 8.1 (Berkeley) 6/19/93 +.\" $FreeBSD: src/usr.sbin/nologin/nologin.8,v 1.14 2004/08/07 04:27:52 imp Exp $ .\" -.Dd February 15, 1997 +.Dd June 19, 1993 .Dt NOLOGIN 8 .Os .Sh NAME .Nm nologin -.Nd politely refuse a login +.Nd politely refuse a login .Sh SYNOPSIS -.Nm nologin +.Nm .Sh DESCRIPTION -.Nm Nologin -displays a message that an account is not available and +The +.Nm +utility displays a message that an account is not available and exits non-zero. It is intended as a replacement shell field for accounts that have been disabled. .Pp -If the file -.Pa /etc/nologin.txt -exists, -.Nm nologin -displays its contents (instead of the default message) to the user. +To disable all logins, +investigate +.Xr nologin 5 . .Sh SEE ALSO -.Xr login 1 +.Xr login 1 , +.Xr nologin 5 .Sh HISTORY The -.Nm nologin -command appeared in +.Nm +utility appeared in .Bx 4.4 . diff --git a/nologin.tproj/nologin.c b/nologin.tproj/nologin.c new file mode 100644 index 0000000..788c90f --- /dev/null +++ b/nologin.tproj/nologin.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2004 The FreeBSD Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/usr.sbin/nologin/nologin.c,v 1.6 2005/01/04 20:07:12 delphij Exp $"); + +#include +#include +#include + +#define MESSAGE "This account is currently not available.\n" + +int +main(__unused int argc, __unused char *argv[]) +{ + const char *user, *tt; + + if ((tt = ttyname(0)) == NULL) + tt = "UNKNOWN"; + if ((user = getlogin()) == NULL) + user = "UNKNOWN"; + openlog("nologin", LOG_CONS, LOG_AUTH); + syslog(LOG_CRIT, "Attempted login by %s on %s", user, tt); + closelog(); + + printf("%s", MESSAGE); + return 1; +} diff --git a/nologin.tproj/nologin.sh b/nologin.tproj/nologin.sh deleted file mode 100644 index 8ad87fb..0000000 --- a/nologin.tproj/nologin.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# -# 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. -# -# @(#)nologin.sh 8.1 (Berkeley) 6/5/93 -# - -echo 'This account is currently not available.' -exit 1 diff --git a/nvram.tproj/Makefile b/nvram.tproj/Makefile index b54374b..5689c52 100644 --- a/nvram.tproj/Makefile +++ b/nvram.tproj/Makefile @@ -4,6 +4,9 @@ Install_Dir = /usr/sbin CFILES = nvram.c MANPAGES = nvram.8 +Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_LD_Flags = -dead_strip + Extra_Frameworks = -framework CoreFoundation -framework IOKit include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index fc9a242..26e486f 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -27,10 +27,10 @@ cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall #include #include #include +#include +#include // Prototypes -static void Error(char *format, long item); -static void FatalError(long exitValue, char *format, long item); static void UsageMessage(char *message); static void ParseFile(char *fileName); static void ParseXMLFile(char *fileName); @@ -66,14 +66,13 @@ int main(int argc, char **argv) result = IOMasterPort(bootstrap_port, &masterPort); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) getting the IOMaster port", result); - exit(-1); + errx(1, "Error getting the IOMaster port: %s", + mach_error_string(result)); } gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options"); if (gOptionsRef == 0) { - FatalError(-1, "nvram is not supported on this system.", -1); - exit(-1); + errx(1, "nvram is not supported on this system"); } for (cnt = 1; cnt < argc; cnt++) { @@ -129,40 +128,13 @@ int main(int argc, char **argv) return 0; } - -// Error(format, item) -// -// Print a message on standard error. -// -static void Error(char *format, long item) -{ - fprintf(stderr, "%s: ", gToolName); - fprintf(stderr, format, item); - fprintf(stderr, "\n"); -} - - -// FatalError(exitValue, format, item) -// -// Print a message on standard error and exit with value. -// -static void FatalError(long exitValue, char *format, long item) -{ - fprintf(stderr, "%s: ", gToolName); - fprintf(stderr, format, item); - fprintf(stderr, "\n"); - - exit(exitValue); -} - - // UsageMessage(message) // // Print the usage information and exit. // static void UsageMessage(char *message) { - Error("(usage: %s)", (long)message); + warnx("(usage: %s)", message); printf("%s [-x] [-p] [-f filename] [-d name] name[=value] ...\n", gToolName); printf("\t-x use XML format for printing or reading variables\n"); @@ -205,6 +177,7 @@ static void ParseFile(char *fileName) char name[kMaxNameSize]; char value[kMaxStringSize]; FILE *patches; + kern_return_t kret; if (gUseXML) { ParseXMLFile(fileName); @@ -213,15 +186,15 @@ static void ParseFile(char *fileName) patches = fopen(fileName, "r"); if (patches == 0) { - FatalError(errno, "Couldn't open patch file - '%s'", (long)fileName); + err(1, "Couldn't open patch file - '%s'", fileName); } state = kFirstColumn; while ((tc = getc(patches)) != EOF) { if(ni==(kMaxNameSize-1)) - FatalError(-1,"Name exceeded max length of %d",kMaxNameSize); + errx(1, "Name exceeded max length of %d", kMaxNameSize); if(vi==(kMaxStringSize-1)) - FatalError(-1,"Value exceeded max length of %d",kMaxStringSize); + errx(1, "Value exceeded max length of %d", kMaxStringSize); switch (state) { case kFirstColumn : ni = 0; @@ -260,7 +233,7 @@ static void ParseFile(char *fileName) case kCollectName : if (tc == '\n') { name[ni] = 0; - Error("Name must be followed by white space - '%s'", (long)name); + warnx("Name must be followed by white space - '%s'", name); state = kFirstColumn; } else if (isspace(tc)) { state = kFindValue; @@ -300,15 +273,16 @@ static void ParseFile(char *fileName) if (state == kSetenv) { name[ni] = 0; value[vi] = 0; - if (SetOFVariable(name, value) != KERN_SUCCESS) { - FatalError(-1, "Error (-1) setting variable - '%s'", (long)name); + if ((kret = SetOFVariable(name, value)) != KERN_SUCCESS) { + errx(1, "Error setting variable - '%s': %s", name, + mach_error_string(kret)); } state = kFirstColumn; } } if (state != kFirstColumn) { - FatalError(-1, "Last line ended abruptly", 0); + errx(1, "Last line ended abruptly"); } } @@ -329,7 +303,7 @@ static void ParseXMLFile(char *fileName) filePath = CFStringCreateWithCString(kCFAllocatorDefault, fileName, kCFStringEncodingUTF8); if (filePath == NULL) { - FatalError(-1, "Could not create file path string", 0); + errx(1, "Could not create file path string"); } // Create a URL that specifies the file we will create to @@ -339,7 +313,7 @@ static void ParseXMLFile(char *fileName) kCFURLPOSIXPathStyle, false /* not a directory */ ); if (fileURL == NULL) { - FatalError(-1, "Could not create file path URL", 0); + errx(1, "Could not create file path URL"); } CFRelease(filePath); @@ -351,7 +325,7 @@ static void ParseXMLFile(char *fileName) NULL, NULL, &errorCode) || data == NULL ) { - FatalError(-1, "Error reading XML file (%d)", errorCode); + errx(1, "Error reading XML file (%d)", errorCode); } CFRelease(fileURL); @@ -364,11 +338,11 @@ static void ParseXMLFile(char *fileName) CFRelease(data); if (plist == NULL) { - FatalError(-1, "Error parsing XML file", 0); + errx(1, "Error parsing XML file"); } if (errorString != NULL) { - FatalError(-1, "Error parsing XML file: %s", (long)CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8)); + errx(1, "Error parsing XML file: %s", CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8)); } CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0); @@ -409,12 +383,14 @@ static void SetOrGetOFVariable(char *str) result = SetOFVariable(name, value); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (-1) setting variable - '%s'", (long)name); + errx(1, "Error setting variable - '%s': %s", name, + mach_error_string(result)); } } else { result = GetOFVariable(name, &nameRef, &valueRef); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (-1) getting variable - '%s'", (long)name); + errx(1, "Error getting variable - '%s': %s", name, + mach_error_string(result)); } PrintOFVariable(nameRef, valueRef, 0); @@ -435,11 +411,11 @@ static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef, *nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if (*nameRef == 0) { - FatalError(-1, "Error (-1) creating CFString for key %s", (long)name); + errx(1, "Error creating CFString for key %s", name); } *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0); - if (*valueRef == 0) return -1; + if (*valueRef == 0) return kIOReturnNotFound; return KERN_SUCCESS; } @@ -454,12 +430,12 @@ static kern_return_t SetOFVariable(char *name, char *value) CFStringRef nameRef; CFTypeRef valueRef; CFTypeID typeID; - kern_return_t result; + kern_return_t result = KERN_SUCCESS; nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if (nameRef == 0) { - FatalError(-1, "Error (-1) creating CFString for key %s", (long)name); + errx(1, "Error creating CFString for key %s", name); } valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, nameRef, 0, 0); @@ -469,7 +445,7 @@ static kern_return_t SetOFVariable(char *name, char *value) valueRef = ConvertValueToCFTypeRef(typeID, value); if (valueRef == 0) { - FatalError(-1, "Error (-1) creating CFTypeRef for value %s",(long)value); + errx(1, "Error creating CFTypeRef for value %s", value); } result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); } else { while (1) { @@ -499,7 +475,6 @@ static kern_return_t SetOFVariable(char *name, char *value) if (result == KERN_SUCCESS) break; } - result = -1; break; } } @@ -532,7 +507,7 @@ static void PrintOFVariables() result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) getting the firmware variables", result); + errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); } if (gUseXML) { @@ -540,7 +515,7 @@ static void PrintOFVariables() data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict ); if (data == NULL) { - FatalError(-1, "Error (%d) converting variables to xml", result); + errx(1, "Error converting variables to xml"); } fwrite(CFDataGetBytePtr(data), sizeof(UInt8), CFDataGetLength(data), stdout); @@ -582,7 +557,7 @@ static void PrintOFVariable(const void *key, const void *value, void *context) if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) ) nameString = nameBuffer; else { - Error("Error (-1) Unable to convert property name to C string", 0); + warnx("Unable to convert property name to C string"); nameString = ""; } @@ -604,7 +579,7 @@ static void PrintOFVariable(const void *key, const void *value, void *context) if ( valueBuffer && CFStringGetCString(value, valueBuffer, valueLen, kCFStringEncodingUTF8) ) valueString = valueBuffer; else { - Error("Error (-1) Unable to convert value to C string", 0); + warnx("Unable to convert value to C string"); valueString = ""; } } else if (typeID == CFDataGetTypeID()) { @@ -649,7 +624,7 @@ static void ClearOFVariables(void) result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) getting the firmware variables", result); + errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); } CFDictionaryApplyFunction(dict, &ClearOFVariable, 0); @@ -662,7 +637,7 @@ static void ClearOFVariable(const void *key, const void *value, void *context) result = IORegistryEntrySetCFProperty(gOptionsRef, CFSTR(kIONVRAMDeletePropertyKey), key); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) clearing firmware variables", result); + errx(1, "Error clearing firmware variables: %s", mach_error_string(result)); } } @@ -723,9 +698,10 @@ static void SetOFVariableFromFile(const void *key, const void *value, void *cont if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) ) nameString = nameBuffer; else { - Error("Error (-1) Unable to convert property name to C string", 0); + warnx("Unable to convert property name to C string"); nameString = ""; } - FatalError(-1, "Error (-1) setting variable - '%s'", (long)nameString); + errx(1, "Error setting variable - '%s': %s", nameString, + mach_error_string(result)); } } diff --git a/pagesize.tproj/pagesize.1 b/pagesize.tproj/pagesize.1 index 4beec29..bf987d0 100644 --- a/pagesize.tproj/pagesize.1 +++ b/pagesize.tproj/pagesize.1 @@ -30,27 +30,29 @@ .\" SUCH DAMAGE. .\" .\" @(#)pagesize.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD: src/usr.bin/pagesize/pagesize.1,v 1.7 2002/04/20 12:16:17 charnier Exp $ .\" .Dd June 6, 1993 .Dt PAGESIZE 1 -.Os BSD 4.2 +.Os .Sh NAME .Nm pagesize .Nd print system page size .Sh SYNOPSIS -.Nm pagesize +.Nm .Sh DESCRIPTION -.Nm Pagesize -prints the size of a page of memory in bytes, as +The +.Nm +utility prints the size of a page of memory in bytes, as returned by -.Xr getpagesize 2 . +.Xr getpagesize 3 . This program is useful in constructing portable shell scripts. .Sh SEE ALSO -.Xr getpagesize 2 +.Xr getpagesize 3 .Sh HISTORY The -.Nm pagesize +.Nm command appeared in .Bx 4.2 . diff --git a/pagesize.tproj/pagesize.sh b/pagesize.tproj/pagesize.sh index da22179..8c46ee0 100644 --- a/pagesize.tproj/pagesize.sh +++ b/pagesize.tproj/pagesize.sh @@ -32,9 +32,9 @@ # SUCH DAMAGE. # # @(#)pagesize.sh 8.1 (Berkeley) 4/3/94 +# $FreeBSD: src/usr.bin/pagesize/pagesize.sh,v 1.5 1999/08/28 01:04:48 peter Exp $ # -PATH=/bin:/usr/bin:/usr/sbin -export PATH +PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH -sysctl -n hw.pagesize +exec sysctl -n hw.pagesize diff --git a/passwd.tproj/Makefile b/passwd.tproj/Makefile index d474a92..b3136d1 100644 --- a/passwd.tproj/Makefile +++ b/passwd.tproj/Makefile @@ -7,12 +7,18 @@ MANPAGES = passwd.1 Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + ifeq ($(Embedded),NO) -CFILES += nis_passwd.c od_passwd.c -Extra_Frameworks = -F/System/Library/PrivateFrameworks -framework OpenDirectory -framework CoreFoundation -Extra_CC_Flags = -F/System/Library/PrivateFrameworks +CFILES += nis_passwd.c od_passwd.c pam_passwd.c +Extra_Frameworks = -framework OpenDirectory -framework CoreFoundation -lpam endif include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make Install_Program_Mode = 04555 + +after_install: + $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d + $(INSTALL_FILE) passwd.pam "$(DSTROOT)"/private/etc/pam.d/passwd diff --git a/passwd.tproj/file_passwd.c b/passwd.tproj/file_passwd.c index 65a862f..ffc81ca 100644 --- a/passwd.tproj/file_passwd.c +++ b/passwd.tproj/file_passwd.c @@ -21,6 +21,7 @@ * * @APPLE_LICENSE_HEADER_END@ */ +#include #include #include #include @@ -387,7 +388,7 @@ file_passwd(char *uname, char *locn) int retries = 0; struct stat sb; FILE *lockFile; - struct sigaction action = {0}; + struct sigaction action = {{0}}; struct rlimit rlim; /* unlimit the resource limits */ diff --git a/passwd.tproj/od_passwd.c b/passwd.tproj/od_passwd.c index fb4494c..908d999 100644 --- a/passwd.tproj/od_passwd.c +++ b/passwd.tproj/od_passwd.c @@ -28,7 +28,6 @@ #include #include #include -#include extern char* progname; int master_mode; @@ -161,7 +160,7 @@ od_passwd(char* uname, char* locn, char* aname) * Connect to DS server */ session = ODSessionCreate(NULL, NULL, &error); - if ( !session && error && CFErrorGetCode(error) == eServerNotRunning ) { + if ( !session && error && CFErrorGetCode(error) == kODErrorSessionDaemonNotRunning ) { /* * In single-user mode, attempt to load the local DS daemon. */ @@ -190,13 +189,13 @@ od_passwd(char* uname, char* locn, char* aname) if (location) { node = ODNodeCreateWithName(NULL, session, location, &error); } else { - node = ODNodeCreateWithNodeType(NULL, session, kODTypeAuthenticationSearchNode, &error); + node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, &error); } if (session) CFRelease(session); if (node) { - rec = ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), username, NULL, &error ); + rec = ODNodeCopyRecord(node, kODRecordTypeUsers, username, NULL, &error ); CFRelease(node); } @@ -213,7 +212,7 @@ od_passwd(char* uname, char* locn, char* aname) * Get the actual location. */ CFArrayRef values = NULL; - values = ODRecordCopyValues(rec, CFSTR(kDSNAttrMetaNodeLocation), &error); + values = ODRecordCopyValues(rec, kODAttributeTypeMetaNodeLocation, &error); location = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : location; printf("Changing password for %s.\n", uname); @@ -265,8 +264,8 @@ od_passwd(char* uname, char* locn, char* aname) CFArrayRef authItems = CFArrayCreate(NULL, values, 4, &kCFTypeArrayCallBacks); ODRecordSetNodeCredentialsExtended(rec, - CFSTR(kDSStdRecordTypeUsers), - CFSTR(kDSStdAuthSetPasswd), + kODRecordTypeUsers, + kODAuthenticationTypeSetPassword, authItems, NULL, NULL, diff --git a/passwd.tproj/pam_passwd.c b/passwd.tproj/pam_passwd.c new file mode 100644 index 0000000..c1586d4 --- /dev/null +++ b/passwd.tproj/pam_passwd.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999-2008 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 + +#include +#include /* for openpam_ttyconv() */ + +extern char* progname; +static pam_handle_t *pamh; +static struct pam_conv pamc; + +int +pam_passwd(char* uname) +{ + int retval = PAM_SUCCESS; + + /* Initialize PAM. */ + pamc.conv = &openpam_ttyconv; + pam_start(progname, uname, &pamc, &pamh); + + /* Authenticate. */ + if (PAM_SUCCESS != (retval = pam_authenticate(pamh, 0))) + goto pamerr; + + /* Authorize. */ + if (PAM_SUCCESS != (retval = pam_acct_mgmt(pamh, 0)) && PAM_NEW_AUTHTOK_REQD != retval) + goto pamerr; + + printf("Changing password for %s.\n", uname); + + /* Change the password. */ + if (PAM_SUCCESS != (retval = pam_chauthtok(pamh, 0))) + goto pamerr; + + /* Set the credentials. */ + if (PAM_SUCCESS != (retval = pam_setcred(pamh, PAM_ESTABLISH_CRED))) + goto pamerr; + + /* Open the session. */ + if (PAM_SUCCESS != (retval = pam_open_session(pamh, 0))) + goto pamerr; + + /* Close the session. */ + if (PAM_SUCCESS != (retval = pam_close_session(pamh, 0))) + goto pamerr; + +pamerr: + /* Print an error, if needed. */ + if (PAM_SUCCESS != retval) + fprintf(stderr, "%s: %s\n", progname, pam_strerror(pamh, retval)); + + /* Terminate PAM. */ + pam_end(pamh, retval); + return retval; +} diff --git a/passwd.tproj/passwd.1 b/passwd.tproj/passwd.1 index 90fa398..fd1cef1 100644 --- a/passwd.tproj/passwd.1 +++ b/passwd.tproj/passwd.1 @@ -31,48 +31,53 @@ .\" .\" @(#)passwd.1 8.1 (Berkeley) 6/6/93 .\" -.Dd June 6, 1993 +.Dd August 18, 2008 .Dt PASSWD 1 -.Os BSD 4 +.Os "Mac OS X" .Sh NAME .Nm passwd .Nd modify a user's password .Sh SYNOPSIS .Nm passwd -.Op Fl i Ar infosystem -.Op Fl l Ar location +.Op Fl i Ar infosystem Op Fl l Ar location .Op Fl u Ar authname -.Op Ar name +.Op Ar user .Sh DESCRIPTION -.Nm Passwd -changes the user's password. -First, the user is prompted for their current password. -If the current password is correctly typed, -a new password is requested. -The new password must be entered twice, -to detect (and avoid accepting) typing errors. +The +.Nm +utility changes the user's password. +If the user is not the super-user, +.Nm +first prompts for the current password and will not continue unless the correct +password is entered. +.Pp +When entering the new password, the characters entered do not echo, in order to +avoid the password being seen by a passer-by. +The +.Nm +utility prompts for the new password twice in order to detect typing errors. .Pp The new password should be at least six characters long and not purely alphabetic. Its total length should be less than .Dv _PASSWORD_LEN (currently 128 characters), -although some infosystems allow longer passwords. -Numbers, upper-case letters, and meta characters -are encouraged. +although some directory systems allow longer passwords. +Numbers, upper +case letters, and meta characters are encouraged. .Pp Once the password has been verified, -.Nm passwd -communicates the new password information to -the authenticating host. +.Nm +communicates the new password to the directory system. .Bl -tag -width flag .It Fl i Ar infosystem This option specifies where the password update should be applied. -Under Mac OS X 10.5, supported infosystems are: +Under Mac OS X 10.5 and later, supported directory systems are: .Bl -tag -width flag +.It Ar PAM +(default) Pluggable Authentication Modules. .It Ar opendirectory -(default) -A system conforming to opendirectory APIs and supporting updates +A system conforming to Open Directory APIs and supporting updates (including LDAP, etc). If no -l option is specified, the search node is used. .It Ar file @@ -82,7 +87,7 @@ A remote NIS server containing the user's password. .El .It Fl l Ar location This option causes the password to be updated in the given location -of the chosen infosystem. +of the chosen directory system. .Bl -tag -width flag .It for file, location may be a file name (/etc/master.passwd is the default) @@ -90,15 +95,17 @@ location may be a file name (/etc/master.passwd is the default) location may be a NIS domainname .It for opendirectory, location may be a directory node name +.It for PAM, +location is not used .El .It Fl u Ar authname -This option specifies the username to use when authenticating to +This option specifies the user name to use when authenticating to the directory node. +.It Ar user +This optional argument specifies the user account whose password will be +changed. This account's current password may be required, even when run as the +super-user, depending on the directory system. .El -.Pp -The super-user privileges are not required -to change a user's current password, -if only the local password is modified. .Sh FILES .Bl -tag -width /etc/master.passwd -compact .It Pa /etc/master.passwd diff --git a/passwd.tproj/passwd.c b/passwd.tproj/passwd.c index b6c960f..2f8599a 100644 --- a/passwd.tproj/passwd.c +++ b/passwd.tproj/passwd.c @@ -26,6 +26,7 @@ #if !TARGET_OS_EMBEDDED #define INFO_NIS 2 #define INFO_OPEN_DIRECTORY 3 +#define INFO_PAM 4 #endif #ifndef __SLICK__ @@ -55,6 +56,9 @@ extern int nis_passwd(char *, char *); #ifdef INFO_OPEN_DIRECTORY extern int od_passwd(char *, char *, char*); #endif +#ifdef INFO_PAM +extern int pam_passwd(char *); +#endif void getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha, @@ -163,15 +167,17 @@ getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha, void usage() { - fprintf(stderr, "usage: %s [-i infosystem] [-l location] [-u authname] [name]\n", progname); + fprintf(stderr, "usage: %s [-i infosystem] -l location]] [-u authname] [name]\n", progname); fprintf(stderr, " infosystem:\n"); fprintf(stderr, " file\n"); fprintf(stderr, " NIS\n"); fprintf(stderr, " OpenDirectory\n"); + fprintf(stderr, " PAM\n"); fprintf(stderr, " location (for infosystem):\n"); fprintf(stderr, " file location is path to file (default is %s)\n", _PASSWD_FILE); fprintf(stderr, " NIS location is NIS domain name\n"); fprintf(stderr, " OpenDirectory location is directory node name\n"); + fprintf(stderr, " PAM location is not used\n"); exit(1); } @@ -184,13 +190,22 @@ main(int argc, char *argv[]) int infosystem, ch; int free_user = 0; +#ifdef INFO_PAM + infosystem = INFO_PAM; +#else #ifdef INFO_OPEN_DIRECTORY - /* since OpenDirectory works for most infosystems, make it the default */ infosystem = INFO_OPEN_DIRECTORY; #else infosystem = INFO_FILE; #endif - +#endif + +#ifdef INFO_OPEN_DIRECTORY + /* PAM is the default infosystem, but we still want to use OpenDirectory directly when run by root */ + if (0 == getuid()) + infosystem = INFO_OPEN_DIRECTORY; +#endif + while ((ch = getopt(argc, argv, "i:l:u:")) != -1) switch(ch) { case 'i': @@ -205,6 +220,10 @@ main(int argc, char *argv[]) #ifdef INFO_OPEN_DIRECTORY } else if (!strcasecmp(optarg, "opendirectory")) { infosystem = INFO_OPEN_DIRECTORY; +#endif +#ifdef INFO_PAM + } else if (!strcasecmp(optarg, "PAM")) { + infosystem = INFO_PAM; #endif } else { fprintf(stderr, "%s: Unknown info system \'%s\'.\n", @@ -232,6 +251,11 @@ main(int argc, char *argv[]) user = argv[0]; } +#ifdef INFO_PAM + if (INFO_PAM == infosystem && NULL != locn) + usage(); +#endif + if (user == NULL) { /* @@ -270,6 +294,11 @@ main(int argc, char *argv[]) case INFO_OPEN_DIRECTORY: od_passwd(user, locn, auth); break; +#endif +#ifdef INFO_PAM + case INFO_PAM: + pam_passwd(user); + break; #endif } diff --git a/passwd.tproj/passwd.pam b/passwd.tproj/passwd.pam new file mode 100644 index 0000000..9ac660f --- /dev/null +++ b/passwd.tproj/passwd.pam @@ -0,0 +1,5 @@ +# passwd: auth account +auth required pam_permit.so +account required pam_opendirectory.so +password required pam_opendirectory.so +session required pam_permit.so diff --git a/pwd_mkdb.tproj/Makefile b/pwd_mkdb.tproj/Makefile index 98c0b2d..03e22f0 100644 --- a/pwd_mkdb.tproj/Makefile +++ b/pwd_mkdb.tproj/Makefile @@ -6,6 +6,9 @@ CFILES = pwd_mkdb.c pw_scan.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble pwd_mkdb.8 MANPAGES = pwd_mkdb.8 -Extra_CC_Flags = -D_PW_NAME_LEN=MAXLOGNAME -D_PW_YPTOKEN=\"__YP!\" +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -D_PW_NAME_LEN=MAXLOGNAME -D_PW_YPTOKEN=\"__YP!\" include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/reboot.tproj/Makefile b/reboot.tproj/Makefile index 40903ab..59a49c4 100644 --- a/reboot.tproj/Makefile +++ b/reboot.tproj/Makefile @@ -9,8 +9,11 @@ ifeq ($(Embedded),NO) USERDEFS = kextmanager.defs endif +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make after_install: - $(LN) $(DSTROOT)/$(Install_Dir)/reboot $(DSTROOT)$(Install_Dir)/halt + $(LN) -f $(DSTROOT)/$(Install_Dir)/reboot $(DSTROOT)$(Install_Dir)/halt $(LN) -fs reboot.8 $(DSTROOT)/usr/share/man/man8/halt.8 diff --git a/reboot.tproj/boot_hp300.8 b/reboot.tproj/boot_hp300.8 deleted file mode 100644 index 0303542..0000000 --- a/reboot.tproj/boot_hp300.8 +++ /dev/null @@ -1,117 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Systems Programming Group of the University of Utah Computer -.\" Science Department. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with 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. -.\" -.\" @(#)boot_hp300.8 8.2 (Berkeley) 4/19/94 -.\" -.Dd April 19, 1994 -.Dt BOOT_HP300 8 hp300 -.Os -.Sh NAME -.Nm boot -.Nd -system bootstrapping procedures -.Sh DESCRIPTION -.Sy Power fail and crash recovery. -Normally, the system will reboot itself at power-up or after crashes. -An automatic consistency check of the file systems will be performed, -and unless this fails, the system will resume multi-user operations. -.Pp -.Sy Cold starts. -On an HP300, the boot procedure uses the boot ROM to load a boot program -from an -.Tn LIF -format directory at the beginning of an attached disk. -The -.Pa /usr/mdec -directory contains a disk boot programs which should be placed in a -new pack automatically by -.Xr newfs 8 -when the ``a'' partition file system on the pack is created. -.Pp -This -.Em boot -program -finds the corresponding file on the given device -.Pf ( Ar vmunix -by default), -loads that file into memory, -and starts the program at the entry address specified in the program header. -.Pp -The boot program can be interrupted by typing `^C' (ctrl-C). -This will force the boot program to interactively prompt for a system to boot. -If not interrupted, it will boot from the device from which the boot -program itself was loaded. -.Pp -The file specifications used for an interactive boot are of the form: -.Pp -.Dl device(unit, minor) -.Pp -where -.Ar device -is the type of the device to be searched, -.Ar unit -is 8 * the hpib number plus the unit number of the disk or tape, -and -.Ar minor -is the disk partition or tape file number. -Normal line editing characters can be used when typing the file specification. -Currently, ``rd'' and ``sd'' are the only valid -.Ar device -specifiers. -.Pp -For example, -to boot from the `a' file system of unit 0 on HP-IB 2, -type -.Ql rd(16, 0)vmunix -to the boot prompt. -For tapes, the minor device number gives a file offset. -.Pp -In an emergency, the bootstrap methods described in the paper -.%T Installing 4.3bsd on the HP300 -can be used to boot from a distribution tape. -.Sh FILES -.Bl -tag -width /usr/mdec/installboot -compact -.It Pa /vmunix -system code -.It Pa /usr/mdec/bootrd -.Tn LIF -format boot block -.It Pa /usr/mdec/installboot -program to install boot blocks -.El -.Sh SEE ALSO -.Xr halt 8 , -.Xr reboot 8 , -.Xr shutdown 8 diff --git a/reboot.tproj/boot_i386.8 b/reboot.tproj/boot_i386.8 deleted file mode 100644 index 0dc3e0b..0000000 --- a/reboot.tproj/boot_i386.8 +++ /dev/null @@ -1,126 +0,0 @@ -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software written and contributed -.\" to Berkeley by William Jolitz. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)boot_i386.8 8.2 (Berkeley) 4/19/94 -.\" -.Dd April 19, 1994 -.Dt BOOT 8 i386 -.Os -.Sh NAME -.Nm boot -.Nd -system bootstrapping procedures -.Sh DESCRIPTION -.Sy Power fail and crash recovery. -Normally, the system will reboot itself at power-up or after crashes. -An automatic consistency check of the file systems will be performed, -and unless this fails, the system will resume multi-user operations. -.Pp -.Sy Cold starts. -The 386 -.Tn "PC AT" -clones attempt to boot the floppy disk drive A (otherwise known as drive -0) first, and failing that, attempt to boot the hard disk C (otherwise -known as hard disk controller 1, drive 0). -The automatic boot will attempt to load -.Pa vmunix -from partition A of either the floppy or the hard disk. -This boot may be aborted by typing any character on the keyboard repeatedly -(four or five times at least) during the operating system load phase, after -which the bootstrap will prompt for the file that you wish to load instead. -.Pp -One exception to this is the -.Ql d -key, which will not abort the load but instead silently force the -.Dv DEBUG -boot flags. -The boot flags for an autoboot are 0, and 3 for the successive boot after -an aborted autoboot sequence. -No other provison is made for setting boot flags (yet). -A specific device or bootstrap file may be used; for example, -.Pp -The file specifications used for the boostrap -when loaded with the -.Dq askme -flag -(e.g. an aborted autoboot) -are of the form: -.Pp -.Dl device unit partition: -.Pp -where -.Ar device -is the type of the device, assumed to be on the ISA bus, to be searched, -.Ar unit -is the unit number of the disk or tape, -and -.Ar partition -is the disk partition or tape file number. -Normal line editing characters can be used when typing the file specification. -The following list of supported devices may vary from installation to -installation: -.Bd -unfilled -offset indent -wd ST506, IDE, ESDI, RLL disks on a WD100[2367] or lookalike - controller -fd 5 1/4" or 3 1/2" High density floppies -.Ed -.Pp -For example, -to boot from a file system which starts at cylinder 0 -of unit 0 of an IDE disk, type -.Dq Li wd0a:vmunix -to the boot prompt; -.Dq Li fd0a:vmunix -would specify a 3 1/2" floppy drive 0 . -.Pp -In an emergency, the bootstrap methods described in the paper -.%T "Installing and Operating 4.3 BSD-Reno UNIX on the AT/386" -can be used -to boot from a distribution tape. -.Sh FILES -.Bl -tag -width /vmunixxx -compact -.It Pa /vmunix -system code -.It Pa /boot -system bootstrap -.El -.Sh SEE ALSO -.Xr halt 8 , -.Xr reboot 8 , -.Xr shutdown 8 -.Sh BUGS -The disklabel format used by this version of -.Bx -is quite -different from that of other architectures. diff --git a/reboot.tproj/boot_sparc.8 b/reboot.tproj/boot_sparc.8 deleted file mode 100644 index 72e57b0..0000000 --- a/reboot.tproj/boot_sparc.8 +++ /dev/null @@ -1,89 +0,0 @@ -.\" 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. -.\" -.\" @(#)boot_sparc.8 8.2 (Berkeley) 4/19/94 -.\" -.Dd April 19, 1994 -.Dt REBOOT 8 sparc -.Os -.Sh NAME -.Nm reboot -.Nd -.Tn UNIX -bootstrapping procedures -.Sh SYNOPSIS -.Nm reboot -.Op Fl n -.Op Fl q -.Sh DESCRIPTION -.Sy Power fail and crash recovery. -Normally, the system will reboot itself at power-up or after crashes. -An automatic consistency check of the file systems will be performed -as described in -.Xr fsck 8 . -and unless this fails, the system will resume multi-user operations. -.Pp -.Sy Cold starts -The SPARC system currently uses the SunOS bootstrap loaders. -This will be changed in a future version of the system. -The SunOS boot will attempt to load -.Pa vmunix -from partition A of the boot device, -which must currently be an ``sd'' disk. -.Pp -The -.Op Fl s -flag to the SunOS boot loader will being the system up in single-user mode. -The -.Op Fl d -flag to the SunOS boot loader will bring the system up in debug mode. -Here it waits for a kernel debugger connect; see -.Xr kgdb 8 . -Other flags are currently ignored. -.Sh FILES -.Bl -tag -width /vmunixxx -compact -.It Pa /vmunix -system code -.It Pa /boot -system bootstrap -.El -.Sh SEE ALSO -.Xr crash 8 , -.Xr disklabel 8 , -.Xr fsck 8 , -.Xr halt 8 , -.Xr init 8 , -.Xr rc 8 , -.Xr shutdown 8 , -.Xr syslogd 8 -.Sh BUGS -The use of Sun disk labels, without the ability to write them, -is problematic. diff --git a/reboot.tproj/boot_tahoe.8 b/reboot.tproj/boot_tahoe.8 deleted file mode 100644 index 01c7f81..0000000 --- a/reboot.tproj/boot_tahoe.8 +++ /dev/null @@ -1,152 +0,0 @@ -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)boot_tahoe.8 8.2 (Berkeley) 4/19/94 -.\" -.Dd April 19, 1994 -.Dt BOOT 8 tahoe -.Os -.Sh NAME -.Nm boot -.Nd -system bootstrapping procedures -.Sh DESCRIPTION -.Sy Power fail and crash recovery. -Normally, the system will reboot itself at power-up or after crashes. -An automatic consistency check of the file systems will be performed, -and unless this fails, the system will resume multi-user operations. -.Pp -.Sy Cold starts. -These are processor-type dependent. -On the -.Tn CCI -Power 6/32 and related processors, -the system will do a standard autoboot from drive 0 -upon power-up or reset. -This automatic boot may be cancelled by typing a -.Ql \&# -in the first few seconds after reset. -This enters console mode; the console prompt is -.Ql > -or -.Ql \&# . -The boot flags can be set to any hexadecimal value -.Fl n -with the command -.Pp -.Bd -filled -offset indent -compact -.Li \&#> p23 -.Ar n . -.Ed -.Pp -The default device may be examined or set; see the Diagnostics and Debugging -manual for the processor for details on device naming and syntax. -After setting the boot flags and/or device, -a bootstrap sequence can be initiated with -.Pp -.Dl #> fb -.Pp -A specific device or bootstrap file may be used; for example, -.Pp -.Dl \&#> \&fb xfd(1,0) -.Pp -would boot from the `a' partition on -.Tn XFD -drive 1. -.Pp -The file specifications used for the boostrap -when loaded with the -.Dq askme -flag -(register 23 set to 1 or 3) -are of the form: -.Pp -.Dl device(adaptor,controller,unit,minor) -.Pp -where -.Ar device -is the type of the device to be searched, -.Ar adaptor -is number of the -.Tn VERSAbus -(or -.Tn VMEbus ) -to which the device is attached, -.Ar controller -is the unit number of the controller on that buss, -.Ar unit -is the unit number of the disk or tape, -and -.Ar minor -is the disk partition or tape file number. -Leading adaptor or controller numbers default to 0. -Normal line editing characters can be used when typing the file specification. -The following list of supported devices may vary from installation to -installation: -.Pp -.Bd -unfilled -offset indent -compact -dk SMD or ESDI disks on VDDC or SMD-E -cy tape on Ciprico Tapemaster controller -.Ed -.Pp -For example, -to boot from a file system which starts at cylinder 0 -of unit 0 of an -.Tn SMD-E -disk, type -.Ql dk(0,0)vmunix -to the boot prompt; -.Ql dk(2,1,0)vmunix -would specify drive 1 on -.Tn SMD-E -controller 2. -.Pp -In an emergency, the bootstrap methods described in the paper -.%T "Installing and Operating 4.3 BSD-tahoe UNIX on the Tahoe" -can be used -to boot from a distribution tape. -.Sh FILES -.Bl -tag -width /vmunix -compact -.It Pa /vmunix -system code -.It Pa /boot -system bootstrap -.El -.Sh SEE ALSO -.Xr halt 8 , -.Xr reboot 8 , -.Xr shutdown 8 -.Sh BUGS -The disklabel format used by some versions of the console processor -is different than the format used by -.Tn UNIX -and the bootstrap. -.Sh HISTORY diff --git a/reboot.tproj/boot_vax.8 b/reboot.tproj/boot_vax.8 deleted file mode 100644 index dce6b69..0000000 --- a/reboot.tproj/boot_vax.8 +++ /dev/null @@ -1,322 +0,0 @@ -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)boot_vax.8 8.2 (Berkeley) 4/19/94 -.\" -.Dd April 19, 1994 -.Dt BOOT 8 vax -.Os -.Sh NAME -.Nm boot -.Nd -system bootstrapping procedures -.Sh DESCRIPTION -.Sy Power fail and crash recovery. -Normally, the system will reboot itself at power-up or after crashes. -Provided the auto-restart is enabled on the machine front panel, -an automatic consistency check of the file systems will be performed, -and unless this fails, the system will resume multi-user operations. -.Pp -.Sy Cold starts. -These are processor-type dependent. -On an 11/780, there are two floppy files for each disk controller, -both of which cause boots from unit 0 of the root file system -of a controller located on mba0 or uba0. -One gives a single user shell, while the other invokes the multi-user -automatic reboot. -Thus these files are -.Tn HPS -and -.Tn HPM -for the single -and multi-user boot from -.Tn MASSBUS -RP06/RM03/RM05 disks, -.Tn UPS -and -.Tn UPM -for -.Tn UNIBUS -storage module controller and disks -such as the -.Tn EMULEX -SC-21 -and -.Tn AMPEX -9300 pair, -.Tn RAS -and -.Tn RAM -to boot from -.Tn MSCP -controllers and disks such as the RA81, -or -.Tn HKS -and -.Tn HKM -for RK07 disks. -There is also a script for booting from the default device, -which is normally a copy of one of the standard multi-user boot scripts, -but which may be modified to perform other actions -or to boot from a different unit. -The situation on the 8600 is similar, with scripts loaded from the console RL02. -.Pp -Giving the command -.Pp -.Dl >>>BOOT HPM -.Pp -would boot the system from (e.g.) an RP06 and run the automatic consistency -check as described in -.Xr fsck 8 . -(Note that it may -be necessary to type control-P -and halt the processor -to gain the attention of the -.Tn LSI-11 -before getting the >>> prompt.) -The command -.Pp -.Dl >>>BOOT ANY -.Pp -invokes a version of the boot program in a way which allows you to -specify any system as the system to be booted. -It reads from the console a device specification (see below) followed -immediately by a pathname. -.Pp -The scripts may be modified for local configuration if necessary. -The flags are placed in register 11 (as defined in -.Aq Pa sys/reboot.h ) . -The boot device is specified in register 10. -The encoding of this register is also defined in -.Aq Pa sys/reboot.h . -The current encoding has a historical basis, and is shown in the following -table: -.Pp -.Bd -unfilled -offset indent -compact -bits usage -0-7 boot device type (the device major number) -8-15 disk partition -16-19 drive unit -20-23 controller number -24-27 adaptor number (UNIBUS or MASSBUS as appropriate) -.Ed -.Pp -The adaptor number corresponds to the normal configuration on the 11/750, -and to the order in which adaptors are found on the 11/780 and 8600 -(generally the same as the numbers used by -.Tn UNIX ) . -.Pp -On an 11/750, the reset button will boot from the device -selected by the front panel boot device switch. In systems -with RK07's, position B normally selects the RK07 for boot. -This will boot multi-user. To boot from RK07 with boot flags you -may specify -.Pp -.Bd -unfilled -offset indent -compact -.Li \&>>>B/ Ns Fl n No DMA0 -.Ed -.Pp -where, giving a -.Ar n -of 1 causes the boot program -to ask for the name of the system to be bootstrapped, -giving a -.Ar n -of 2 causes the boot program to come up single -user, and a -.Ar n -of 3 causes both of these actions to occur. -The ``DM'' specifies RK07, the ``A'' represents the adaptor number -.Pf ( Tn UNIBUS -or -.Tn MASSBUS ) , -and the ``0'' is the drive unit number. -Other disk types which may be used are DB -.Pq Tn MASSBUS , -DD (TU58), -and DU -.Pf ( Tn UDA-50/RA -disk). -A non-zero disk partition can be used by adding (partition times 1000 hex) -to -.Ar n . -.Pp -The boot procedure on the Micro -.Tn VAX -II -is similar. -A switch on the back panel sets the power-up action -to autoboot or to halt. -When halted, the processor may be booted using the same syntax -as on the 11/750. -.Pp -The 11/750 boot procedure uses the boot roms to load block 0 off of -the specified device. The /usr/mdec directory contains a number -of bootstrap programs for the various disks which should be placed -in a new pack by -.Xr disklabel 8 . -Similarly, the Micro -.Tn VAX -II boot procedure loads a boot parameter block -from block 0 of the disk. -The -.Xr rdboot -.Dq bootstrap -contains the correct parameters for an -.Tn MSCP -disk such -as the RD53. -.Pp -On any processor, the -.Em boot -program -finds the corresponding file on the given device -.Pf ( Pa vmunix -by default), loads that file -into memory location zero, and starts the program at the entry address -specified in the program header (after clearing off the high bit -of the specified entry address). -.Pp -The file specifications used with -.Dq BOOT ANY -or -.Dq \&B/3 -are of the form: -.Pp -.Dl device(adaptor,controller,unit,minor) -.Pp -where -.Ar device -is the type of the device to be searched, -.Ar adaptor -is the -.Tn UNIBUS -or -.Tn MASSBUS -number of the adaptor to which the device is attached, -.Ar controller -is the unit number of the controller or -.Tn MASSBUS -tape formatter on that adaptor, -.Ar unit -is the unit number of the disk or transport slave unit of the tape, -and -.Ar minor -is the disk partition or tape file number. -Leading adaptor or controller numbers default to 0. -Normal line editing characters can be used when typing the file specification. -The following list of supported devices may vary from installation to -installation: -.Pp -.Bd -unfilled -offset indent -compact -hp MASSBUS disk drive -up UNIBUS storage module drive -ht TE16,TU45,TU77 on MASSBUS -kra storage module on a KDB50 -mt TU78 on MASSBUS -hk RK07 on UNIBUS -ra storage module on a MSCP-compatible UNIBUS controller -rb storage module on a 730 IDC -rl RL02 on UNIBUS -tm TM11 emulation tape drives on UNIBUS -tms TMSCP-compatible tape -ts TS11 on UNIBUS -ut UNIBUS TU45 emulator -.Ed -.Pp -For example, -to boot from a file system which starts at cylinder 0 -of unit 0 of a -.Tn MASSBUS -disk, type -.Ql hp(0,0)vmunix -to the boot prompt; -.Ql hp(2,0,1,0)vmunix -would specify drive 1 on -.Tn MASSBUS -adaptor 2; -.Ql up(0,0)vmunix -would specify a -.Tn UNIBUS -drive, -.Ql hk(0,0)vmunix -would specify -an RK07 disk drive, -.Ql ra(1,0,0,0)vmunix -would specify a -.Tn UDA50 -disk drive on a second -.Tn UNIBUS , -and -.Ql rb(0,0)vmunix -would specify a -disk on a 730 -.Tn IDC . -For tapes, the minor device number gives a file offset; -.Ql mt(1,2,3,4) -would specify the fifth file on slave 3 of the formatter -at -.Ql drive -2 on mba 1. -.Pp -On an 11/750 with patchable control store, -microcode patches will be installed by -.Em boot -if the file -.Pa psc750.bin -exists in the root of the filesystem from which the system is booted. -.Pp -In an emergency, the bootstrap methods described in the paper -.%T Installing and Operating 4.3bsd -can be used to boot from a distribution tape. -.Sh FILES -.Bl -tag -width /usr/mdec/xxboot -compact -.It Pa /vmunix -system code -.It Pa /boot -system bootstrap -.It Pa /usr/mdec/xxboot -sector-0 boot block for 750, xx is disk type -.It Pa /usr/mdec/bootxx -second-stage boot for 750, xx is disk type -.It Pa /pcs750.bin -microcode patch file on 750 -.El -.Sh SEE ALSO -.Xr arff 8 , -.Xr halt 8 , -.Xr reboot 8 , -.Xr shutdown 8 -.Sh HISTORY -The -.Nm -command appeared in -.Bx 4.0 . diff --git a/reboot.tproj/reboot.c b/reboot.tproj/reboot.c index 47e9046..e4fc1e0 100644 --- a/reboot.tproj/reboot.c +++ b/reboot.tproj/reboot.c @@ -67,6 +67,8 @@ static const char rcsid[] = #include // task_self, etc #include // bootstrap #include +#include +#include #endif void usage(void); @@ -150,19 +152,14 @@ main(int argc, char *argv[]) } #if defined(__APPLE__) && !TARGET_OS_EMBEDDED - if (!lflag) { // shutdown(8) has already checked w/kextd - if ((errno = reserve_reboot()) && !qflag) + if (!qflag && !lflag) { // shutdown(8) has already checked w/kextd + if ((errno = reserve_reboot())) err(1, "couldn't lock for reboot"); } #endif if (qflag) { - #ifdef __APPLE__ - // launchd(8) handles reboot. This call returns NULL on success. - exit(reboot2(howto) == NULL ? EXIT_SUCCESS : EXIT_FAILURE); - #else /* __APPLE__ */ reboot(howto); - #endif /* __APPLE__ */ err(1, NULL); } @@ -193,7 +190,20 @@ main(int argc, char *argv[]) syslog(LOG_CRIT, "rebooted by %s", user); } } +#if defined(__APPLE__) + { + struct utmpx utx; + bzero(&utx, sizeof(utx)); + utx.ut_type = BOOT_TIME; + gettimeofday(&utx.ut_tv, NULL); + pututxline(&utx); + + int newvalue = 1; + sysctlbyname("kern.willshutdown", NULL, NULL, &newvalue, sizeof(newvalue)); + } +#else logwtmp("~", "shutdown", ""); +#endif /* * Do a sync early on, so disks start transfers while we're off diff --git a/sa.tproj/Makefile b/sa.tproj/Makefile index 92573da..515b592 100644 --- a/sa.tproj/Makefile +++ b/sa.tproj/Makefile @@ -1,7 +1,12 @@ Project = sa Install_Dir = /usr/sbin -CFILES = main.c pdb.c usrdb.c +CFILES = main.c pdb.c usrdb.c db.c MANPAGES = sa.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID +Extra_CC_Flags += -DAHZV1=64 +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sa.tproj/db.c b/sa.tproj/db.c new file mode 100644 index 0000000..299eeea --- /dev/null +++ b/sa.tproj/db.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2007 Diomidis Spinellis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING 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.sbin/sa/db.c,v 1.3 2008/02/21 07:12:56 grog Exp $"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +/* Key used to store the version of the database data elements. */ +#define VERSION_KEY "\0VERSION" + +/* + * Create the in-memory database, *mdb. + * If iflag is not set, fill-in mdb with the records of the disk-based + * database dbname. + * Upgrade old-version records by calling v1_to_v2. + * Return 0 if OK, -1 on error. + */ +int +db_copy_in(DB **mdb, const char *dbname, const char *uname, BTREEINFO *bti, + int (*v1_to_v2)(DBT *key, DBT *data)) +{ + DBT key, data; + DB *ddb; + int error, rv, version; + + if ((*mdb = dbopen(NULL, O_RDWR, 0, DB_BTREE, bti)) == NULL) + return (-1); + + if (iflag) + return (0); + + if ((ddb = dbopen(dbname, O_RDONLY, 0, DB_BTREE, bti)) == NULL) { + if (errno == ENOENT) + return (0); + warn("retrieving %s summary", uname); + db_destroy(*mdb, uname); + return (-1); + } + + error = 0; + + /* Obtain/set version. */ + version = 1; + key.data = &VERSION_KEY; + key.size = sizeof(VERSION_KEY); + + rv = DB_GET(ddb, &key, &data, 0); + if (rv < 0) { + warn("get version key from %s stats", uname); + error = -1; + goto closeout; + } else if (rv == 0) { /* It's there; verify version. */ + if (data.size != sizeof(version)) { + warnx("invalid version size %zd in %s", + data.size, uname); + error = -1; + goto closeout; + } + memcpy(&version, data.data, data.size); + if (version != 2) { + warnx("unsupported version %d in %s", + version, uname); + error = -1; + goto closeout; + } + } + + for (rv = DB_SEQ(ddb, &key, &data, R_FIRST); rv == 0; + rv = DB_SEQ(ddb, &key, &data, R_NEXT)) { + + /* See if this is a version record. */ + if (key.size == sizeof(VERSION_KEY) && + memcmp(key.data, VERSION_KEY, sizeof(VERSION_KEY)) == 0) + continue; + + /* Convert record from v1, if needed. */ + if (version == 1 && v1_to_v2(&key, &data) < 0) { + warn("converting %s stats", uname); + error = -1; + goto closeout; + } + + /* Copy record to the in-memory database. */ + if ((rv = DB_PUT(*mdb, &key, &data, 0)) < 0) { + warn("initializing %s stats", uname); + error = -1; + goto closeout; + } + } + if (rv < 0) { + warn("retrieving %s summary", uname); + error = -1; + } + +closeout: + if (DB_CLOSE(ddb) < 0) { + warn("closing %s summary", uname); + error = -1; + } + + if (error) + db_destroy(*mdb, uname); + return (error); +} + +/* + * Save the in-memory database mdb to the disk database dbname. + * Return 0 if OK, -1 on error. + */ +int +db_copy_out(DB *mdb, const char *dbname, const char *uname, BTREEINFO *bti) +{ + DB *ddb; + DBT key, data; + int error, rv, version; + + if ((ddb = dbopen(dbname, O_RDWR|O_CREAT|O_TRUNC, 0644, + DB_BTREE, bti)) == NULL) { + warn("creating %s summary", uname); + return (-1); + } + + error = 0; + + for (rv = DB_SEQ(mdb, &key, &data, R_FIRST); + rv == 0; rv = DB_SEQ(mdb, &key, &data, R_NEXT)) { + if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) { + warn("saving %s summary", uname); + error = -1; + goto out; + } + } + if (rv < 0) { + warn("retrieving %s stats", uname); + error = -1; + } + +out: +#ifndef __APPLE__ + /* Add a version record. */ + key.data = &VERSION_KEY; + key.size = sizeof(VERSION_KEY); + version = 2; + data.data = &version; + data.size = sizeof(version); + if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) { + warn("add version record to %s stats", uname); + error = -1; + } else if (rv == 1) { + warnx("duplicate version record in %s stats", uname); + error = -1; + } +#else + version = 1; // avoid unused warning +#endif + + if (DB_SYNC(ddb, 0) < 0) { + warn("syncing %s summary", uname); + error = -1; + } + if (DB_CLOSE(ddb) < 0) { + warn("closing %s summary", uname); + error = -1; + } + return error; +} + +void +db_destroy(DB *db, const char *uname) +{ + if (DB_CLOSE(db) < 0) + warn("destroying %s stats", uname); +} diff --git a/sa.tproj/extern.h b/sa.tproj/extern.h index f77282b..d6fcc17 100644 --- a/sa.tproj/extern.h +++ b/sa.tproj/extern.h @@ -27,7 +27,7 @@ * (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.sbin/sa/extern.h,v 1.5 2002/07/11 22:11:20 alfred Exp $ + * $FreeBSD: src/usr.sbin/sa/extern.h,v 1.7 2007/05/22 06:51:38 dds Exp $ */ #include @@ -36,32 +36,56 @@ /* structures */ +/* All times are stored in 1e-6s units. */ + struct cmdinfo { char ci_comm[MAXCOMLEN+2]; /* command name (+ '*') */ - u_long ci_uid; /* user id */ + uid_t ci_uid; /* user id */ +#ifdef __APPLE__ u_quad_t ci_calls; /* number of calls */ u_quad_t ci_etime; /* elapsed time */ u_quad_t ci_utime; /* user time */ u_quad_t ci_stime; /* system time */ u_quad_t ci_mem; /* memory use */ u_quad_t ci_io; /* number of disk i/o ops */ +#else + double ci_etime; /* elapsed time */ + double ci_utime; /* user time */ + double ci_stime; /* system time */ + double ci_mem; /* memory use */ + double ci_io; /* number of disk i/o ops */ +#endif u_int ci_flags; /* flags; see below */ }; #define CI_UNPRINTABLE 0x0001 /* unprintable chars in name */ struct userinfo { - u_long ui_uid; /* user id; for consistency */ + uid_t ui_uid; /* user id; for consistency */ u_quad_t ui_calls; /* number of invocations */ +#ifdef __APPLE__ u_quad_t ui_utime; /* user time */ u_quad_t ui_stime; /* system time */ u_quad_t ui_mem; /* memory use */ u_quad_t ui_io; /* number of disk i/o ops */ +#else + double ui_utime; /* user time */ + double ui_stime; /* system time */ + double ui_mem; /* memory use */ + double ui_io; /* number of disk i/o ops */ +#endif }; /* typedefs */ typedef int (*cmpf_t)(const DBT *, const DBT *); +/* external functions in db.c */ +int db_copy_in(DB **mdb, const char *dbname, const char *name, + BTREEINFO *bti, int (*v1_to_v2)(DBT *key, DBT *data)); +int db_copy_out(DB *mdb, const char *dbname, const char *name, + BTREEINFO *bti); +void db_destroy(DB *db, const char *uname); + /* external functions in pdb.c */ int pacct_init(void); void pacct_destroy(void); @@ -69,6 +93,11 @@ int pacct_add(const struct cmdinfo *); int pacct_update(void); void pacct_print(void); +#ifndef __APPLE__ +/* external functions in readrec.c */ +int readrec_forward(FILE *f, struct acctv2 *av2); +#endif + /* external functions in usrdb.c */ int usracct_init(void); void usracct_destroy(void); @@ -82,6 +111,7 @@ extern int aflag, bflag, cflag, dflag, Dflag, fflag, iflag, jflag, kflag; extern int Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag; extern u_quad_t cutoff; extern cmpf_t sa_cmp; +extern const char *pdb_file, *usrdb_file; /* some #defines to help with db's stupidity */ diff --git a/sa.tproj/main.c b/sa.tproj/main.c index 4bc068d..5812c96 100644 --- a/sa.tproj/main.c +++ b/sa.tproj/main.c @@ -28,16 +28,15 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1994 Christopher G. Demetriou\n\ All rights reserved.\n"; #endif - -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/usr.sbin/sa/main.c,v 1.12 2002/07/15 16:05:15 des Exp $"; -#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/usr.sbin/sa/main.c,v 1.18 2007/05/22 06:51:38 dds Exp $"); /* * sa: system accounting @@ -47,6 +46,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -57,21 +57,25 @@ static const char rcsid[] = #include "extern.h" #include "pathnames.h" -static int acct_load(char *, int); +static FILE *acct_load(const char *, int); +#ifdef __APPLE__ static u_quad_t decode_comp_t(comp_t); -static int cmp_comm(const char *, const char *); -static int cmp_usrsys(const DBT *, const DBT *); -static int cmp_avgusrsys(const DBT *, const DBT *); -static int cmp_dkio(const DBT *, const DBT *); -static int cmp_avgdkio(const DBT *, const DBT *); -static int cmp_cpumem(const DBT *, const DBT *); -static int cmp_avgcpumem(const DBT *, const DBT *); -static int cmp_calls(const DBT *, const DBT *); -static void usage(void); +#endif +static int cmp_comm(const char *, const char *); +static int cmp_usrsys(const DBT *, const DBT *); +static int cmp_avgusrsys(const DBT *, const DBT *); +static int cmp_dkio(const DBT *, const DBT *); +static int cmp_avgdkio(const DBT *, const DBT *); +static int cmp_cpumem(const DBT *, const DBT *); +static int cmp_avgcpumem(const DBT *, const DBT *); +static int cmp_calls(const DBT *, const DBT *); +static void usage(void); int aflag, bflag, cflag, dflag, Dflag, fflag, iflag, jflag, kflag; int Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag; u_quad_t cutoff = 1; +const char *pdb_file = _PATH_SAVACCT; +const char *usrdb_file = _PATH_USRACCT; static char *dfltargv[] = { NULL }; static int dfltargc = (sizeof dfltargv/sizeof(char *)); @@ -82,13 +86,13 @@ cmpf_t sa_cmp = cmp_usrsys; int main(int argc, char **argv) { - char ch; + FILE *f; char pathacct[] = _PATH_ACCT; - int error = 0; + int ch, error = 0; dfltargv[0] = pathacct; - while ((ch = getopt(argc, argv, "abcdDfijkKlmnqrstuv:")) != -1) + while ((ch = getopt(argc, argv, "abcdDfijkKlmnP:qrstuU:v:")) != -1) switch (ch) { case 'a': /* print all commands */ @@ -147,6 +151,10 @@ main(int argc, char **argv) /* sort by number of calls */ sa_cmp = cmp_calls; break; + case 'P': + /* specify program database summary file */ + pdb_file = optarg; + break; case 'q': /* quiet; error messages only */ qflag = 1; @@ -167,6 +175,10 @@ main(int argc, char **argv) /* first, print uid and command name */ uflag = 1; break; + case 'U': + /* specify user database summary file */ + usrdb_file = optarg; + break; case 'v': /* cull junk */ vflag = 1; @@ -202,14 +214,12 @@ main(int argc, char **argv) /* for each file specified */ for (; argc > 0; argc--, argv++) { - int fd; - /* * load the accounting data from the file. * if it fails, go on to the next file. */ - fd = acct_load(argv[0], sflag); - if (fd < 0) + f = acct_load(argv[0], sflag); + if (f == NULL) continue; if (!uflag && sflag) { @@ -240,7 +250,7 @@ main(int argc, char **argv) * the saved stats; better to underbill than overbill, * but we want every accounting record intact. */ - if (ftruncate(fd, 0) == -1) { + if (ftruncate(fileno(f), 0) == -1) { warn("couldn't truncate %s", *argv); error = 1; } @@ -267,8 +277,8 @@ main(int argc, char **argv) /* * close the opened accounting file */ - if (close(fd) == -1) { - warn("close %s", *argv); + if (fclose(f) == EOF) { + warn("fclose %s", *argv); error = 1; } } @@ -296,27 +306,30 @@ static void usage() { (void)fprintf(stderr, - "usage: sa [-abcdDfijkKlmnqrstu] [-v cutoff] [file ...]\n"); + "usage: sa [-abcdDfijkKlmnqrstu] [-P file] [-U file] [-v cutoff] [file ...]\n"); exit(1); } -static int -acct_load(pn, wr) - char *pn; - int wr; +static FILE * +acct_load(const char *pn, int wr) { +#ifdef __APPLE__ struct acct ac; +#else + struct acctv2 ac; +#endif struct cmdinfo ci; ssize_t rv; - int fd, i; + FILE *f; + int i; /* * open the file */ - fd = open(pn, wr ? O_RDWR : O_RDONLY, 0); - if (fd == -1) { + f = fopen(pn, wr ? "r+" : "r"); + if (f == NULL) { warn("open %s %s", pn, wr ? "for read/write" : "read-only"); - return (-1); + return (NULL); } /* @@ -325,13 +338,22 @@ acct_load(pn, wr) */ while (1) { /* get one accounting entry and punt if there's an error */ - rv = read(fd, &ac, sizeof(struct acct)); +#ifdef __APPLE__ + rv = read(fileno(f), &ac, sizeof(struct acct)); if (rv == -1) warn("error reading %s", pn); else if (rv > 0 && rv < (int)sizeof(struct acct)) warnx("short read of accounting data in %s", pn); if (rv != sizeof(struct acct)) break; +#else + rv = readrec_forward(f, &ac); + if (rv != 1) { + if (rv == EOF) + warn("error reading %s", pn); + break; + } +#endif /* decode it */ ci.ci_calls = 1; @@ -345,6 +367,7 @@ acct_load(pn, wr) } else ci.ci_comm[i] = c; } +#ifdef __APPLE__ if (ac.ac_flag & AFORK) ci.ci_comm[i++] = '*'; ci.ci_comm[i++] = '\0'; @@ -354,6 +377,17 @@ acct_load(pn, wr) ci.ci_uid = ac.ac_uid; ci.ci_mem = ac.ac_mem; ci.ci_io = decode_comp_t(ac.ac_io) / AHZ; +#else + if (ac.ac_flagx & AFORK) + ci.ci_comm[i++] = '*'; + ci.ci_comm[i++] = '\0'; + ci.ci_etime = ac.ac_etime; + ci.ci_utime = ac.ac_utime; + ci.ci_stime = ac.ac_stime; + ci.ci_uid = ac.ac_uid; + ci.ci_mem = ac.ac_mem; + ci.ci_io = ac.ac_io; +#endif if (!uflag) { /* and enter it into the usracct and pacct databases */ @@ -362,20 +396,27 @@ acct_load(pn, wr) if (sflag || (mflag && !qflag)) usracct_add(&ci); } else if (!qflag) - printf("%6lu %12.2f cpu %12juk mem %12ju io %s\n", +#ifdef __APPLE__ + printf("%6u %12.2f cpu %12juk mem %12ju io %s\n", ci.ci_uid, (ci.ci_utime + ci.ci_stime) / (double) AHZ, (uintmax_t)ci.ci_mem, (uintmax_t)ci.ci_io, ci.ci_comm); +#else + printf("%6u %12.3lf cpu %12.0lfk mem %12.0lf io %s\n", + ci.ci_uid, + (ci.ci_utime + ci.ci_stime) / 1000000, + ci.ci_mem, ci.ci_io, + ci.ci_comm); +#endif } - /* finally, return the file descriptor for possible truncation */ - return (fd); + /* Finally, return the file stream for possible truncation. */ + return (f); } -static u_quad_t -decode_comp_t(comp) - comp_t comp; +#ifdef __APPLE__ +static u_quad_t decode_comp_t(comp_t comp) { u_quad_t rv; @@ -392,11 +433,11 @@ decode_comp_t(comp) return (rv); } +#endif /* sort commands, doing the right thing in terms of reversals */ static int -cmp_comm(s1, s2) - const char *s1, *s2; +cmp_comm(const char *s1, const char *s2) { int rv; @@ -408,11 +449,14 @@ cmp_comm(s1, s2) /* sort by total user and system time */ static int -cmp_usrsys(d1, d2) - const DBT *d1, *d2; +cmp_usrsys(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; +#ifdef __APPLE__ u_quad_t t1, t2; +#else + double t1, t2; +#endif memcpy(&c1, d1->data, sizeof(c1)); memcpy(&c2, d2->data, sizeof(c2)); @@ -430,8 +474,7 @@ cmp_usrsys(d1, d2) /* sort by average user and system time */ static int -cmp_avgusrsys(d1, d2) - const DBT *d1, *d2; +cmp_avgusrsys(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; double t1, t2; @@ -455,8 +498,7 @@ cmp_avgusrsys(d1, d2) /* sort by total number of disk I/O operations */ static int -cmp_dkio(d1, d2) - const DBT *d1, *d2; +cmp_dkio(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; @@ -473,8 +515,7 @@ cmp_dkio(d1, d2) /* sort by average number of disk I/O operations */ static int -cmp_avgdkio(d1, d2) - const DBT *d1, *d2; +cmp_avgdkio(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; double n1, n2; @@ -482,8 +523,13 @@ cmp_avgdkio(d1, d2) memcpy(&c1, d1->data, sizeof(c1)); memcpy(&c2, d2->data, sizeof(c2)); +#ifdef __APPLE__ n1 = (double) c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1); n2 = (double) c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1); +#else + n1 = c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1); + n2 = c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1); +#endif if (n1 < n2) return -1; @@ -495,8 +541,7 @@ cmp_avgdkio(d1, d2) /* sort by the cpu-storage integral */ static int -cmp_cpumem(d1, d2) - const DBT *d1, *d2; +cmp_cpumem(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; @@ -513,11 +558,14 @@ cmp_cpumem(d1, d2) /* sort by the cpu-time average memory usage */ static int -cmp_avgcpumem(d1, d2) - const DBT *d1, *d2; +cmp_avgcpumem(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; +#ifdef __APPLE__ u_quad_t t1, t2; +#else + double t1, t2; +#endif double n1, n2; memcpy(&c1, d1->data, sizeof(c1)); @@ -526,8 +574,13 @@ cmp_avgcpumem(d1, d2) t1 = c1.ci_utime + c1.ci_stime; t2 = c2.ci_utime + c2.ci_stime; +#ifdef __APPLE__ n1 = (double) c1.ci_mem / (double) (t1 ? t1 : 1); n2 = (double) c2.ci_mem / (double) (t2 ? t2 : 1); +#else + n1 = c1.ci_mem / (t1 ? t1 : 1); + n2 = c2.ci_mem / (t2 ? t2 : 1); +#endif if (n1 < n2) return -1; @@ -539,8 +592,7 @@ cmp_avgcpumem(d1, d2) /* sort by the number of invocations */ static int -cmp_calls(d1, d2) - const DBT *d1, *d2; +cmp_calls(const DBT *d1, const DBT *d2) { struct cmdinfo c1, c2; diff --git a/sa.tproj/pdb.c b/sa.tproj/pdb.c index f0dd48b..66c99f1 100644 --- a/sa.tproj/pdb.c +++ b/sa.tproj/pdb.c @@ -28,95 +28,86 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/usr.sbin/sa/pdb.c,v 1.9 2002/07/15 16:05:15 des Exp $"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD: src/usr.sbin/sa/pdb.c,v 1.14 2007/05/22 06:51:38 dds Exp $"); #include #include #include #include #include +#include #include #include #include #include "extern.h" #include "pathnames.h" -static int check_junk __P((struct cmdinfo *)); -static void add_ci __P((const struct cmdinfo *, struct cmdinfo *)); -static void print_ci __P((const struct cmdinfo *, const struct cmdinfo *)); +static int check_junk(const struct cmdinfo *); +static void add_ci(const struct cmdinfo *, struct cmdinfo *); +static void print_ci(const struct cmdinfo *, const struct cmdinfo *); static DB *pacct_db; -int -pacct_init() +/* Legacy format in AHZV1 units. */ +struct cmdinfov1 { + char ci_comm[MAXCOMLEN+2]; /* command name (+ '*') */ + uid_t ci_uid; /* user id */ + u_quad_t ci_calls; /* number of calls */ + u_quad_t ci_etime; /* elapsed time */ + u_quad_t ci_utime; /* user time */ + u_quad_t ci_stime; /* system time */ + u_quad_t ci_mem; /* memory use */ + u_quad_t ci_io; /* number of disk i/o ops */ + u_int ci_flags; /* flags; see below */ +}; + +/* + * Convert a v1 data record into the current version. + * Return 0 if OK, -1 on error, setting errno. + */ +static int +v1_to_v2(DBT *key __unused, DBT *data) { - DB *saved_pacct_db; - int error; + struct cmdinfov1 civ1; + static struct cmdinfo civ2; - pacct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL); - if (pacct_db == NULL) + if (data->size != sizeof(civ1)) { + errno = EFTYPE; return (-1); - - error = 0; - if (!iflag) { - DBT key, data; - int serr, nerr; - - saved_pacct_db = dbopen(_PATH_SAVACCT, O_RDONLY, 0, DB_BTREE, - NULL); - if (saved_pacct_db == NULL) { - error = errno == ENOENT ? 0 : -1; - if (error) - warn("retrieving process accounting summary"); - goto out; - } - - serr = DB_SEQ(saved_pacct_db, &key, &data, R_FIRST); - if (serr < 0) { - warn("retrieving process accounting summary"); - error = -1; - goto closeout; - } - while (serr == 0) { - nerr = DB_PUT(pacct_db, &key, &data, 0); - if (nerr < 0) { - warn("initializing process accounting stats"); - error = -1; - break; - } - - serr = DB_SEQ(saved_pacct_db, &key, &data, R_NEXT); - if (serr < 0) { - warn("retrieving process accounting summary"); - error = -1; - break; - } - } - -closeout: if (DB_CLOSE(saved_pacct_db) < 0) { - warn("closing process accounting summary"); - error = -1; - } } + memcpy(&civ1, data->data, data->size); + memset(&civ2, 0, sizeof(civ2)); + memcpy(civ2.ci_comm, civ1.ci_comm, sizeof(civ2.ci_comm)); + civ2.ci_uid = civ1.ci_uid; + civ2.ci_calls = civ1.ci_calls; + civ2.ci_etime = ((double)civ1.ci_etime / AHZV1) * 1000000; + civ2.ci_utime = ((double)civ1.ci_utime / AHZV1) * 1000000; + civ2.ci_stime = ((double)civ1.ci_stime / AHZV1) * 1000000; + civ2.ci_mem = civ1.ci_mem; + civ2.ci_io = civ1.ci_io; + civ2.ci_flags = civ1.ci_flags; + data->size = sizeof(civ2); + data->data = &civ2; + return (0); +} -out: if (error != 0) - pacct_destroy(); - return (error); +/* Copy pdb_file to in-memory pacct_db. */ +int +pacct_init() +{ + return (db_copy_in(&pacct_db, pdb_file, "process accounting", + NULL, v1_to_v2)); } void pacct_destroy() { - if (DB_CLOSE(pacct_db) < 0) - warn("destroying process accounting stats"); + db_destroy(pacct_db, "process accounting"); } int -pacct_add(ci) - const struct cmdinfo *ci; +pacct_add(const struct cmdinfo *ci) { DBT key, data; struct cmdinfo newci; @@ -157,52 +148,12 @@ pacct_add(ci) return (0); } +/* Copy in-memory pacct_db to pdb_file. */ int pacct_update() { - DB *saved_pacct_db; - DBT key, data; - int error, serr, nerr; - - saved_pacct_db = dbopen(_PATH_SAVACCT, O_RDWR|O_CREAT|O_TRUNC, 0644, - DB_BTREE, NULL); - if (saved_pacct_db == NULL) { - warn("creating process accounting summary"); - return (-1); - } - - error = 0; - - serr = DB_SEQ(pacct_db, &key, &data, R_FIRST); - if (serr < 0) { - warn("retrieving process accounting stats"); - error = -1; - } - while (serr == 0) { - nerr = DB_PUT(saved_pacct_db, &key, &data, 0); - if (nerr < 0) { - warn("saving process accounting summary"); - error = -1; - break; - } - - serr = DB_SEQ(pacct_db, &key, &data, R_NEXT); - if (serr < 0) { - warn("retrieving process accounting stats"); - error = -1; - break; - } - } - - if (DB_SYNC(saved_pacct_db, 0) < 0) { - warn("syncing process accounting summary"); - error = -1; - } - if (DB_CLOSE(saved_pacct_db) < 0) { - warn("closing process accounting summary"); - error = -1; - } - return error; + return (db_copy_out(pacct_db, pdb_file, "process accounting", + NULL)); } void @@ -304,8 +255,7 @@ next: rv = DB_SEQ(pacct_db, &key, &data, R_NEXT); } static int -check_junk(cip) - struct cmdinfo *cip; +check_junk(const struct cmdinfo *cip) { char *cp; size_t len; @@ -317,9 +267,7 @@ check_junk(cip) } static void -add_ci(fromcip, tocip) - const struct cmdinfo *fromcip; - struct cmdinfo *tocip; +add_ci(const struct cmdinfo *fromcip, struct cmdinfo *tocip) { tocip->ci_calls += fromcip->ci_calls; tocip->ci_etime += fromcip->ci_etime; @@ -329,9 +277,9 @@ add_ci(fromcip, tocip) tocip->ci_io += fromcip->ci_io; } +#ifdef __APPLE__ static void -print_ci(cip, totalcip) - const struct cmdinfo *cip, *totalcip; +print_ci(const struct cmdinfo *cip, const struct cmdinfo *totalcip) { double t, c; int uflow; @@ -422,3 +370,100 @@ print_ci(cip, totalcip) printf(" %s\n", cip->ci_comm); } +#else +static void +print_ci(const struct cmdinfo *cip, const struct cmdinfo *totalcip) +{ + double t, c; + int uflow; + + c = cip->ci_calls ? cip->ci_calls : 1; + t = (cip->ci_utime + cip->ci_stime) / 1000000; + if (t < 0.01) { + t = 0.01; + uflow = 1; + } else + uflow = 0; + + printf("%8ju ", (uintmax_t)cip->ci_calls); + if (cflag) { + if (cip != totalcip) + printf(" %4.1f%% ", cip->ci_calls / + (double)totalcip->ci_calls * 100); + else + printf(" %4s ", ""); + } + + if (jflag) + printf("%11.3fre ", cip->ci_etime / (1000000 * c)); + else + printf("%11.3fre ", cip->ci_etime / (60.0 * 1000000)); + if (cflag) { + if (cip != totalcip) + printf(" %4.1f%% ", cip->ci_etime / + totalcip->ci_etime * 100); + else + printf(" %4s ", ""); + } + + if (!lflag) { + if (jflag) + printf("%11.3fcp ", t / (double) cip->ci_calls); + else + printf("%11.2fcp ", t / 60.0); + if (cflag) { + if (cip != totalcip) + printf(" %4.1f%% ", + (cip->ci_utime + cip->ci_stime) / + (totalcip->ci_utime + totalcip->ci_stime) * + 100); + else + printf(" %4s ", ""); + } + } else { + if (jflag) + printf("%11.3fu ", cip->ci_utime / (1000000 * c)); + else + printf("%11.2fu ", cip->ci_utime / (60.0 * 1000000)); + if (cflag) { + if (cip != totalcip) + printf(" %4.1f%% ", cip->ci_utime / + (double)totalcip->ci_utime * 100); + else + printf(" %4s ", ""); + } + if (jflag) + printf("%11.3fs ", cip->ci_stime / (1000000 * c)); + else + printf("%11.2fs ", cip->ci_stime / (60.0 * 1000000)); + if (cflag) { + if (cip != totalcip) + printf(" %4.1f%% ", cip->ci_stime / + (double)totalcip->ci_stime * 100); + else + printf(" %4s ", ""); + } + } + + if (tflag) { + if (!uflow) + printf("%8.2fre/cp ", + cip->ci_etime / + (cip->ci_utime + cip->ci_stime)); + else + printf("*ignore* "); + } + + if (Dflag) + printf("%10.0fio ", cip->ci_io); + else + printf("%8.0favio ", cip->ci_io / c); + + if (Kflag) + printf("%10.0fk*sec ", cip->ci_mem); + else + printf("%8.0fk ", cip->ci_mem / t); + + printf(" %s\n", cip->ci_comm); +} +#endif \ No newline at end of file diff --git a/sa.tproj/sa.8 b/sa.tproj/sa.8 index 288df04..1e9540c 100644 --- a/sa.tproj/sa.8 +++ b/sa.tproj/sa.8 @@ -27,28 +27,30 @@ .\" (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.sbin/sa/sa.8,v 1.15 2002/07/14 14:46:01 charnier Exp $ +.\" $FreeBSD: src/usr.sbin/sa/sa.8,v 1.20 2007/05/18 12:36:10 dds Exp $ .\" -.Dd February 25, 1994 +.Dd May 18, 2007 .Dt SA 8 .Os .Sh NAME .Nm sa .Nd print system accounting statistics .Sh SYNOPSIS -.Nm sa +.Nm .Op Fl abcdDfijkKlmnqrstu +.Op Fl P Ar file +.Op Fl U Ar file .Op Fl v Ar cutoff .Op Ar .Sh DESCRIPTION The -.Nm sa +.Nm utility reports on, cleans up, and generally maintains system accounting files. .Pp The -.Nm sa +.Nm utility is able to condense the information in .Pa /var/account/acct into the summary files @@ -69,139 +71,132 @@ If file names are supplied, they are read instead of .Pa /var/account/acct . After each file is read, if the summary files are being updated, an updated summary will -be saved to disk. Only one report is printed, +be saved to disk. +Only one report is printed, after the last file is processed. .Pp The labels used in the output indicate the following, except where otherwise specified by individual options: .Bl -tag -width k*sec -.\" ========== .It Dv avio Average number of I/O operations per execution -.\" ========== .It Dv cp Sum of user and system time, in minutes -.\" ========== .It Dv cpu Same as .Dv cp -.\" ========== .It Dv k CPU-time averaged core usage, in 1k units -.\" ========== .It Dv k*sec CPU storage integral, in 1k-core seconds -.\" ========== .It Dv re Real time, in minutes -.\" ========== .It Dv s System time, in minutes -.\" ========== .It Dv tio Total number of I/O operations -.\" ========== .It Dv u User time, in minutes .El .Pp The options to -.Nm sa +.Nm are: .Bl -tag -width Ds -.\" ========== .It Fl a List all command names, including those containing unprintable -characters and those used only once. By default, -.Nm sa +characters and those used only once. +By default, +.Nm places all names containing unprintable characters and those used only once under the name ``***other''. -.\" ========== .It Fl b If printing command statistics, sort output by the sum of user and system time divided by number of calls. -.\" ========== .It Fl c In addition to the number of calls and the user, system and real times for each command, print their percentage of the total over all commands. -.\" ========== -.It Fl D -If printing command statistics, sort and print by the total number -of disk I/O operations. -.\" ========== .It Fl d If printing command statistics, sort by the average number of disk -I/O operations. If printing user statistics, print the average number of +I/O operations. +If printing user statistics, print the average number of disk I/O operations per user. -.\" ========== +.It Fl D +If printing command statistics, sort and print by the total number +of disk I/O operations. .It Fl f Force no interactive threshold comparison with the .Fl v option. -.\" ========== .It Fl i Do not read in the summary files. -.\" ========== .It Fl j Instead of the total minutes per category, give seconds per call. -.\" ========== -.It Fl K -If printing command statistics, print and sort by the cpu-storage integral. -.\" ========== .It Fl k If printing command statistics, sort by the cpu-time average memory -usage. If printing user statistics, print the cpu-time average +usage. +If printing user statistics, print the cpu-time average memory usage. -.\" ========== +.It Fl K +If printing command statistics, print and sort by the cpu-storage integral. .It Fl l Separate system and user time; normally they are combined. -.\" ========== .It Fl m Print per-user statistics rather than per-command statistics. -.\" ========== .It Fl n Sort by number of calls. -.\" ========== +.It Fl P Ar file +Use the specified +.Ar file +for accessing the per-command accounting summary database, +instead of the default +.Pa /var/account/savacct . .It Fl q Create no output other than error messages. -.\" ========== .It Fl r Reverse order of sort. -.\" ========== .It Fl s Truncate the accounting files when done and merge their data into the summary files. -.\" ========== .It Fl t For each command, report the ratio of real time to the sum of user and system cpu times. If the cpu time is too small to report, ``*ignore*'' appears in this field. -.\" ========== +.It Fl U Ar file +Use the specified +.Ar file +for accessing the per-user accounting summary database, +instead of the default +.Pa /var/account/usracct . .It Fl u Superseding all other flags, for each entry in the accounting file, print the user ID, total seconds of cpu usage, total memory usage, number of I/O operations performed, and command name. -.\" ========== .It Fl v Ar cutoff For each command used .Ar cutoff times or fewer, print the command name and await a reply -from the terminal. If the reply begins with ``y'', add -the command to the category ``**junk**''. This flag is +from the terminal. +If the reply begins with ``y'', add +the command to the category ``**junk**''. +This flag is used to strip garbage from the report. .El .Pp -By default, per-command statistics will be printed. The number of +By default, per-command statistics will be printed. +The number of calls, the total elapsed time in minutes, total cpu and user time in minutes, average number of I/O operations, and CPU-time -averaged core usage will be printed. If the +averaged core usage will be printed. +If the .Fl m option is specified, per-user statistics will be printed, including the user name, the number of commands invoked, total cpu time used (in minutes), total number of I/O operations, and CPU storage integral -for each user. If the +for each user. +If the .Fl u option is specified, the uid, user and system time (in seconds), CPU storage integral, I/O usage, and command name will be printed @@ -211,7 +206,8 @@ If the .Fl u flag is specified, all flags other than .Fl q -are ignored. If the +are ignored. +If the .Fl m flag is specified, only the .Fl b , @@ -222,8 +218,6 @@ flag is specified, only the and .Fl s flags are honored. -.Sh DIAGNOSTICS -.Ex -std .Sh FILES .Bl -tag -width /var/account/usracct -compact .It Pa /var/account/acct @@ -233,23 +227,19 @@ per-command accounting summary database .It Pa /var/account/usracct per-user accounting summary database .El +.Sh EXIT STATUS +.Ex -std .Sh SEE ALSO .Xr lastcomm 1 , .Xr acct 5 , .Xr ac 8 , .Xr accton 8 -.Sh BUGS -The number of options to this program is absurd, especially considering -that there's not much logic behind their lettering. -.Pp -The field labels should be more consistent. -.Pp -The VM system does not record the CPU storage integral. .Sh CAVEATS While the behavior of the options in this version of -.Nm sa +.Nm was modeled after the original version, there are some intentional -differences and undoubtedly some unintentional ones as well. In +differences and undoubtedly some unintentional ones as well. +In particular, the .Fl q option has been added, and the @@ -257,9 +247,16 @@ option has been added, and the option now understands more options than it used to. .Pp The formats of the summary files created by this version of -.Nm sa +.Nm are very different from the those used by the original version. This is not considered a problem, however, because the accounting record format has changed as well (since user ids are now 32 bits). .Sh AUTHORS .An Chris G. Demetriou Aq cgd@postgres.berkeley.edu +.Sh BUGS +The number of options to this program is absurd, especially considering +that there is not much logic behind their lettering. +.Pp +The field labels should be more consistent. +.Pp +The VM system does not record the CPU storage integral. diff --git a/sa.tproj/usrdb.c b/sa.tproj/usrdb.c index dda96ae..277987a 100644 --- a/sa.tproj/usrdb.c +++ b/sa.tproj/usrdb.c @@ -28,10 +28,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/usr.sbin/sa/usrdb.c,v 1.12 2002/07/15 16:05:15 des Exp $"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD: src/usr.sbin/sa/usrdb.c,v 1.16 2007/05/22 06:51:38 dds Exp $"); #include #include @@ -47,87 +45,81 @@ static const char rcsid[] = #include "extern.h" #include "pathnames.h" -static int uid_compare __P((const DBT *, const DBT *)); +static int uid_compare(const DBT *, const DBT *); static DB *usracct_db; +/* Legacy format in AHZV1 units. */ +struct userinfov1 { + uid_t ui_uid; /* user id; for consistency */ + u_quad_t ui_calls; /* number of invocations */ + u_quad_t ui_utime; /* user time */ + u_quad_t ui_stime; /* system time */ + u_quad_t ui_mem; /* memory use */ + u_quad_t ui_io; /* number of disk i/o ops */ +}; + +/* + * Convert a v1 data record into the current version. + * Return 0 if OK, -1 on error, setting errno. + */ +static int +v1_to_v2(DBT *key, DBT *data) +{ + struct userinfov1 uiv1; + static struct userinfo uiv2; + static uid_t uid; + + if (key->size != sizeof(u_long) || data->size != sizeof(uiv1)) { + errno = EFTYPE; + return (-1); + } + + /* Convert key. */ + key->size = sizeof(uid_t); + uid = (uid_t)*(u_long *)(key->data); + key->data = &uid; + + /* Convert data. */ + memcpy(&uiv1, data->data, data->size); + memset(&uiv2, 0, sizeof(uiv2)); + uiv2.ui_uid = uiv1.ui_uid; + uiv2.ui_calls = uiv1.ui_calls; + uiv2.ui_utime = ((double)uiv1.ui_utime / AHZV1) * 1000000; + uiv2.ui_stime = ((double)uiv1.ui_stime / AHZV1) * 1000000; + uiv2.ui_mem = uiv1.ui_mem; + uiv2.ui_io = uiv1.ui_io; + data->size = sizeof(uiv2); + data->data = &uiv2; + + return (0); +} + +/* Copy usrdb_file to in-memory usracct_db. */ int usracct_init() { - DB *saved_usracct_db; BTREEINFO bti; - int error; bzero(&bti, sizeof bti); bti.compare = uid_compare; - usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti); - if (usracct_db == NULL) - return (-1); - - error = 0; - if (!iflag) { - DBT key, data; - int serr, nerr; - - saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE, - &bti); - if (saved_usracct_db == NULL) { - error = (errno == ENOENT) ? 0 : -1; - if (error) - warn("retrieving user accounting summary"); - goto out; - } - - serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST); - if (serr < 0) { - warn("retrieving user accounting summary"); - error = -1; - goto closeout; - } - while (serr == 0) { - nerr = DB_PUT(usracct_db, &key, &data, 0); - if (nerr < 0) { - warn("initializing user accounting stats"); - error = -1; - break; - } - - serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT); - if (serr < 0) { - warn("retrieving user accounting summary"); - error = -1; - break; - } - } - -closeout: - if (DB_CLOSE(saved_usracct_db) < 0) { - warn("closing user accounting summary"); - error = -1; - } - } - -out: - if (error != 0) - usracct_destroy(); - return (error); + return (db_copy_in(&usracct_db, usrdb_file, "user accounting", + &bti, v1_to_v2)); } void usracct_destroy() { - if (DB_CLOSE(usracct_db) < 0) - warn("destroying user accounting stats"); + db_destroy(usracct_db, "user accounting"); } int -usracct_add(ci) - const struct cmdinfo *ci; +usracct_add(const struct cmdinfo *ci) { DBT key, data; struct userinfo newui; - u_long uid; + uid_t uid; int rv; uid = ci->ci_uid; @@ -136,13 +128,13 @@ usracct_add(ci) rv = DB_GET(usracct_db, &key, &data, 0); if (rv < 0) { - warn("get key %lu from user accounting stats", uid); + warn("get key %u from user accounting stats", uid); return (-1); } else if (rv == 0) { /* it's there; copy whole thing */ /* add the old data to the new data */ bcopy(data.data, &newui, data.size); if (newui.ui_uid != uid) { - warnx("key %lu != expected record number %lu", + warnx("key %u != expected record number %u", newui.ui_uid, uid); warnx("inconsistent user accounting stats"); return (-1); @@ -162,7 +154,7 @@ usracct_add(ci) data.size = sizeof newui; rv = DB_PUT(usracct_db, &key, &data, 0); if (rv < 0) { - warn("add key %lu to user accounting stats", uid); + warn("add key %u to user accounting stats", uid); return (-1); } else if (rv != 0) { warnx("DB_PUT returned 1"); @@ -172,56 +164,17 @@ usracct_add(ci) return (0); } +/* Copy in-memory usracct_db to usrdb_file. */ int usracct_update() { - DB *saved_usracct_db; - DBT key, data; BTREEINFO bti; - int error, serr, nerr; bzero(&bti, sizeof bti); bti.compare = uid_compare; - saved_usracct_db = dbopen(_PATH_USRACCT, O_RDWR|O_CREAT|O_TRUNC, 0644, - DB_BTREE, &bti); - if (saved_usracct_db == NULL) { - warn("creating user accounting summary"); - return (-1); - } - - error = 0; - - serr = DB_SEQ(usracct_db, &key, &data, R_FIRST); - if (serr < 0) { - warn("retrieving user accounting stats"); - error = -1; - } - while (serr == 0) { - nerr = DB_PUT(saved_usracct_db, &key, &data, 0); - if (nerr < 0) { - warn("saving user accounting summary"); - error = -1; - break; - } - - serr = DB_SEQ(usracct_db, &key, &data, R_NEXT); - if (serr < 0) { - warn("retrieving user accounting stats"); - error = -1; - break; - } - } - - if (DB_SYNC(saved_usracct_db, 0) < 0) { - warn("syncing process accounting summary"); - error = -1; - } - if (DB_CLOSE(saved_usracct_db) < 0) { - warn("closing process accounting summary"); - error = -1; - } - return error; + return (db_copy_out(usracct_db, usrdb_file, "user accounting", + &bti)); } void @@ -242,6 +195,7 @@ usracct_print() printf("%-*s %9ju ", MAXLOGNAME - 1, user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls); +#ifdef __APPLE__ t = (double) (ui->ui_utime + ui->ui_stime) / (double) AHZ; if (t < 0.0001) /* kill divide by zero */ @@ -261,6 +215,26 @@ usracct_print() printf("%12.0f%s", ui->ui_mem / t, "k"); else printf("%12ju%s", (uintmax_t)ui->ui_mem, "k*sec"); +#else + t = (ui->ui_utime + ui->ui_stime) / 1000000; + if (t < 0.000001) /* kill divide by zero */ + t = 0.000001; + + printf("%12.2f%s ", t / 60.0, "cpu"); + + /* ui->ui_calls is always != 0 */ + if (dflag) + printf("%12.0f%s", + ui->ui_io / ui->ui_calls, "avio"); + else + printf("%12.0f%s", ui->ui_io, "tio"); + + /* t is always >= 0.000001; see above. */ + if (kflag) + printf("%12.0f%s", ui->ui_mem / t, "k"); + else + printf("%12.0f%s", ui->ui_mem, "k*sec"); +#endif printf("\n"); @@ -271,10 +245,9 @@ usracct_print() } static int -uid_compare(k1, k2) - const DBT *k1, *k2; +uid_compare(const DBT *k1, const DBT *k2) { - u_long d1, d2; + uid_t d1, d2; bcopy(k1->data, &d1, sizeof d1); bcopy(k2->data, &d2, sizeof d2); diff --git a/sadc.tproj/Makefile b/sadc.tproj/Makefile index f9fbd4f..93bd5b1 100644 --- a/sadc.tproj/Makefile +++ b/sadc.tproj/Makefile @@ -8,7 +8,10 @@ MANPAGES = sa1.8 sa2.8 sadc.8 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sa1.8 sa1.sh\ sa2.8 sa2.sh sadc.8 -Extra_CC_Flags = -I. +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -I. Extra_Frameworks = -framework CoreFoundation -framework IOKit include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sadc.tproj/sadc.h b/sadc.tproj/sadc.h index f7da13f..d37ae0d 100644 --- a/sadc.tproj/sadc.h +++ b/sadc.tproj/sadc.h @@ -37,10 +37,10 @@ struct record_hdr { - int rec_type; - int rec_version; - int rec_count; - long rec_size; + int32_t rec_type; + int32_t rec_version; + int32_t rec_count; + int32_t rec_size; }; #define rec_data rec_size @@ -55,36 +55,37 @@ struct record_hdr struct drivepath { - int drivepath_id; /* compressed table id */ - int state; - char BSDName[MAXDRIVENAME + 1]; - io_string_t ioreg_path; /* unique id, hardware path */ + int32_t drivepath_id; /* compressed table id */ + int32_t state; + char BSDName[MAXDRIVENAME + 1]; + io_string_t ioreg_path; /* unique id, hardware path */ }; struct drivestats { - io_registry_entry_t driver; - int drivepath_id; - u_int64_t blocksize; - - u_int64_t Reads; - u_int64_t BytesRead; - - u_int64_t Writes; - u_int64_t BytesWritten; - - u_int64_t LatentReadTime; - u_int64_t LatentWriteTime; - - u_int64_t ReadErrors; - u_int64_t WriteErrors; - - u_int64_t ReadRetries; - u_int64_t WriteRetries; + io_registry_entry_t driver; + + int32_t drivepath_id; + uint64_t blocksize; + + uint64_t Reads; + uint64_t BytesRead; + + uint64_t Writes; + uint64_t BytesWritten; + + uint64_t LatentReadTime; + uint64_t LatentWriteTime; + + uint64_t ReadErrors; + uint64_t WriteErrors; + + uint64_t ReadRetries; + uint64_t WriteRetries; - u_int64_t TotalReadTime; - u_int64_t TotalWriteTime; + uint64_t TotalReadTime; + uint64_t TotalWriteTime; }; @@ -103,17 +104,17 @@ struct drivestats struct netstats { - char tname_unit[MAX_TNAME_UNIT_SIZE + 1]; - unsigned long gen_counter; /* unit generation counter */ + char tname_unit[MAX_TNAME_UNIT_SIZE + 1]; + uint32_t gen_counter; /* unit generation counter */ - unsigned long long net_ipackets; - unsigned long long net_ierrors; - unsigned long long net_opackets; - unsigned long long net_oerrors; - unsigned long long net_collisions; - unsigned long long net_ibytes; - unsigned long long net_obytes; - unsigned long long net_imcasts; - unsigned long long net_omcasts; - unsigned long long net_drops; + uint64_t net_ipackets; + uint64_t net_ierrors; + uint64_t net_opackets; + uint64_t net_oerrors; + uint64_t net_collisions; + uint64_t net_ibytes; + uint64_t net_obytes; + uint64_t net_imcasts; + uint64_t net_omcasts; + uint64_t net_drops; }; diff --git a/sar.tproj/Makefile b/sar.tproj/Makefile index e00833b..ec59ecc 100644 --- a/sar.tproj/Makefile +++ b/sar.tproj/Makefile @@ -5,6 +5,9 @@ HFILES = sar.h CFILES = sar.c MANPAGES = sar.1 -Extra_CC_Flags = -I. -I../sadc.tproj +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -I. -I../sadc.tproj include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sar.tproj/sar.c b/sar.tproj/sar.c index 1f046c0..678914c 100644 --- a/sar.tproj/sar.c +++ b/sar.tproj/sar.c @@ -19,7 +19,7 @@ */ /* - cc -Wall -Wno-long-double -I. -I ../sadc.tproj -O -o sar sar.c + cc -Wall -I. -I ../sadc.tproj -O -o sar sar.c */ #include @@ -148,7 +148,7 @@ static void read_record_hdr(struct record_hdr *hdr, int writeflag); static void read_record_data(char *buf, size_t size, int writeflag); static void write_record_hdr(struct record_hdr *hdr); static void write_record_data(char *buf, size_t size); -static long convert_hms(char *string); +static time_t convert_hms(char *string); static char *get_hms_string(time_t, char *); static int find_restart_header(struct record_hdr *); static void print_all_column_headings (time_t timestamp); diff --git a/sar.tproj/sar.h b/sar.tproj/sar.h index cd555f9..2ff405e 100644 --- a/sar.tproj/sar.h +++ b/sar.tproj/sar.h @@ -29,109 +29,107 @@ struct drivestats_report { - char *next; - int present; - int avg_count; - int drivepath_id; - char name[MAXDRIVENAME+1]; - u_int64_t blocksize; - - u_int64_t cur_Reads; - u_int64_t prev_Reads; - u_int64_t avg_Reads; - - u_int64_t cur_BytesRead; - u_int64_t prev_BytesRead; - u_int64_t avg_BytesRead; + char *next; + int32_t present; + int32_t avg_count; + int32_t drivepath_id; + char name[MAXDRIVENAME+1]; + uint64_t blocksize; + + uint64_t cur_Reads; + uint64_t prev_Reads; + uint64_t avg_Reads; + + uint64_t cur_BytesRead; + uint64_t prev_BytesRead; + uint64_t avg_BytesRead; - u_int64_t cur_Writes; - u_int64_t prev_Writes; - u_int64_t avg_Writes; + uint64_t cur_Writes; + uint64_t prev_Writes; + uint64_t avg_Writes; - u_int64_t cur_BytesWritten; - u_int64_t prev_BytesWritten; - u_int64_t avg_BytesWritten; + uint64_t cur_BytesWritten; + uint64_t prev_BytesWritten; + uint64_t avg_BytesWritten; - u_int64_t cur_LatentReadTime; - u_int64_t prev_LatentReadTime; - u_int64_t avg_LatentReadTime; + uint64_t cur_LatentReadTime; + uint64_t prev_LatentReadTime; + uint64_t avg_LatentReadTime; - u_int64_t cur_LatentWriteTime; - u_int64_t prev_LatentWriteTime; - u_int64_t avg_LatentWriteTime; + uint64_t cur_LatentWriteTime; + uint64_t prev_LatentWriteTime; + uint64_t avg_LatentWriteTime; - u_int64_t cur_ReadErrors; - u_int64_t prev_ReadErrors; - u_int64_t avg_ReadErrors; + uint64_t cur_ReadErrors; + uint64_t prev_ReadErrors; + uint64_t avg_ReadErrors; - u_int64_t cur_WriteErrors; - u_int64_t prev_WriteErrors; - u_int64_t avg_WriteErrors; + uint64_t cur_WriteErrors; + uint64_t prev_WriteErrors; + uint64_t avg_WriteErrors; - u_int64_t cur_ReadRetries; - u_int64_t prev_ReadRetries; - u_int64_t avg_ReadRetries; + uint64_t cur_ReadRetries; + uint64_t prev_ReadRetries; + uint64_t avg_ReadRetries; - u_int64_t cur_WriteRetries; - u_int64_t prev_WriteRetries; - u_int64_t avg_WriteRetries; + uint64_t cur_WriteRetries; + uint64_t prev_WriteRetries; + uint64_t avg_WriteRetries; - u_int64_t cur_TotalReadTime; - u_int64_t prev_TotalReadTime; - u_int64_t avg_TotalReadTime; + uint64_t cur_TotalReadTime; + uint64_t prev_TotalReadTime; + uint64_t avg_TotalReadTime; - u_int64_t cur_TotalWriteTime; - u_int64_t prev_TotalWriteTime; - u_int64_t avg_TotalWriteTime; + uint64_t cur_TotalWriteTime; + uint64_t prev_TotalWriteTime; + uint64_t avg_TotalWriteTime; }; struct netstats_report { - int valid; - int present; - int avg_count; - unsigned long gen_counter; - char tname_unit[MAX_TNAME_UNIT_SIZE +1 ]; + int32_t valid; + int32_t present; + int32_t avg_count; + uint32_t gen_counter; + char tname_unit[MAX_TNAME_UNIT_SIZE +1 ]; - unsigned long long cur_ipackets; - unsigned long long prev_ipackets; - unsigned long long avg_ipackets; + uint64_t cur_ipackets; + uint64_t prev_ipackets; + uint64_t avg_ipackets; - unsigned long long cur_ierrors; - unsigned long long prev_ierrors; - unsigned long long avg_ierrors; + uint64_t cur_ierrors; + uint64_t prev_ierrors; + uint64_t avg_ierrors; - unsigned long long cur_opackets; - unsigned long long prev_opackets; - unsigned long long avg_opackets; + uint64_t cur_opackets; + uint64_t prev_opackets; + uint64_t avg_opackets; - unsigned long long cur_oerrors; - unsigned long long prev_oerrors; - unsigned long long avg_oerrors; + uint64_t cur_oerrors; + uint64_t prev_oerrors; + uint64_t avg_oerrors; - unsigned long long cur_collisions; - unsigned long long prev_collisions; - unsigned long long avg_collisions; + uint64_t cur_collisions; + uint64_t prev_collisions; + uint64_t avg_collisions; - unsigned long long cur_ibytes; - unsigned long long prev_ibytes; - unsigned long long avg_ibytes; + uint64_t cur_ibytes; + uint64_t prev_ibytes; + uint64_t avg_ibytes; - unsigned long long cur_obytes; - unsigned long long prev_obytes; - unsigned long long avg_obytes; + uint64_t cur_obytes; + uint64_t prev_obytes; + uint64_t avg_obytes; - unsigned long long cur_imcasts; - unsigned long long prev_imcasts; - unsigned long long avg_imcasts; + uint64_t cur_imcasts; + uint64_t prev_imcasts; + uint64_t avg_imcasts; - unsigned long long cur_omcasts; - unsigned long long prev_omcasts; - unsigned long long avg_omcasts; + uint64_t cur_omcasts; + uint64_t prev_omcasts; + uint64_t avg_omcasts; - unsigned long long cur_drops; - unsigned long long prev_drops; - unsigned long long avg_drops; - - + uint64_t cur_drops; + uint64_t prev_drops; + uint64_t avg_drops; }; diff --git a/sc_usage.tproj/Makefile b/sc_usage.tproj/Makefile index f96a032..22818ac 100644 --- a/sc_usage.tproj/Makefile +++ b/sc_usage.tproj/Makefile @@ -4,10 +4,12 @@ Install_Dir = /usr/bin CFILES = sc_usage.c MANPAGES = sc_usage.1 -Extra_LD_Flags = -lcurses +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip -Extra_CC_Flags = -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ +Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd +Extra_LD_Flags += -lcurses -lutil include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sc_usage.tproj/sc_usage.c b/sc_usage.tproj/sc_usage.c index 9000d6c..5e7f768 100644 --- a/sc_usage.tproj/sc_usage.c +++ b/sc_usage.tproj/sc_usage.c @@ -59,7 +59,7 @@ cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o sc_usage sc_usage.c -lncurses #include #include #include - +#include /* Number of lines of header information on the standard screen */ #define HEADER_LINES 5 @@ -218,6 +218,8 @@ void quit(char *); int argtopid(char *); int argtoi(int, char*, char*, int); +void get_bufinfo(kbufinfo_t *); + /* * signal handlers @@ -291,11 +293,11 @@ void print_time(char *p, unsigned int useconds, unsigned int seconds) hours = minutes / 60; if (minutes < 100) { // up to 100 minutes - sprintf(p, "%2ld:%02ld.%03ld", minutes, (unsigned long)(seconds % 60), + sprintf(p, "%02ld:%02ld.%03ld", minutes, (unsigned long)(seconds % 60), (unsigned long)usec_to_1000ths(useconds)); } else if (hours < 100) { // up to 100 hours - sprintf(p, "%2ld:%02ld:%02ld ", hours, (minutes % 60), + sprintf(p, "%02ld:%02ld:%02ld ", hours, (minutes % 60), (unsigned long)(seconds % 60)); } else { @@ -324,6 +326,11 @@ main(argc, argv) exit(1); } + if (0 != reexec_to_match_kernel()) { + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); + } + /* get our name */ if (argc > 0) { if ((myname = rindex(argv[0], '/')) == 0) { @@ -448,8 +455,6 @@ main(argc, argv) topn = 1024; COLS = 80; } - if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0) - quit("can't allocate memory for tracing info\n"); set_remove(); set_numbufs(SAMPLE_SIZE); @@ -465,6 +470,12 @@ main(argc, argv) if ((sort_now = 10 / delay) < 2) sort_now = 2; + get_bufinfo(&bufinfo); + + my_buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf)); + if(my_buffer == (char *) 0) + quit("can't allocate memory for tracing info\n"); + (void)sort_scalls(); (void)screen_update(); @@ -549,11 +560,6 @@ print_row(struct sc_entry *se, int no_wtime) { } } sprintf(&tbuf[clen], "\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -628,11 +634,6 @@ void screen_update() clen = 78 - 8; sprintf(&tbuf[clen], "%-8.8s\n", &(ctime(&curr_time)[11])); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -652,11 +653,6 @@ void screen_update() clen = strlen(tbuf); sprintf(&tbuf[clen], " %3ld:%02ld:%02ld\n", (long)hours, (long)(minutes % 60), (long)(elapsed_secs % 60)); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -664,22 +660,13 @@ void screen_update() - sprintf(tbuf, "\nTYPE NUMBER CPU_TIME WAIT_TIME\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } + sprintf(tbuf, "\nTYPE NUMBER CPU_TIME WAIT_TIME\n"); if (no_screen_refresh) printf("%s", tbuf); else printw(tbuf); sprintf(tbuf, "------------------------------------------------------------------------------\n"); - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -706,11 +693,6 @@ void screen_update() clen += strlen(&tbuf[clen]); } sprintf(&tbuf[clen], "\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -737,11 +719,6 @@ void screen_update() clen += strlen(&tbuf[clen]); } sprintf(&tbuf[clen], "\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -754,12 +731,8 @@ void screen_update() print_time(&tbuf[clen], (unsigned long)(utime_usecs), utime_secs); clen += strlen(&tbuf[clen]); - sprintf(&tbuf[clen], "\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } + + sprintf(&tbuf[clen], "\n"); if (no_screen_refresh) printf("%s", tbuf); else @@ -809,31 +782,24 @@ void screen_update() print_row(&sc_tab[n], 0); rows++; } - if (no_screen_refresh == 0) { - sprintf(tbuf, "\n"); + + sprintf(tbuf, "\n"); + if (no_screen_refresh == 0) { while (rows++ < max_rows) printw(tbuf); } else - printf("\n"); + printf("%s", tbuf); if (num_of_threads) { sprintf(tbuf, "\nCURRENT_TYPE LAST_PATHNAME_WAITED_FOR CUR_WAIT_TIME THRD# PRI\n"); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } + if (no_screen_refresh) printf("%s", tbuf); else printw(tbuf); sprintf(tbuf, "------------------------------------------------------------------------------\n"); - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } if (no_screen_refresh) printf("%s", tbuf); else @@ -874,11 +840,11 @@ void screen_update() p = (char *)ti->pathname; plen = strlen(p); - if (plen > 34) - plen -= 34; + if (plen > 26) + plen -= 26; else plen = 0; - sprintf(&tbuf[clen], " %-34.34s ", &p[plen]); + sprintf(&tbuf[clen], " %-26.26s ", &p[plen]); clen += strlen(&tbuf[clen]); @@ -889,12 +855,7 @@ void screen_update() print_time(&tbuf[clen], time_usecs, time_secs); clen += strlen(&tbuf[clen]); - sprintf(&tbuf[clen], " %2d %3d\n", i, ti->curpri); - - if (tbuf[COLS-2] != '\n') { - tbuf[COLS-1] = '\n'; - tbuf[COLS] = 0; - } + sprintf(&tbuf[clen], " %2d %3d\n", i, ti->curpri); if (no_screen_refresh) printf("%s", tbuf); else @@ -988,11 +949,7 @@ sc_tab_init(char *codefile) { printf("Failed to open code description file %s\n", codefile); exit(1); } - - n = fscanf(fp, "%d\n", &cnt); - if (n != 1) - return; - + /* Count Mach message MSG_ codes */ for (msgcode_cnt=0;;) { n = fscanf(fp, "%x%55s\n", &code, &name[0]); @@ -1000,7 +957,7 @@ sc_tab_init(char *codefile) { break; if (strncmp ("MSG_", &name[0], 4) == 0) msgcode_cnt++; - if (strcmp("USER_TEST", &name[0]) == 0) + if (strcmp("TRACE_LAST_WRAPPER", &name[0]) == 0) break; } @@ -1026,12 +983,7 @@ sc_tab_init(char *codefile) { rewind(fp); - - n = fscanf(fp, "%d\n", &cnt); - - if (n != 1) - return; - + for (;;) { n = fscanf(fp, "%x%55s\n", &code, &name[0]); @@ -1087,7 +1039,7 @@ sc_tab_init(char *codefile) { strcpy(&sc_tab[n].name[0], &name[4]); continue; } - if (strcmp("USER_TEST", &name[0]) == 0) + if (strcmp("TRACE_LAST_WRAPPER", &name[0]) == 0) break; } strcpy(&faults[1].name[0], "zero_fill"); @@ -1326,7 +1278,7 @@ set_remove() set_remove_flag = 0; if (errno == EBUSY) - quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); + quit("The trace facility is currently in use...\n Note: fs_usage, sc_usage, and latency use this feature.\n\n"); else quit("trace facility failure, KERN_KDREMOVE\n"); } @@ -1367,21 +1319,25 @@ sample_sc() int i, count; int secs; int find_msgcode(); - - /* Get kernel buffer information */ - get_bufinfo(&bufinfo); + + int reenable; + #ifdef OLD_KDEBUG set_enable(0); #endif + get_bufinfo(&bufinfo); + needed = bufinfo.nkdbufs * sizeof(kd_buf); mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDREADTR\n"); + mib[2] = KERN_KDREADTR; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + + if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDREADTR\n"); + count = needed; if (bufinfo.flags & KDBG_WRAPPED) { @@ -1394,6 +1350,7 @@ sample_sc() } num_of_threads = 0; } + #ifdef OLD_KDEBUG set_remove(); set_init(); @@ -1747,9 +1704,17 @@ quit(char *s) if (set_remove_flag) set_remove(); + if (no_screen_refresh == 0) { + /* clear for new display */ + erase(); + move(0, 0); + refresh(); + endwin(); + } + printf("sc_usage: "); if (s) - printf("%s ", s); + printf("%s", s); exit(1); } diff --git a/sc_usage.tproj/trace.codes b/sc_usage.tproj/trace.codes index 383ff50..c9ff79b 100644 --- a/sc_usage.tproj/trace.codes +++ b/sc_usage.tproj/trace.codes @@ -1,67 +1,66 @@ -1346 -0x1f000000 DYLD_initialize -0x1f010000 DYLD_CALL_image_init_routine -0x1f010004 DYLD_CALL_dependent_init_routine -0x1f010008 DYLD_CALL_lazy_init_routine -0x1f01000c DYLD_CALL_module_init_for_library -0x1f010010 DYLD_CALL_module_init_for_object -0x1f010014 DYLD_CALL_module_terminator_for_object -0x1f010018 DYLD_CALL_module_init_for_dylib -0x1f01001c DYLD_CALL_mod_term_func -0x1f010020 DYLD_CALL_object_func -0x1f010024 DYLD_CALL_library_func -0x1f010028 DYLD_CALL_add_image_func -0x1f01002c DYLD_CALL_remove_image_func -0x1f010030 DYLD_CALL_link_object_module_func -0x1f010034 DYLD_CALL_link_library_module_func -0x1f010038 DYLD_CALL_link_module_func -0x1f020000 DYLD_lookup_and_bind_with_hint -0x1f020004 DYLD_lookup_and_bind_fully -0x1f020008 DYLD_link_module -0x1f02000c DYLD_ulink_module -0x1f020010 DYLD_bind_objc_module -0x1f020014 DYLD_bind_fully_image_containing_address -0x1f020018 DYLD_make_delayed_module_initializer_calls -0x1f02001c DYLD_NSNameOfSymbol -0x1f020020 DYLD_NSAddressOfSymbol -0x1f020024 DYLD_NSModuleForSymbol -0x1f020028 DYLD_NSLookupAndBindSymbolWithHint -0x1f02002c DYLD_NSLookupSymbolInModule -0x1f020030 DYLD_NSLookupSymbolInImage -0x1f020034 DYLD_NSIsSymbolNameDefined -0x1f020038 DYLD_NSIsSymbolNameDefinedWithHint -0x1f02003c DYLD_NSIsSymbolNameDefinedInImage -0x1f020040 DYLD_NSNameOfModule -0x1f020044 DYLD_NSLibraryNameForModule -0x1f020048 DYLD_NSAddLibrary -0x1f02004c DYLD_NSAddLibraryWithSearching -0x1f020050 DYLD_NSAddImage -0x1f030000 DYLD_lookup_symbol -0x1f030004 DYLD_bind_lazy_symbol_reference -0x1f030008 DYLD_bind_symbol_by_name -0x1f03000c DYLD_link_in_need_modules -0x1f040000 DYLD_map_image -0x1f040004 DYLD_load_executable_image -0x1f040008 DYLD_load_library_image -0x1f04000c DYLD_map_library_image -0x1f040010 DYLD_map_bundle_image -0x1f040014 DYLD_load_dependent_libraries -0x1f040018 DYLD_notify_prebinding_agent -0x21060000 LAUNCH_CPSTraceLineNum -0x21060004 LAUNCH_CPSLaunch -0x21060008 LAUNCH_CPSRegisterwithServer -0x2106000c LAUNCH_CPSCheckInNewProcess -0x21060010 LAUNCH_CPSServerSideLaunch -0x21060014 LAUNCH_CPSExecProcess -0x21070000 LAUNCH_LSOpen -0x21070004 LAUNCH_LSRegisterItem +0x1f000000 DYLD_initialize +0x1f010000 DYLD_CALL_image_init_routine +0x1f010004 DYLD_CALL_dependent_init_routine +0x1f010008 DYLD_CALL_lazy_init_routine +0x1f01000c DYLD_CALL_module_init_for_library +0x1f010010 DYLD_CALL_module_init_for_object +0x1f010014 DYLD_CALL_module_terminator_for_object +0x1f010018 DYLD_CALL_module_init_for_dylib +0x1f01001c DYLD_CALL_mod_term_func +0x1f010020 DYLD_CALL_object_func +0x1f010024 DYLD_CALL_library_func +0x1f010028 DYLD_CALL_add_image_func +0x1f01002c DYLD_CALL_remove_image_func +0x1f010030 DYLD_CALL_link_object_module_func +0x1f010034 DYLD_CALL_link_library_module_func +0x1f010038 DYLD_CALL_link_module_func +0x1f020000 DYLD_lookup_and_bind_with_hint +0x1f020004 DYLD_lookup_and_bind_fully +0x1f020008 DYLD_link_module +0x1f02000c DYLD_ulink_module +0x1f020010 DYLD_bind_objc_module +0x1f020014 DYLD_bind_fully_image_containing_address +0x1f020018 DYLD_make_delayed_module_initializer_calls +0x1f02001c DYLD_NSNameOfSymbol +0x1f020020 DYLD_NSAddressOfSymbol +0x1f020024 DYLD_NSModuleForSymbol +0x1f020028 DYLD_NSLookupAndBindSymbolWithHint +0x1f02002c DYLD_NSLookupSymbolInModule +0x1f020030 DYLD_NSLookupSymbolInImage +0x1f020034 DYLD_NSIsSymbolNameDefined +0x1f020038 DYLD_NSIsSymbolNameDefinedWithHint +0x1f02003c DYLD_NSIsSymbolNameDefinedInImage +0x1f020040 DYLD_NSNameOfModule +0x1f020044 DYLD_NSLibraryNameForModule +0x1f020048 DYLD_NSAddLibrary +0x1f02004c DYLD_NSAddLibraryWithSearching +0x1f020050 DYLD_NSAddImage +0x1f030000 DYLD_lookup_symbol +0x1f030004 DYLD_bind_lazy_symbol_reference +0x1f030008 DYLD_bind_symbol_by_name +0x1f03000c DYLD_link_in_need_modules +0x1f040000 DYLD_map_image +0x1f040004 DYLD_load_executable_image +0x1f040008 DYLD_load_library_image +0x1f04000c DYLD_map_library_image +0x1f040010 DYLD_map_bundle_image +0x1f040014 DYLD_load_dependent_libraries +0x1f040018 DYLD_notify_prebinding_agent +0x21060000 LAUNCH_CPSTraceLineNum +0x21060004 LAUNCH_CPSLaunch +0x21060008 LAUNCH_CPSRegisterwithServer +0x2106000c LAUNCH_CPSCheckInNewProcess +0x21060010 LAUNCH_CPSServerSideLaunch +0x21060014 LAUNCH_CPSExecProcess +0x21070000 LAUNCH_LSOpen +0x21070004 LAUNCH_LSRegisterItem 0x21070008 LAUNCH_LSGetApplicationAndFlagsForInfo -0x1fff0000 LAUNCH_START_FINDER -0x1fff0100 LAUNCH_START_DOCK -0x1fff0310 LAUNCH_APP_EnterEventLoop -0x1fff0314 LAUNCH_APP_WillOpenUntitled -0x1fff031c LAUNCH_APP_DidOpenUntitled -0x1fffffff LAUNCH_END +0x1fff0000 LAUNCH_START_FINDER +0x1fff0100 LAUNCH_START_DOCK +0x1fff0310 LAUNCH_APP_EnterEventLoop +0x1fff0314 LAUNCH_APP_WillOpenUntitled +0x1fff031c LAUNCH_APP_DidOpenUntitled +0x1fffffff LAUNCH_END 0xff000104 MSG_mach_notify_port_deleted 0xff000114 MSG_mach_notify_port_destroyed 0xff000118 MSG_mach_notify_no_senders @@ -219,15 +218,15 @@ 0xff002cac MSG_io_service_add_notification_ool 0xff002cb0 MSG_io_object_get_superclass 0xff002cb4 MSG_io_object_get_bundle_identifier -0xff002cb8 MSG_io_service_open_extended -0xff002cbc MSG_io_connect_map_memory_into_task -0xff002cc0 MSG_io_connect_unmap_memory_from_task -0xff002cc4 MSG_io_connect_method -0xff002cc8 MSG_io_connect_async_method -0xff002ccc MSG_io_connect_set_notification_port_64 -0xff002cd0 MSG_io_service_add_notification_64 -0xff002cd4 MSG_io_service_add_interest_notification_64 -0xff002cd8 MSG_io_service_add_notification_ool_64 +0xff002cb8 MSG_io_service_open_extended +0xff002cbc MSG_io_connect_map_memory_into_task +0xff002cc0 MSG_io_connect_unmap_memory_from_task +0xff002cc4 MSG_io_connect_method +0xff002cc8 MSG_io_connect_async_method +0xff002ccc MSG_io_connect_set_notification_port_64 +0xff002cd0 MSG_io_service_add_notification_64 +0xff002cd4 MSG_io_service_add_interest_notification_64 +0xff002cd8 MSG_io_service_add_notification_ool_64 0xff002ee0 MSG_processor_start 0xff002ee4 MSG_processor_exit 0xff002ee8 MSG_processor_info @@ -374,6 +373,7 @@ 0xff004b3c MSG_mach_vm_region_recurse 0xff004b40 MSG_mach_vm_region 0xff004b44 MSG__mach_make_memory_entry +0xff004b48 MSG__mach_vm_purgable_control 0xff004e20 MSG_ledger_create 0xff004e24 MSG_ledger_terminate 0xff004e28 MSG_ledger_transfer @@ -402,65 +402,69 @@ 0xff25abd4 MSG_semaphore_wait_signal 0xff25abd8 MSG_semaphore_timedwait_signal 0xffbebdcc MSG_clock_alarm_reply -0x1020000 KTrap_DivideError -0x1020004 KTrap_Debug -0x1020008 KTrap_NMI -0x102000c KTrap_Int3 -0x1020010 KTrap_Overflow -0x1020014 KTrap_BoundRange -0x1020018 KTrap_InvalidOpcode -0x102001c KTrap_DeviceNotAvail -0x1020020 KTrap_DoubleFault -0x1020024 KTrap_Coprocessor -0x1020028 KTrap_InvalidTSS -0x102002c KTrap_SegmentNotPresent -0x1020030 KTrap_StackFault -0x1020034 KTrap_GeneralProtection -0x1020038 KTrap_PageFault -0x102003c KTrap_unknown -0x1020040 KTrap_FloatPointError -0x1020044 KTrap_AlignmentCheck -0x1020048 KTrap_MachineCheck -0x102004c KTrap_SIMD_FP -0x10203fc KTrap_Preempt -0x1070000 UTrap_DivideError -0x1070004 UTrap_Debug -0x1070008 UTrap_NMI -0x107000c UTrap_Int3 -0x1070010 UTrap_Overflow -0x1070014 UTrap_BoundRange -0x1070018 UTrap_InvalidOpcode -0x107001c UTrap_DeviceNotAvail -0x1070020 UTrap_DoubleFault -0x1070024 UTrap_Coprocessor -0x1070028 UTrap_InvalidTSS -0x107002c UTrap_SegmentNotPresent -0x1070030 UTrap_StackFault -0x1070034 UTrap_GeneralProtection -0x1070038 UTrap_PageFault -0x107003c UTrap_unknown -0x1070040 UTrap_FloatPointError -0x1070044 UTrap_AlignmentCheck -0x1070048 UTrap_MachineCheck -0x107004c UTrap_SIMD_FP +0x1020000 KTrap_DivideError +0x1020004 KTrap_Debug +0x1020008 KTrap_NMI +0x102000c KTrap_Int3 +0x1020010 KTrap_Overflow +0x1020014 KTrap_BoundRange +0x1020018 KTrap_InvalidOpcode +0x102001c KTrap_DeviceNotAvail +0x1020020 KTrap_DoubleFault +0x1020024 KTrap_Coprocessor +0x1020028 KTrap_InvalidTSS +0x102002c KTrap_SegmentNotPresent +0x1020030 KTrap_StackFault +0x1020034 KTrap_GeneralProtection +0x1020038 KTrap_PageFault +0x102003c KTrap_unknown +0x1020040 KTrap_FloatPointError +0x1020044 KTrap_AlignmentCheck +0x1020048 KTrap_MachineCheck +0x102004c KTrap_SIMD_FP +0x10203fc KTrap_Preempt +0x1070000 UTrap_DivideError +0x1070004 UTrap_Debug +0x1070008 UTrap_NMI +0x107000c UTrap_Int3 +0x1070010 UTrap_Overflow +0x1070014 UTrap_BoundRange +0x1070018 UTrap_InvalidOpcode +0x107001c UTrap_DeviceNotAvail +0x1070020 UTrap_DoubleFault +0x1070024 UTrap_Coprocessor +0x1070028 UTrap_InvalidTSS +0x107002c UTrap_SegmentNotPresent +0x1070030 UTrap_StackFault +0x1070034 UTrap_GeneralProtection +0x1070038 UTrap_PageFault +0x107003c UTrap_unknown +0x1070040 UTrap_FloatPointError +0x1070044 UTrap_AlignmentCheck +0x1070048 UTrap_MachineCheck +0x107004c UTrap_SIMD_FP 0x1300004 MACH_Pageout 0x1300008 MACH_vmfault +0x1300100 MACH_purgable_token_add +0x1300104 MACH_purgable_token_delete +0x1300108 MACH_purgable_token_ripened +0x130010c MACH_purgable_token_purged 0x1400000 MACH_SCHED -0x1400004 MACH_STKATTACH +0x1400004 MACH_STKATTACH 0x1400008 MACH_STKHANDOFF -0x140000c MACH_CALLCONT -0x1400010 MACH_CALLOUT -0x1400014 MACH_ServiceT +0x140000c MACH_CALLCONT +0x1400010 MACH_CALLOUT +0x1400014 MACH_ServiceT 0x1400018 MACH_MKRUNNABLE -0x140001c MACH_PROMOTE -0x1400020 MACH_DEMOTE +0x140001c MACH_PROMOTE +0x1400020 MACH_DEMOTE 0x1400024 MACH_IDLE 0x1500000 MACH_MSGID_INVALID 0x1090000 DecrTrap 0x1090004 DecrSet -0x1090008 TimerCallIntr -0x109000c pmsStep -0x1090010 clock_deadline +0x1090008 TimerCallIntr +0x109000c pmsStep +0x1090010 clock_deadline 0x10c0000 MACH_SysCall 0x10c0004 MSC_kern_invalid_#1 0x10c0008 MSC_kern_invalid_#2 @@ -492,7 +496,7 @@ 0x10c0070 MSC_task_self_trap 0x10c0074 MSC_host_self_trap 0x10c0078 MSC_kern_invalid_#30 -0x10c007c MSC_mach_msg_trap +0x10c007c MSC_mach_msg_trap 0x10c0080 MSC_mach_msg_overwrite_trap 0x10c0084 MSC_semaphore_signal_trap 0x10c0088 MSC_semaphore_signal_all_trap @@ -513,8 +517,8 @@ 0x10c00c4 MSC_macx_swapoff 0x10c00c8 MSC_kern_invalid_#50 0x10c00cc MSC_macx_triggers -0x10c00d0 MSC_macx_backing_store_suspend -0x10c00d4 MSC_macx_backing_store_recovery +0x10c00d0 MSC_kern_invalid_#52 +0x10c00d4 MSC_kern_invalid_#53 0x10c00d8 MSC_kern_invalid_#54 0x10c00dc MSC_kern_invalid_#55 0x10c00e0 MSC_kern_invalid_#56 @@ -561,7 +565,7 @@ 0x10c0184 MSC_kern_invalid_#97 0x10c0188 MSC_kern_invalid_#98 0x10c018c MSC_kern_invalid_#99 -0x10c0190 MSC_iokit_user_client_trap +0x10c0190 MSC_audio_fast_trap 0x10c0194 MSC_kern_invalid_#101 0x10c0198 MSC_kern_invalid_#102 0x10c019c MSC_kern_invalid_#103 @@ -591,30 +595,33 @@ 0x10c01fc MSC_kern_invalid_#127 0x1050000 INTERRUPT 0x3010090 VFS_LOOKUP -0x3020000 P_WrData -0x3020008 P_RdData -0x3020020 P_WrMeta -0x3020028 P_RdMeta -0x3020040 P_PgOut -0x3020048 P_PgIn -0x3020010 P_WrDataAsync -0x3020018 P_RdDataAsync -0x3020030 P_WrMetaAsync -0x3020038 P_RdMetaAsync -0x3020050 P_PgOutAsync -0x3020058 P_PgInAsync -0x3020004 P_WrDataDone -0x302000C P_RdDataDone -0x3020024 P_WrMetaDone -0x302002C P_RdMetaDone -0x3020044 P_PgOutDone -0x302004C P_PgInDone -0x3020014 P_WrDataAsyncDone -0x302001C P_RdDataAsyncDone -0x3020034 P_WrMetaAsyncDone -0x302003C P_RdMetaAsyncDone -0x3020054 P_PgOutAsyncDone -0x302005C P_PgInAsyncDone +0x3020000 P_WrData +0x3020008 P_RdData +0x3020020 P_WrMeta +0x3020028 P_RdMeta +0x3020040 P_PgOut +0x3020048 P_PgIn +0x3020010 P_WrDataAsync +0x3020018 P_RdDataAsync +0x3020030 P_WrMetaAsync +0x3020038 P_RdMetaAsync +0x3020050 P_PgOutAsync +0x3020058 P_PgInAsync +0x3020004 P_WrDataDone +0x302000C P_RdDataDone +0x3020024 P_WrMetaDone +0x302002C P_RdMetaDone +0x3020044 P_PgOutDone +0x302004C P_PgInDone +0x3020014 P_WrDataAsyncDone +0x302001C P_RdDataAsyncDone +0x3020034 P_WrMetaAsyncDone +0x302003C P_RdMetaAsyncDone +0x3020054 P_PgOutAsyncDone +0x302005C P_PgInAsyncDone +0x3050004 journal_flush +0x4010004 proc_exit +0x4010008 force_exit 0x40c0000 BSC_SysCall 0x40c0004 BSC_exit 0x40c0008 BSC_fork @@ -633,7 +640,7 @@ 0x40c003c BSC_chmod 0x40c0040 BSC_chown 0x40c0044 BSC_obs_break -0x40c0048 BSC_obs_getfsstat +0x40c0048 BSC_getfsstat 0x40c004c BSC_old_lseek 0x40c0050 BSC_getpid 0x40c0054 BSC_obs_mount @@ -660,7 +667,7 @@ 0x40c00a8 BSC_pipe 0x40c00ac BSC_getegid 0x40c00b0 BSC_profil -0x40c00b4 BSC_ktrace +0x40c00b4 BSC_obs_ktrace 0x40c00b8 BSC_sigaction 0x40c00bc BSC_getgid 0x40c00c0 BSC_sigprocmask @@ -692,16 +699,16 @@ 0x40c0124 BSC_munmap 0x40c0128 BSC_mprotect 0x40c012c BSC_madvise -0x40c0130 BSC_#76 -0x40c0134 BSC_#77 +0x40c0130 BSC_obs_vhangup +0x40c0134 BSC_obs_vlimit 0x40c0138 BSC_mincore 0x40c013c BSC_getgroups 0x40c0140 BSC_setgroups 0x40c0144 BSC_getpgrp 0x40c0148 BSC_setpgid 0x40c014c BSC_setitimer -0x40c0150 BSC_old_wait -0x40c0154 BSC_obs_swapon +0x40c0150 BSC_obs_wait +0x40c0154 BSC_swapon 0x40c0158 BSC_getitimer 0x40c015c BSC_obs_gethostname 0x40c0160 BSC_obs_sethostname @@ -717,9 +724,9 @@ 0x40c0188 BSC_connect 0x40c018c BSC_obs_accept 0x40c0190 BSC_getpriority -0x40c0194 BSC_old_send -0x40c0198 BSC_old_recv -0x40c019c BSC_sigreturn +0x40c0194 BSC_obs_send +0x40c0198 BSC_obs_recv +0x40c019c BSC_obs_sigreturn 0x40c01a0 BSC_bind 0x40c01a4 BSC_setsockopt 0x40c01a8 BSC_listen @@ -742,8 +749,8 @@ 0x40c01ec BSC_fchown 0x40c01f0 BSC_fchmod 0x40c01f4 BSC_obs_recvfrom -0x40c01f8 BSC_obs_setreuid -0x40c01fc BSC_obs_setregid +0x40c01f8 BSC_setreuid +0x40c01fc BSC_setregid 0x40c0200 BSC_rename 0x40c0204 BSC_obs_truncate 0x40c0208 BSC_obs_ftruncate @@ -758,7 +765,7 @@ 0x40c022c BSC_futimes 0x40c0230 BSC_adjtime 0x40c0234 BSC_obs_getpeername -0x40c0238 BSC_obs_gethostid +0x40c0238 BSC_gethostuuid 0x40c023c BSC_obs_sethostid 0x40c0240 BSC_obs_getrlimit 0x40c0244 BSC_obs_setrlimit @@ -770,11 +777,11 @@ 0x40c025c BSC_getpgid 0x40c0260 BSC_setprivexec 0x40c0264 BSC_pread -0x40e0264 BSC_pread_extended_info +0x40e0264 BSC_pread_extended_info 0x40c0268 BSC_pwrite -0x40e0268 BSC_pwrite_extended_info +0x40e0268 BSC_pwrite_extended_info 0x40c026c BSC_nfssvc -0x40c0270 BSC_getdirentries +0x40c0270 BSC_obs_getdirentries 0x40c0274 BSC_statfs 0x40c0278 BSC_fstatfs 0x40c027c BSC_unmount @@ -783,27 +790,27 @@ 0x40c0288 BSC_obs_getdomainname 0x40c028c BSC_obs_setdomainname 0x40c0290 BSC_#164 -0x40c0294 BSC_quotactl -0x40c0298 BSC_obs_exportfs -0x40c029c BSC_mount -0x40c02a0 BSC_obs_ustat -0x40c02a4 BSC_#169 -0x40c02a8 BSC_table -0x40c02ac BSC_obs_wait3 -0x40c02b0 BSC_obs_rpause -0x40c02b4 BSC_waitid -0x40c02b8 BSC_obs_getdents -0x40c02bc BSC_obs_gc_control -0x40c02c0 BSC_add_profil -0x40c02c4 BSC_#177 -0x40c02c8 BSC_#178 -0x40c02cc BSC_#179 -0x40c02d0 BSC_kdebug_trace -0x40c02d4 BSC_setgid -0x40c02d8 BSC_setegid -0x40c02dc BSC_seteuid -0x40c02e0 BSC_sigreturn -0x40c02e4 BSC_#185 +0x40c0294 BSC_quotactl +0x40c0298 BSC_obs_exportfs +0x40c029c BSC_mount +0x40c02a0 BSC_obs_ustat +0x40c02a4 BSC_csops +0x40c02a8 BSC_obs_table +0x40c02ac BSC_obs_wait3 +0x40c02b0 BSC_obs_rpause +0x40c02b4 BSC_waitid +0x40c02b8 BSC_obs_getdents +0x40c02bc BSC_obs_gc_control +0x40c02c0 BSC_add_profil +0x40c02c4 BSC_#177 +0x40c02c8 BSC_#178 +0x40c02cc BSC_#179 +0x40c02d0 BSC_kdebug_trace +0x40c02d4 BSC_setgid +0x40c02d8 BSC_setegid +0x40c02dc BSC_seteuid +0x40c02e0 BSC_sigreturn +0x40c02e4 BSC_chud 0x40c02e8 BSC_#186 0x40c02ec BSC_#187 0x40c02f0 BSC_stat @@ -811,7 +818,7 @@ 0x40c02f8 BSC_lstat 0x40c02fc BSC_pathconf 0x40c0300 BSC_fpathconf -0x40c0304 BSC_obs_getfsstat +0x40c0304 BSC_#193 0x40c0308 BSC_getrlimit 0x40c030c BSC_setrlimit 0x40c0310 BSC_getdirentries @@ -834,19 +841,19 @@ 0x40c034c BSC_ATPgetreq 0x40c0350 BSC_ATPgetrsp 0x40c0354 BSC_#213 -0x40c0358 BSC_kqueue_from_portset_np -0x40c035c BSC_kqueue_portset_np -0x40c0360 BSC_mkcomplex -0x40c0364 BSC_statv -0x40c0368 BSC_lstatv -0x40c036c BSC_fstatv +0x40c0358 BSC_kqueue_from_portset_np +0x40c035c BSC_kqueue_portset_np +0x40c0360 BSC_mkcomplex +0x40c0364 BSC_statv +0x40c0368 BSC_lstatv +0x40c036c BSC_fstatv 0x40c0370 BSC_getattrlist 0x40c0374 BSC_setattrlist 0x40c0378 BSC_getdirentriesattr 0x40c037c BSC_exchangedata -0x40c0380 BSC_checkuseraccess +0x40c0380 BSC_224 0x40c0384 BSC_searchfs -0x40c0388 BSC_delete +0x40c0388 BSC_delete_Carbon 0x40c038c BSC_copyfile 0x40c0390 BSC_#228 0x40c0394 BSC_#229 @@ -854,17 +861,17 @@ 0x40c039c BSC_watchevent 0x40c03a0 BSC_waitevent 0x40c03a4 BSC_modwatch -0x40c03a8 BSC_getxattr -0x40c03ac BSC_fgetxattr -0x40c03b0 BSC_setxattr -0x40c03b4 BSC_fsetxattr -0x40c03b8 BSC_removexattr -0x40c03bc BSC_fremovexattr -0x40c03c0 BSC_listxattr -0x40c03c4 BSC_flistxattr +0x40c03a8 BSC_getxattr +0x40c03ac BSC_fgetxattr +0x40c03b0 BSC_setxattr +0x40c03b4 BSC_fsetxattr +0x40c03b8 BSC_removexattr +0x40c03bc BSC_fremovexattr +0x40c03c0 BSC_listxattr +0x40c03c4 BSC_flistxattr 0x40c03c8 BSC_fsctl -0x40c03cc BSC_#243 -0x40c03d0 BSC_#244 +0x40c03cc BSC_initgroups +0x40c03d0 BSC_posix_spawn 0x40c03d4 BSC_#245 0x40c03d8 BSC_#246 0x40c03dc BSC_nfsclnt @@ -877,7 +884,7 @@ 0x40c03f8 BSC_semctl 0x40c03fc BSC_semget 0x40c0400 BSC_semop -0x40c0404 BSC_semconfig +0x40c0404 BSC_#257 0x40c0408 BSC_msgctl 0x40c040c BSC_msgget 0x40c0410 BSC_msgsnd @@ -913,33 +920,33 @@ 0x40c0488 BSC_getwgroups 0x40c048c BSC_mkfifo_extended 0x40c0490 BSC_mkdir_extended -0x40c0494 BSC_identifysvc -0x40c0498 BSC_#294 -0x40c049c BSC_#295 -0x40c04a0 BSC_load_shared_file -0x40c04a4 BSC_reset_shared_file -0x40c04a8 BSC_new_system_shared_regions -0x40c04ac BSC_shared_region_map_file_np -0x40c04b0 BSC_shared_region_make_private_np -0x40c04b4 BSC_#301 -0x40c04b8 BSC_#302 -0x40c04bc BSC_#303 -0x40c04c0 BSC_#304 -0x40c04c4 BSC_#305 -0x40c04c8 BSC_#306 -0x40c04cc BSC_#307 -0x40c04d0 BSC_#308 -0x40c04d4 BSC_#309 +0x40c0494 BSC_identitysvc +0x40c0498 BSC_shared_region_chk_np +0x40c049c BSC_shared_region_map_np +0x40c04a0 BSC_obs_load_shared_file +0x40c04a4 BSC_obs_reset_shared_file +0x40c04a8 BSC_obs_new_system_shared_regions +0x40c04ac BSC_obs_shared_region_map_file_np +0x40c04b0 BSC_obs_shared_region_make_private_np +0x40c04b4 BSC_pthread_mutex_destroy +0x40c04b8 BSC_pthread_mutex_init +0x40c04bc BSC_pthread_mutex_lock +0x40c04c0 BSC_pthread_mutex_trylock +0x40c04c4 BSC_pthread_mutex_unlock +0x40c04c8 BSC_pthread_cond_init +0x40c04cc BSC_pthread_cond_destroy +0x40c04d0 BSC_pthread_cond_broadcast +0x40c04d4 BSC_pthread_cond_signal 0x40c04d8 BSC_getsid 0x40c04dc BSC_settid_with_pid -0x40c04e0 BSC_#312 -0x40c04e4 BSC_aio_fsync -0x40c04e8 BSC_aio_return -0x40c04ec BSC_aio_suspend -0x40c04f0 BSC_aio_cancel -0x40c04f4 BSC_aio_error -0x40c04f8 BSC_aio_read -0x40c04fc BSC_aio_write +0x40c04e0 BSC_pthread_cond_timedwait +0x40c04e4 BSC_aio_fsync +0x40c04e8 BSC_aio_return +0x40c04ec BSC_aio_suspend +0x40c04f0 BSC_aio_cancel +0x40c04f4 BSC_aio_error +0x40c04f8 BSC_aio_read +0x40c04fc BSC_aio_write 0x40c0500 BSC_lio_listio 0x40c0504 BSC__pthread_cond_wait 0x40c0508 BSC_iopolicysys @@ -955,7 +962,7 @@ 0x40c0530 BSC_pthread_markcancel 0x40c0534 BSC_pthread_canceled 0x40c0538 BSC_semwait_signal -0x40c053c BSC_utrace +0x40c053c BSC_obs_utrace 0x40c0540 BSC_proc_info 0x40c0544 BSC_sendfile 0x40c0548 BSC_stat64 @@ -964,31 +971,31 @@ 0x40c0554 BSC_stat64_extended 0x40c0558 BSC_lstat64_extended 0x40c055c BSC_fstat64_extended -0x40c0560 BSC_#344 -0x40c0564 BSC_#345 -0x40c0568 BSC_#346 -0x40c056c BSC_#347 -0x40c0570 BSC_#348 -0x40c0574 BSC_#349 -0x40c0578 BSC_audit -0x40c057c BSC_auditon -0x40c0580 BSC_#352 -0x40c0584 BSC_getauid -0x40c0588 BSC_setauid -0x40c058c BSC_getaudit -0x40c0590 BSC_setaudit -0x40c0594 BSC_getaudit_addr -0x40c0598 BSC_setaudit_addr -0x40c059c BSC_auditctl -0x40c05a0 BSC_#360 -0x40c05a4 BSC_#361 -0x40c05a8 BSC_kqueue -0x40c05ac BSC_kevent +0x40c0560 BSC_getdirentries64 +0x40c0564 BSC_statfs64 +0x40c0568 BSC_fstatfs64 +0x40c056c BSC_getfsstat64 +0x40c0570 BSC_pthread_chdir +0x40c0574 BSC_pthread_fchdir +0x40c0578 BSC_audit +0x40c057c BSC_auditon +0x40c0580 BSC_#352 +0x40c0584 BSC_getauid +0x40c0588 BSC_setauid +0x40c058c BSC_getaudit +0x40c0590 BSC_setaudit +0x40c0594 BSC_getaudit_addr +0x40c0598 BSC_setaudit_addr +0x40c059c BSC_auditctl +0x40c05a0 BSC_bsdthread_create +0x40c05a4 BSC_bsdthread_terminate +0x40c05a8 BSC_kqueue +0x40c05ac BSC_kevent 0x40c05b0 BSC_lchown -0x40c05b4 BSC_#365 -0x40c05b8 BSC_#366 -0x40c05bc BSC_#367 -0x40c05c0 BSC_#368 +0x40c05b4 BSC_stack_snapshot +0x40c05b8 BSC_bsdthread_register +0x40c05bc BSC_workq_open +0x40c05c0 BSC_workq_ops 0x40c05c4 BSC_#369 0x40c05c8 BSC_#370 0x40c05cc BSC_#371 @@ -1044,144 +1051,169 @@ 0x40c0694 BSC_aio_suspend_nocancel 0x40c0698 BSC_sigwait_nocancel 0x40c069c BSC_semwait_signal_nocancel +0x40c06a0 BSC_mac_mount +0x40c06a4 BSC_mac_get_mount +0x40c06a8 BSC_mac_getfsstat +0x5020004 IES_client +0x5020008 IES_latency +0x502000c IES_sema +0x5020010 IES_intctxt 0x5020018 IES_action 0x502001c IES_filter +0x5030004 TES_client +0x5030008 TES_latency +0x503000c TES_sema 0x5030010 TES_action +0x5040004 CQ_client +0x5040008 CQ_latency +0x504000c CQ_sema +0x5040010 CQ_psema +0x5040014 CQ_plock 0x5040018 CQ_action -0x5100004 PM_SetParent -0x5100008 PM_AddChild -0x510000c PM_RemoveChild -0x5100010 PM_CtrlDriver -0x5100014 PM_CtrlDrvrE1 -0x5100018 PM_CtrlDrvrE2 -0x510001c PM_CtrlDrvrE3 -0x5100020 PM_CtrlDrvrE4 -0x5100024 PM_IntDriver -0x5100028 PM_AckE1 -0x510002c PM_ChildAck -0x5100030 PM_DriverAck -0x5100034 PM_AckE2 -0x5100038 PM_AckE3 -0x510003c PM_AckE4 -0x5100040 PM_DrvrAckSPwr -0x5100044 PM_WillChange -0x5100048 PM_DidChange -0x510004c PM_ReqstDomain -0x5100050 PM_MakeUsable -0x5100054 PM_ChangeTo -0x5100058 PM_ChngeToPriv -0x510005c PM_SetAggrssvs -0x5100060 PM_CritclTemp -0x5100064 PM_OverrideOn -0x5100068 PM_OverrideOff -0x510006c PM_EnqueueErr -0x5100070 PM_CollapseQ -0x5100074 PM_ChangeDone -0x5100078 PM_CtrlDrvTrdy -0x510007c PM_IntDrvrTrdy -0x5100080 PM_StartAckTmr -0x5100084 PM_ParentChnge -0x5100088 PM_AmndPrnChng -0x510008c PM_DeviceChnge -0x5100090 PM_ReqDenied -0x5100094 PM_CtrlDrvrE45 -0x5100098 PM_PrgrmHrdwre -0x510009c PM_InfDrvrPre -0x51000a0 PM_InfDrvrPost -0x51000a4 PM_RemoveDrivr -0x51000a8 PM_IdlTimerPrd -0x51000ac PM_SystemWake -0x51000b0 PM_AckE5 -0x51000b4 PM_ClientAck -0x51000b8 PM_ClientTardy -0x51000bc PM_ClientCancl -0x51000c0 PM_ClientNotfy -0x51000c4 PM_AppNotify -0x5310004 CPUPM_PSTATE -0x5310008 CPUPM_IDLE_CSTATE -0x531000c CPUPM_IDLE_HALT -0x5310010 CPUPM_IDLE_LOOP -0x5310014 CPUPM_HPET_START -0x5310018 CPUPM_HPET_END -0x531001c CPUPM_HPET_INTR -0x5310020 CPUPM_PSTATE_HW -0x5310024 CPUPM_PSTATE_LIMIT -0x5310028 CPUPM_PSTATE_PARK -0x531002c CPUPM_PSTATE_START -0x5310030 CPUPM_PSTATE_PAUSE -0x5310034 CPUPM_PSTATE_RESUME -0x5310038 CPUPM_PSTATE_DOWN -0x531003c CPUPM_PSTATE_UP -0x5310040 CPUPM_PSTATE_NORM -0x5310044 CPUPM_PSTATE_FORCE -0x5310048 CPUPM_PSTATE_TIMEOUT -0x531004c CPUPM_PSTATE_SETTO -0x5310050 CPUPM_SET_DEADLINE -0x5310054 CPUPM_GET_DEADLINE -0x5310058 CPUPM_DEADLINE -0x531005c CPUPM_IDLE_SNOOP -0x5310060 CPUPM_IDLE_LATENCY -0x5310064 CPUPM_IDLE_WAKEUP -0x5310068 CPUPM_IDLE_SW_WAKEUP -0x531006c CPUPM_IDLE_SELECT -0x5310070 CPUPM_IDLE_SELECTED -0x5310074 CPUPM_IDLE_INTSKIP -0x5310078 CPUPM_IDLE_LOCK -0x531007c CPUPM_IDLE_UNLOCK -0x5310080 CPUPM_IDLE_NO_HPET -0x5310084 CPUPM_FI_UP -0x5310088 CPUPM_FI_UP_CPU -0x531008c CPUPM_FI_MP -0x5310090 CPUPM_FI_MP_CPU -0x5310094 CPUPM_FI_PAUSE -0x5310098 CPUPM_FI_RUN -0x531009c CPUPM_PROC_HALT -0x53100a0 CPUPM_TRACE_STOPPED -0x53100a4 CPUPM_HPET_INT_LOCK -0x53100a8 CPUPM_HPET_INT_UNLOCK -0x53100ac CPUPM_HPET_TRY_AGAIN -0x53100b0 CPUPM_HPET_SETDEADLINE -0x53100b4 CPUPM_LOCK_HELDBY -0x53100b8 CPUPM_HPET_DELTA -0x53100bc CPUPM_HPET_TOO_LATE -0x53100c0 CPUPM_HPET_NO_DEADLINE -0x53100c4 CPUPM_IDLE -0x53100c8 CPUPM_CORE_CHK_DEADLINE -0x53100cc CPUPM_SET_HPET_DEADLINE -0x53100d0 CPUPM_HPET_READ -0x53100d4 CPUPM_TIME_ADJUST -0x53100d8 CPUPM_IDLE_MWAIT -0x53100dc CPUPM_FI_SLAVE_IDLE -0x53100e0 CPUPM_FI_SLAVE_BLOCK -0x53100e4 CPUPM_FI_MAST_SIGNAL -0x53100e8 CPUPM_CORE_DEADLINE -0x53100ec CPUPM_IDLE_FAST -0x53100f0 CPUPM_IDLE_PAUSE -0x53100f4 CPUPM_IDLE_SHORT -0x53100f8 CPUPM_IDLE_NORMAL -0x53100fc CPUPM_IDLE_SPURIOUS -0x5310100 CPUPM_PSTATE_INFO -0x5310104 CPUPM_PSTATE_INFO_HW -0x5310108 CPUPM_PSTATE_FSM -0x531010c CPUPM_PSTATE_FSM_STEP -0x5310110 CPUPM_PSTATE_FSM_EVAL -0x5310114 CPUPM_PSTATE_FSM_MAP -0x5310118 CPUPM_CPUSTEP_RUN -0x531011c CPUPM_CPUSTEP_RUN_UP -0x5310120 CPUPM_CPUSTEP_RUN_DOWN -0x5310124 CPUPM_CPUSTEP_AVAIL -0x5310128 CPUPM_CPUSTEP_AVAIL_STEP -0x531012c CPUPM_CPUSTEP_AVAIL_CHNG -0x5310130 CPUPM_CPUSTEP_LOAD -0x5310134 CPUPM_CPUSTEP_START -0x5310138 CPUPM_CPUSTEP_STOP -0x531013c CPUPM_CPUSTEP_COPY -0x5310140 CPUPM_CPUSTEP_STEP -0x5310144 CPUPM_CPUSTEP_RUNCOUNT +0x5100004 PM_SetParent +0x5100008 PM_AddChild +0x510000c PM_RemoveChild +0x5100010 PM_CtrlDriver +0x5100014 PM_CtrlDrvrE1 +0x5100018 PM_CtrlDrvrE2 +0x510001c PM_CtrlDrvrE3 +0x5100020 PM_CtrlDrvrE4 +0x5100024 PM_IntDriver +0x5100028 PM_AckE1 +0x510002c PM_ChildAck +0x5100030 PM_DriverAck +0x5100034 PM_AckE2 +0x5100038 PM_AckE3 +0x510003c PM_AckE4 +0x5100040 PM_DrvrAckSPwr +0x5100044 PM_WillChange +0x5100048 PM_DidChange +0x510004c PM_ReqstDomain +0x5100050 PM_MakeUsable +0x5100054 PM_ChangeTo +0x5100058 PM_ChngeToPriv +0x510005c PM_SetAggrssvs +0x5100060 PM_CritclTemp +0x5100064 PM_OverrideOn +0x5100068 PM_OverrideOff +0x510006c PM_EnqueueErr +0x5100070 PM_CollapseQ +0x5100074 PM_ChangeDone +0x5100078 PM_CtrlDrvTrdy +0x510007c PM_IntDrvrTrdy +0x5100080 PM_StartAckTmr +0x5100084 PM_ParentChnge +0x5100088 PM_AmndPrnChng +0x510008c PM_DeviceChnge +0x5100090 PM_ReqDenied +0x5100094 PM_CtrlDrvrE45 +0x5100098 PM_PrgrmHrdwre +0x510009c PM_InfDrvrPre +0x51000a0 PM_InfDrvrPost +0x51000a4 PM_RemoveDrivr +0x51000a8 PM_IdlTimerPrd +0x51000ac PM_SystemWake +0x51000b0 PM_AckE5 +0x51000b4 PM_ClientAck +0x51000b8 PM_ClientTardy +0x51000bc PM_ClientCancl +0x51000c0 PM_ClientNotfy +0x51000c4 PM_AppNotify +0x5310004 CPUPM_PSTATE +0x5310008 CPUPM_IDLE_CSTATE +0x531000c CPUPM_IDLE_HALT +0x5310010 CPUPM_IDLE_LOOP +0x5310014 CPUPM_HPET_START +0x5310018 CPUPM_HPET_END +0x531001c CPUPM_HPET_INTR +0x5310020 CPUPM_PSTATE_HW +0x5310024 CPUPM_PSTATE_LIMIT +0x5310028 CPUPM_PSTATE_PARK +0x531002c CPUPM_PSTATE_START +0x5310030 CPUPM_PSTATE_PAUSE +0x5310034 CPUPM_PSTATE_RESUME +0x5310038 CPUPM_PSTATE_DOWN +0x531003c CPUPM_PSTATE_UP +0x5310040 CPUPM_PSTATE_NORM +0x5310044 CPUPM_PSTATE_FORCE +0x5310048 CPUPM_PSTATE_TIMEOUT +0x531004c CPUPM_PSTATE_SETTO +0x5310050 CPUPM_SET_DEADLINE +0x5310054 CPUPM_GET_DEADLINE +0x5310058 CPUPM_DEADLINE +0x531005c CPUPM_IDLE_SNOOP +0x5310060 CPUPM_IDLE_LATENCY +0x5310064 CPUPM_IDLE_WAKEUP +0x5310068 CPUPM_IDLE_SW_WAKEUP +0x531006c CPUPM_IDLE_SELECT +0x5310070 CPUPM_IDLE_SELECTED +0x5310074 CPUPM_IDLE_INTSKIP +0x5310078 CPUPM_IDLE_LOCK +0x531007c CPUPM_IDLE_UNLOCK +0x5310080 CPUPM_IDLE_NO_HPET +0x5310084 CPUPM_FI_UP +0x5310088 CPUPM_FI_UP_CPU +0x531008c CPUPM_FI_MP +0x5310090 CPUPM_FI_MP_CPU +0x5310094 CPUPM_FI_PAUSE +0x5310098 CPUPM_FI_RUN +0x531009c CPUPM_PROC_HALT +0x53100a0 CPUPM_TRACE_STOPPED +0x53100a4 CPUPM_HPET_INT_LOCK +0x53100a8 CPUPM_HPET_INT_UNLOCK +0x53100ac CPUPM_HPET_TRY_AGAIN +0x53100b0 CPUPM_HPET_SETDEADLINE +0x53100b4 CPUPM_LOCK_HELDBY +0x53100b8 CPUPM_HPET_DELTA +0x53100bc CPUPM_HPET_TOO_LATE +0x53100c0 CPUPM_HPET_NO_DEADLINE +0x53100c4 CPUPM_IDLE +0x53100c8 CPUPM_CORE_CHK_DEADLINE +0x53100cc CPUPM_SET_HPET_DEADLINE +0x53100d0 CPUPM_HPET_READ +0x53100d4 CPUPM_TIME_ADJUST +0x53100d8 CPUPM_IDLE_MWAIT +0x53100dc CPUPM_FI_SLAVE_IDLE +0x53100e0 CPUPM_FI_SLAVE_BLOCK +0x53100e4 CPUPM_FI_MAST_SIGNAL +0x53100e8 CPUPM_CORE_DEADLINE +0x53100ec CPUPM_IDLE_FAST +0x53100f0 CPUPM_IDLE_PAUSE +0x53100f4 CPUPM_IDLE_SHORT +0x53100f8 CPUPM_IDLE_NORMAL +0x53100fc CPUPM_IDLE_SPURIOUS +0x5310100 CPUPM_PSTATE_INFO +0x5310104 CPUPM_PSTATE_INFO_HW +0x5310108 CPUPM_PSTATE_FSM +0x531010c CPUPM_PSTATE_FSM_STEP +0x5310110 CPUPM_PSTATE_FSM_EVAL +0x5310114 CPUPM_PSTATE_FSM_MAP +0x5310118 CPUPM_CPUSTEP_STEP +0x531011c CPUPM_CPUSTEP_STEP_UP +0x5310120 CPUPM_CPUSTEP_STEP_DOWN +0x5310124 CPUPM_CPUSTEP_AVAIL +0x5310128 CPUPM_CPUSTEP_AVAIL_STEP +0x531012c CPUPM_CPUSTEP_AVAIL_CHNG +0x5310130 CPUPM_CPUSTEP_LOAD +0x5310134 CPUPM_CPUSTEP_START +0x5310138 CPUPM_CPUSTEP_STOP +0x531013c CPUPM_CPUSTEP_COPY +0x5310140 CPUPM_CPUSTEP_CLEAR +0x5310144 CPUPM_CPUSTEP_RUNCOUNT +0x5310148 CPUPM_CPUSTEP_WAKEUP 0x7000004 TRACE_DATA_NEWTHREAD 0x7010004 TRACE_STRING_NEWTHREAD 0x7010008 TRACE_STRING_EXEC 0x8000000 USER_TEST +0x8000004 USER_run +0x8000008 USER_join +0x800000c USER_create +0x8000010 USER_pthread_create +0x8000014 USER_pthread_exit +0x8000018 USER_pthread_join +0x800001c USER_pthread_run +0x8000020 USER_pthread_cleanup_push +0x8040000 USER_STOP 0x21800000 SMB_smbd_idle 0x21800004 SMB_syscall_opendir 0x21800008 SMB_syscall_readdir @@ -1348,3 +1380,128 @@ 0x2180028c SMB_sync_browse_lists 0x21800290 SMB_run_elections 0x21800294 SMB_election +0xb000000 AFP_asp_tcp_usr_send +0xb000004 AFP_asp_tcp_usr_send_after_Request +0xb000008 AFP_asp_tcp_usr_send_after_FindDSIReq +0xb00000c AFP_asp_tcp_usr_send_after_Reply +0xb000010 AFP_asp_tcp_slowtimo +0xb000014 AFP_asp_tcp_usr_control +0xb000018 AFP_asp_tcp_fasttimo +0xb000020 AFP_Send +0xb000024 AFP_Send_before_sosend +0xb000028 AFP_Send_after_sosend +0xb00002c AFP_Send_before_write +0xb000030 AFP_Send_after_write +0xb000040 AFP_Reply +0xb000044 AFP_Reply_rcvdAlready +0xb000048 AFP_Reply_before_RcvLock +0xb00004c AFP_Reply_fail_RcvLock +0xb000050 AFP_Reply_before_ReadDSIHdr +0xb000054 AFP_Reply_after_ReadDSIHdr +0xb000058 AFP_Reply_fail_ReadDSIHdr +0xb00005c AFP_Reply_after_FindDSIReqInfo +0xb000060 AFP_Reply_SetAFPCmd +0xb000064 AFP_Reply_before_ReadDSIPacket +0xb000068 AFP_Reply_setRcvdReplyLen +0xb000070 AFP_SendReply +0xb000080 AFP_CreateDSIHeader +0xb000084 AFP_CreateDSIHeader_after_GetReqID +0xb000090 AFP_Request +0xb0000a0 AFP_ReceiveLock +0xb0000b0 AFP_ReceiveWakeUp +0xb0000c0 AFP_ReceiveUnLock +0xb0000e0 AFP_SendLock +0xb0000e4 AFP_SendUnLock +0xb0000f0 AFP_SendQueueLock +0xb000100 AFP_SendQueueUnLock +0xb000110 AFP_ReadDSIHeader +0xb000120 AFP_Receive +0xb000124 AFP_Receive_before_sorcv +0xb000128 AFP_Receive_after_sorcv +0xb000130 AFP_ReadDSIPacket +0xb000140 AFP_DoCopyOut +0xb000150 AFP_DoCopyIn +0xb000160 AFP_CheckRcvTickle +0xb000164 AFP_CheckRcvTickleTO +0xb000170 AFP_CheckSendTickle +0xb000180 AFP_CheckIncomingPkts +0xb000190 AFP_ProcessOptions +0xb000200 AFP_FindDSIReqInfo +0xb000204 AFP_FindDSIReqInfo_foundReqInfo +0xb000208 AFP_FindDSIReqInfo_flags +0xb00020c AFP_FindDSIReqLeave +0xb000210 AFP_UsrDisconnect +0xc000000 AFPVFS_UserReply +0xc000004 AFPVFS_UserReplyGetMbuf +0xc000008 AFPVFS_UserReplysosend +0xc000010 AFPVFS_UserCommand +0xc000018 AFPVFS_UserCommandsosend +0xc000020 AFPVFS_ReadFork +0xc000024 AFPVFS_ReadForkFillQPB +0xc000028 AFPVFS_ReadForkNbrRequests +0xc00002c AFPVFS_ReadForkSendQPB +0xc000030 AFPVFS_ReadForkSendErr +0xc000040 AFPVFS_ReadForkGetReply +0xc000044 AFPVFS_ReadForkGetReplyResult +0xc000050 AFPVFS_WriteFork +0xc000054 AFPVFS_WriteForkFillQPB +0xc000058 AFPVFS_WriteForkNbrRequests +0xc00005c AFPVFS_WriteForkSendQPB +0xc000060 AFPVFS_WriteForkSendErr +0xc000064 AFPVFS_WriteForkGetReply +0xc000068 AFPVFS_WriteForkGetReplyResult +0xc000070 AFPVFS_GetAttr +0xc000080 AFPVFS_SetAttr +0xc000090 AFPVFS_GetAttrList +0xc0000a0 AFPVFS_SetAttrList +0xc0000b0 AFPVFS_FSCTL +0xc0000c0 AFPVFS_LookUp +0xc0000d0 AFPVFS_CacheLookUp +0xc0000e0 AFPVFS_Write +0xc0000e4 AFPVFS_WriteNoCluster +0xc0000e8 AFPVFS_WriteDone +0xc0000f0 AFPVFS_DoWrite +0xc000100 AFPVFS_Lock +0xc000110 AFPVFS_Statfs +0xc000120 AFPVFS_Sync +0xc000130 AFPVFS_VGet +0xc000140 AFPVFS_FlushFiles +0xc000150 AFPVFS_Create +0xc000160 AFPVFS_Mknod +0xc000170 AFPVFS_Open +0xc000180 AFPVFS_Close +0xc000190 AFPVFS_Access +0xc000194 AFPVFS_AccessUID +0xc000198 AFPVFS_AccessGID +0xc00019c AFPVFS_AccessWID +0xc0001a0 AFPVFS_Writeperm +0xc0001b0 AFPVFS_Chmod +0xc0001c0 AFPVFS_Chflags +0xc0001d0 AFPVFS_Exchange +0xc0001e0 AFPVFS_Chid +0xc0001f0 AFPVFS_Fsync +0xc000200 AFPVFS_Remove +0xc000210 AFPVFS_Rename +0xc000220 AFPVFS_Copyfile +0xc000230 AFPVFS_Mkdir +0xc000230 AFPVFS_Rmdir +0xc000240 AFPVFS_Symlink +0xc000250 AFPVFS_Readdir +0xc000260 AFPVFS_Readdirattr +0xc000264 AFPVFS_Readdirattr1 +0xc000268 AFPVFS_Readdirattr2 +0xc00026c AFPVFS_Readdirattr3 +0xc000270 AFPVFS_Readlink +0xc000280 AFPVFS_Abortop +0xc000290 AFPVFS_Inactive +0xc0002a0 AFPVFS_Reclaim +0xc0002b0 AFPVFS_Unlock +0xc0002c0 AFPVFS_Islocked +0xc0002d0 AFPVFS_Pathconf +0xc0002e0 AFPVFS_Update +0xc0002e0 AFPVFS_Vinit +0xc0002f0 AFPVFS_Makenode +0xc000300 AFPVFS_Allocate +0xc000310 AFPVFS_Search +0xc000320 AFPVFS_Reconnect +0x14200000 TRACE_LAST_WRAPPER diff --git a/shutdown.tproj/Makefile b/shutdown.tproj/Makefile index 5806a4b..b21ef26 100644 --- a/shutdown.tproj/Makefile +++ b/shutdown.tproj/Makefile @@ -6,7 +6,10 @@ CFILES = shutdown.c USERDEFS = kextmanager.defs MANPAGES = shutdown.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + Extra_Frameworks = -framework IOKit -Extra_LD_Flags = -lbsm +Extra_LD_Flags += -lbsm include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/shutdown.tproj/shutdown.c b/shutdown.tproj/shutdown.c index e7a7928..31f3033 100644 --- a/shutdown.tproj/shutdown.c +++ b/shutdown.tproj/shutdown.c @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD: src/sbin/shutdown/shutdown.c,v 1.28 2005/01/25 08:40:51 delp #include #include #include +#include +#include #include "kextmanager.h" #include @@ -74,6 +76,8 @@ __FBSDID("$FreeBSD: src/sbin/shutdown/shutdown.c,v 1.28 2005/01/25 08:40:51 delp #include // task_self, etc #include // bootstrap #include +#include +#include #include "pathnames.h" #endif /* __APPLE__ */ @@ -278,6 +282,11 @@ main(int argc, char **argv) } if (forkpid) errx(0, "[pid %d]", forkpid); +#ifdef __APPLE__ + /* 5863185: reboot2() needs to talk to launchd. */ + if (_vprocmgr_detach_from_console(0) != NULL) + warnx("can't detach from console"); +#endif /* __APPLE__ */ } audit_shutdown(0); setsid(); @@ -409,8 +418,10 @@ die_you_gravy_sucking_pig_dog() #ifndef __APPLE__ char *empty_environ[] = { NULL }; #else - if ((errno = reserve_reboot())) - err(1, "couldn't lock for reboot"); + if ((errno = reserve_reboot())) { + warn("couldn't lock for reboot"); + finish(0); + } #endif syslog(LOG_NOTICE, "%s%s by %s: %s", @@ -460,21 +471,33 @@ die_you_gravy_sucking_pig_dog() } } } - exit((kr == kIOReturnSuccess) ? 0 : 1); } else { int howto = 0; +#if defined(__APPLE__) + { + struct utmpx utx; + bzero(&utx, sizeof(utx)); + utx.ut_type = SHUTDOWN_TIME; + gettimeofday(&utx.ut_tv, NULL); + pututxline(&utx); + + int newvalue = 1; + sysctlbyname("kern.willshutdown", NULL, NULL, &newvalue, sizeof(newvalue)); + } +#else logwtmp("~", "shutdown", ""); +#endif if (dohalt) howto |= RB_HALT; if (doups) howto |= RB_UPSDELAY; if (nosync) howto |= RB_NOSYNC; // launchd(8) handles reboot. This call returns NULL on success. - exit(reboot2(howto) == NULL ? EXIT_SUCCESS : EXIT_FAILURE); + if (reboot2(howto)) { + syslog(LOG_ERR, "shutdown: launchd reboot failed."); + } } - /* NOT-REACHED */ - #else /* __APPLE__ */ if (!oflag) { (void)kill(1, doreboot ? SIGINT : /* reboot */ @@ -598,7 +621,6 @@ getoffset(char *timearg) void nolog() { -#ifndef __APPLE__ int logfd; char *ct; @@ -616,16 +638,13 @@ nolog() (void)write(logfd, mbuf, strlen(mbuf)); (void)close(logfd); } -#endif /* !__APPLE__ */ } void finish(int signo __unused) { -#ifndef __APPLE__ if (!killflg) (void)unlink(_PATH_NOLOGIN); -#endif exit(0); } diff --git a/sync.tproj/Makefile b/sync.tproj/Makefile index 51cb40e..502fbde 100644 --- a/sync.tproj/Makefile +++ b/sync.tproj/Makefile @@ -4,4 +4,8 @@ Install_Dir = /bin CFILES = sync.c MANPAGES = sync.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags += -D__FBSDID=__RCSID +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sync.tproj/sync.8 b/sync.tproj/sync.8 index 6d39ad0..fc733b8 100644 --- a/sync.tproj/sync.8 +++ b/sync.tproj/sync.8 @@ -1,3 +1,4 @@ +.\"- .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -9,10 +10,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with 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. @@ -30,44 +27,42 @@ .\" SUCH DAMAGE. .\" .\" @(#)sync.8 8.1 (Berkeley) 5/31/93 +.\" $FreeBSD: src/bin/sync/sync.8,v 1.16 2005/01/10 08:39:26 imp Exp $ .\" .Dd May 31, 1993 .Dt SYNC 8 -.Os BSD 4 +.Os .Sh NAME .Nm sync .Nd force completion of pending disk writes (flush cache) .Sh SYNOPSIS -.Nm sync +.Nm .Sh DESCRIPTION -.Nm Sync -can be called to insure that all disk writes have been completed before the +The +.Nm +utility +can be called to ensure that all disk writes have been completed before the processor is halted in a way not suitably done by -.Xr reboot 8 -or -.Xr halt 8 . +.Xr shutdown 8 . Generally, it is preferable to use -.Xr reboot -or -.Xr halt +.Xr shutdown 8 to shut down the system, as they may perform additional actions such as resynchronizing the hardware clock and flushing internal caches before performing a final -.Nm sync . +.Nm . .Pp -.Nm Sync -utilizes the +The +.Nm +utility utilizes the .Xr sync 2 function call. .Sh SEE ALSO .Xr fsync 2 , .Xr sync 2 , -.Xr halt 8 , -.Xr reboot 8 , -.Xr update 8 +.Xr shutdown 8 .Sh HISTORY A -.Nm sync -command appeared in -.At v6 . +.Nm +utility appeared in +.At v4 . diff --git a/sync.tproj/sync.c b/sync.tproj/sync.c index 10a4856..2d68997 100644 --- a/sync.tproj/sync.c +++ b/sync.tproj/sync.c @@ -1,29 +1,6 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* +/*- * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with 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. @@ -54,11 +27,25 @@ * SUCH DAMAGE. */ +#if 0 +#ifndef lint +static char const copyright[] = +"@(#) Copyright (c) 1987, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)sync.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/bin/sync/sync.c,v 1.16 2005/01/10 08:39:26 imp Exp $"); + #include #include int -main() +main(int argc __unused, char *argv[] __unused) { sync(); exit(0); diff --git a/sysctl.tproj/Makefile b/sysctl.tproj/Makefile index ee35679..9c01459 100644 --- a/sysctl.tproj/Makefile +++ b/sysctl.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/sbin CFILES = sysctl.c MANPAGES = sysctl.8 sysctl.conf.5 +Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sysctl.tproj/pathconf.c b/sysctl.tproj/pathconf.c deleted file mode 100644 index dc7aecc..0000000 --- a/sysctl.tproj/pathconf.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 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 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@ - */ -/* - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)pathconf.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include - -#define PC_NAMES { \ - { 0, 0 }, \ - { "link_max", CTLTYPE_INT }, \ - { "max_canon", CTLTYPE_INT }, \ - { "max_input", CTLTYPE_INT }, \ - { "name_max", CTLTYPE_INT }, \ - { "path_max", CTLTYPE_INT }, \ - { "pipe_buf", CTLTYPE_INT }, \ - { "chown_restricted", CTLTYPE_INT }, \ - { "no_trunc", CTLTYPE_INT }, \ - { "vdisable", CTLTYPE_INT }, \ -} -#define PC_MAXID 10 - -struct ctlname pcnames[] = PC_NAMES; -char names[BUFSIZ]; - -struct list { - struct ctlname *list; - int size; -}; -struct list pclist = { pcnames, PC_MAXID }; - -int Aflag, aflag, nflag, wflag, stdinflag; - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - char *path; - int ch; - - while ((ch = getopt(argc, argv, "Aan")) != EOF) { - switch (ch) { - - case 'A': - Aflag = 1; - break; - - case 'a': - aflag = 1; - break; - - case 'n': - nflag = 1; - break; - - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (argc == 0) - usage(); - path = *argv++; - if (strcmp(path, "-") == 0) - stdinflag = 1; - argc--; - if (Aflag || aflag) { - listall(path, &pclist); - exit(0); - } - if (argc == 0) - usage(); - while (argc-- > 0) - parse(path, *argv, 1); - exit(0); -} - -/* - * List all variables known to the system. - */ -listall(path, lp) - char *path; - struct list *lp; -{ - int lvl2; - - if (lp->list == 0) - return; - for (lvl2 = 0; lvl2 < lp->size; lvl2++) { - if (lp->list[lvl2].ctl_name == 0) - continue; - parse(path, lp->list[lvl2].ctl_name, Aflag); - } -} - -/* - * Parse a name into an index. - * Lookup and print out the attribute if it exists. - */ -parse(pathname, string, flags) - char *pathname; - char *string; - int flags; -{ - int indx, value; - char *bufp, buf[BUFSIZ]; - - bufp = buf; - snprintf(buf, BUFSIZ, "%s", string); - if ((indx = findname(string, "top", &bufp, &pclist)) == -1) - return; - if (bufp) { - fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); - return; - } - if (stdinflag) - value = fpathconf(0, indx); - else - value = pathconf(pathname, indx); - if (value == -1) { - if (flags == 0) - return; - switch (errno) { - case ENOTSUP: - fprintf(stderr, "%s: value is not available\n", string); - return; - case ENOTDIR: - fprintf(stderr, "%s: specification is incomplete\n", - string); - return; - case ENOMEM: - fprintf(stderr, "%s: type is unknown to this program\n", - string); - return; - default: - perror(string); - return; - } - } - if (!nflag) - fprintf(stdout, "%s = ", string); - fprintf(stdout, "%d\n", value); -} - -/* - * Scan a list of names searching for a particular name. - */ -findname(string, level, bufp, namelist) - char *string; - char *level; - char **bufp; - struct list *namelist; -{ - char *name; - int i; - - if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { - fprintf(stderr, "%s: incomplete specification\n", string); - return (-1); - } - for (i = 0; i < namelist->size; i++) - if (namelist->list[i].ctl_name != NULL && - strcmp(name, namelist->list[i].ctl_name) == 0) - break; - if (i == namelist->size) { - fprintf(stderr, "%s level name %s in %s is invalid\n", - level, name, string); - return (-1); - } - return (i); -} - -usage() -{ - - (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n", - "pathname [-n] variable ...", - "pathname [-n] -a", "pathname [-n] -A"); - exit(1); -} diff --git a/sysctl.tproj/sysctl.c b/sysctl.tproj/sysctl.c index b861263..c649826 100644 --- a/sysctl.tproj/sysctl.c +++ b/sysctl.tproj/sysctl.c @@ -493,6 +493,10 @@ old_parse(string, flags) fprintf(stderr, "%s: type is unknown to this program\n", string); return; + case ENOENT: + fprintf(stderr, "%s: no such MIB\n", + string); + return; default: perror(string); return; @@ -567,11 +571,11 @@ old_parse(string, flags) } return; + case CTLTYPE_NODE: case CTLTYPE_STRUCT: return; default: - case CTLTYPE_NODE: fprintf(stderr, "%s: unknown type returned\n", string); return; @@ -663,8 +667,10 @@ findname(string, level, bufp, namelist) if (bufp[0][strlen(*bufp)-1] == '.') bufp[0][strlen(*bufp)-1]='\0'; if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { - fprintf(stderr, "%s: incomplete specification\n", string); - invalid_name_used = 1; + if (!foundSome) { + fprintf(stderr, "%s: incomplete specification\n", string); + invalid_name_used = 1; + } return (-1); } for (i = 0; i < namelist->size; i++) @@ -672,9 +678,11 @@ findname(string, level, bufp, namelist) strcmp(name, namelist->list[i].ctl_name) == 0) break; if (i == namelist->size) { - fprintf(stderr, "%s level name %s in %s is invalid\n", - level, name, string); - invalid_name_used = 1; + if (!foundSome) { + fprintf(stderr, "%s level name %s in %s is invalid\n", + level, name, string); + invalid_name_used = 1; + } return (-1); } return (i); @@ -710,6 +718,8 @@ parse(char *string, int flags) u_int kind; bufp = buf; + if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) + errx(1, "MIB too long"); snprintf(buf, BUFSIZ, "%s", string); if ((cp = strchr(string, '=')) != NULL) { if (!wflag) diff --git a/update.tproj/Makefile b/update.tproj/Makefile index 88540fe..15b4851 100644 --- a/update.tproj/Makefile +++ b/update.tproj/Makefile @@ -1,14 +1,5 @@ Project = update -Install_Dir = /usr/sbin -CFILES = update.c MANPAGES = update.8 -LAUNCHD_PLISTS = com.apple.update.plist include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make - -SANDBOX = "$(DSTROOT)/usr/share/sandbox" - -after_install: - $(INSTALL_DIRECTORY) $(SANDBOX) - $(INSTALL_FILE) update.sb $(SANDBOX) diff --git a/update.tproj/com.apple.update.plist b/update.tproj/com.apple.update.plist index 238f9fc..e69de29 100644 --- a/update.tproj/com.apple.update.plist +++ b/update.tproj/com.apple.update.plist @@ -1,14 +0,0 @@ - - - - - Label - com.apple.update - OnDemand - - ProgramArguments - - /usr/sbin/update - - - diff --git a/update.tproj/update.8 b/update.tproj/update.8 index 72f099e..2d6e742 100644 --- a/update.tproj/update.8 +++ b/update.tproj/update.8 @@ -31,7 +31,7 @@ .\" .\" @(#)update.8 8.3 (Berkeley) 4/19/94 .\" -.Dd April 19, 1994 +.Dd August 18, 2008 .Dt UPDATE 8 .Os .Sh NAME @@ -39,25 +39,18 @@ .Nd flush internal filesystem caches to disk frequently .Sh SYNOPSIS .Nm update -.Op Ar normal_interval Op Ar save_energy_interval .Sh DESCRIPTION The .Nm update -command helps protect the integrity of disk volumes +utility has been incorporated into +.Xr launchd 8 . +It historically helped protect the integrity of disk volumes by flushing volatile cached filesystem data -to disk at thirty second intervals. -.Nm Update -uses the +to disk at thirty second intervals +using the .Xr sync 2 -function call to do the task. -The normal_interval and save_energy_interval can be used to set the -.Xr sync 2 interval in seconds of the normal case and the case where the computer is trying to save energy. -.Pp -.Nm Update -is invoked at startup time by -.Xr launchd 8 -when the system goes multi-user. +function call. .Sh SEE ALSO .Xr sync 2 , .Xr fsck 8 , @@ -71,6 +64,6 @@ file system damage. See .Xr fsck 8 . .Sh HISTORY An -.Nm update -command appeared in +.Nm +utility appeared in .At v6 . diff --git a/update.tproj/update.c b/update.tproj/update.c index 17c33ee..e69de29 100644 --- a/update.tproj/update.c +++ b/update.tproj/update.c @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2007 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@ - */ -#include -#include -#include - -int -main(void) -{ - const char* progname = "update"; - char* errmsg; - int res = sandbox_init(progname, SANDBOX_NAMED, &errmsg); - if (res) { - fprintf(stderr, "%s: sandbox_init: %s\n", progname, errmsg); - sandbox_free_error(errmsg); - } - - for (;;) { - sleep(30); - sync(); - } - - return 0; -} diff --git a/update.tproj/update.sb b/update.tproj/update.sb index d8cb413..e69de29 100644 --- a/update.tproj/update.sb +++ b/update.tproj/update.sb @@ -1,18 +0,0 @@ -;; Copyright (c) 2007 Apple Inc. All Rights reserved. -;; -;; WARNING: The sandbox rules in this file currently constitute -;; Apple System Private Interface and are subject to change at any time and -;; without notice. The contents of this file are also auto-generated and not -;; user editable; it may be overwritten at any time. -;; -(version 1) -(debug deny) -(allow process-exec (regex #"^/usr/sbin/update$")) -(allow sysctl-read) -(allow file-read-data file-read-metadata - (regex #"^/usr/lib/.*\.dylib$" - #"^/var" - #"^/private/var/db/dyld/" - #"^/dev/urandom$" - #"^/dev/dtracehelper$")) -(deny default) diff --git a/vifs.tproj/Makefile b/vifs.tproj/Makefile index 7627118..231d384 100644 --- a/vifs.tproj/Makefile +++ b/vifs.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/sbin CFILES = vifs.c MANPAGES = vifs.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/vipw.tproj/Makefile b/vipw.tproj/Makefile index 88c4d20..2f5516d 100644 --- a/vipw.tproj/Makefile +++ b/vipw.tproj/Makefile @@ -5,4 +5,7 @@ HFILES = pw_util.h CFILES = pw_util.c vipw.c MANPAGES = vipw.8 +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/vm_stat.tproj/Makefile b/vm_stat.tproj/Makefile index 7d6e4c3..14aef47 100644 --- a/vm_stat.tproj/Makefile +++ b/vm_stat.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/bin CFILES = vm_stat.c MANPAGES = vm_stat.1 +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/vm_stat.tproj/vm_stat.c b/vm_stat.tproj/vm_stat.c index ec9680f..d7a4536 100644 --- a/vm_stat.tproj/vm_stat.c +++ b/vm_stat.tproj/vm_stat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,6 +37,9 @@ * * 25-mar-99 A.Ramesh at Apple * Ported to MacOS X + * + * 22-Jan-09 R.Branche at Apple + * Changed some fields to 64-bit to alleviate overflows ************************************************************************ */ @@ -47,7 +50,7 @@ #include -vm_statistics_data_t vm_stat, last; +vm_statistics64_data_t vm_stat, last; natural_t percent; int delay; char *pgmname; @@ -55,11 +58,13 @@ mach_port_t myHost; vm_size_t pageSize = 4096; /* set to 4k default */ void usage(void); -void banner(void); void snapshot(void); -void pstat(char *str, natural_t n); +void sspstat(char *str, uint64_t n); +void banner(void); void print_stats(void); -void get_stats(struct vm_statistics *stat); +void get_stats(vm_statistics64_t stat); + +void pstat(uint64_t n, int width); int main(int argc, char *argv[]) @@ -104,55 +109,62 @@ usage(void) exit(EXIT_FAILURE); } +void +snapshot(void) +{ + + get_stats(&vm_stat); + printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n", + (int) (pageSize)); + + sspstat("Pages free:", (uint64_t) (vm_stat.free_count - vm_stat.speculative_count)); + sspstat("Pages active:", (uint64_t) (vm_stat.active_count)); + sspstat("Pages inactive:", (uint64_t) (vm_stat.inactive_count)); + sspstat("Pages speculative:", (uint64_t) (vm_stat.speculative_count)); + sspstat("Pages wired down:", (uint64_t) (vm_stat.wire_count)); + sspstat("\"Translation faults\":", (uint64_t) (vm_stat.faults)); + sspstat("Pages copy-on-write:", (uint64_t) (vm_stat.cow_faults)); + sspstat("Pages zero filled:", (uint64_t) (vm_stat.zero_fill_count)); + sspstat("Pages reactivated:", (uint64_t) (vm_stat.reactivations)); + sspstat("Pageins:", (uint64_t) (vm_stat.pageins)); + sspstat("Pageouts:", (uint64_t) (vm_stat.pageouts)); +#if defined(__ppc__) /* vm_statistics are still 32-bit on ppc */ + printf("Object cache: %u hits of %u lookups (%u%% hit rate)\n", +#else + printf("Object cache: %llu hits of %llu lookups (%u%% hit rate)\n", +#endif + vm_stat.hits, vm_stat.lookups, percent); + +} + +void +sspstat(char *str, uint64_t n) +{ + printf("%-25s %16llu.\n", str, n); +} + void banner(void) { get_stats(&vm_stat); printf("Mach Virtual Memory Statistics: "); printf("(page size of %d bytes, cache hits %u%%)\n", - pageSize, percent); - printf("%6s %6s %4s %4s %8s %8s %8s %8s %8s %8s\n", + (int) (pageSize), percent); + printf("%6s %6s %6s %8s %6s %8s %8s %8s %8s %8s %8s\n", "free", "active", - "inac", + "spec", + "inactive", "wire", "faults", "copy", - "zerofill", + "0fill", "reactive", "pageins", "pageout"); bzero(&last, sizeof(last)); } -void -snapshot(void) -{ - - get_stats(&vm_stat); - printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n", - pageSize); - - pstat("Pages free:", vm_stat.free_count); - pstat("Pages active:", vm_stat.active_count); - pstat("Pages inactive:", vm_stat.inactive_count); - pstat("Pages wired down:", vm_stat.wire_count); - pstat("\"Translation faults\":", vm_stat.faults); - pstat("Pages copy-on-write:", vm_stat.cow_faults); - pstat("Pages zero filled:", vm_stat.zero_fill_count); - pstat("Pages reactivated:", vm_stat.reactivations); - pstat("Pageins:", vm_stat.pageins); - pstat("Pageouts:", vm_stat.pageouts); - printf("Object cache: %u hits of %u lookups (%u%% hit rate)\n", - vm_stat.hits, vm_stat.lookups, percent); -} - -void -pstat(char *str, natural_t n) -{ - printf("%-25s %10u.\n", str, n); -} - void print_stats(void) { @@ -165,25 +177,55 @@ print_stats(void) count = 0; get_stats(&vm_stat); - printf("%6u %6u %4u %4u %8u %8u %8u %8u %8u %8u\n", - vm_stat.free_count, - vm_stat.active_count, - vm_stat.inactive_count, - vm_stat.wire_count, - vm_stat.faults - last.faults, - vm_stat.cow_faults - last.cow_faults, - vm_stat.zero_fill_count - last.zero_fill_count, - vm_stat.reactivations - last.reactivations, - vm_stat.pageins - last.pageins, - vm_stat.pageouts - last.pageouts); + pstat((uint64_t) (vm_stat.free_count - vm_stat.speculative_count), 6); + pstat((uint64_t) (vm_stat.active_count), 6); + pstat((uint64_t) (vm_stat.speculative_count), 6); + pstat((uint64_t) (vm_stat.inactive_count), 8); + pstat((uint64_t) (vm_stat.wire_count), 6); + pstat((uint64_t) (vm_stat.faults - last.faults), 8); + pstat((uint64_t) (vm_stat.cow_faults - last.cow_faults), 8); + pstat((uint64_t) (vm_stat.zero_fill_count - last.zero_fill_count), 8); + pstat((uint64_t) (vm_stat.reactivations - last.reactivations), 8); + pstat((uint64_t) (vm_stat.pageins - last.pageins), 8); + pstat((uint64_t) (vm_stat.pageouts - last.pageouts), 8); + putchar('\n'); last = vm_stat; } void -get_stats(struct vm_statistics *stat) +pstat(uint64_t n, int width) +{ + char buf[80]; + if (width >= sizeof(buf)) { + width = sizeof(buf) -1; + } + + unsigned long long nb = n * (unsigned long long)pageSize; + + /* Now that we have the speculative field, there is really not enough + space, but we were actually overflowing three or four fields before + anyway. So any field that overflows we drop some insignifigant + digets and slap on the appropriate suffix + */ + int w = snprintf(buf, sizeof(buf), "%*llu", width, n); + if (w > width) { + w = snprintf(buf, sizeof(buf), "%*lluK", width -1, n / 1000); + if (w > width) { + w = snprintf(buf, sizeof(buf), "%*lluM", width -1, n / 1000000); + if (w > width) { + w = snprintf(buf, sizeof(buf), "%*lluG", width -1, n / 1000000000); + } + } + } + fputs(buf, stdout); + putchar(' '); +} + +void +get_stats(vm_statistics64_t stat) { - unsigned int count = HOST_VM_INFO_COUNT; - if (host_statistics(myHost, HOST_VM_INFO, (host_info_t)stat, &count) != KERN_SUCCESS) { + unsigned int count = HOST_VM_INFO64_COUNT; + if (host_statistics64(myHost, HOST_VM_INFO64, (host_info64_t)stat, &count) != KERN_SUCCESS) { fprintf(stderr, "%s: failed to get statistics.\n", pgmname); exit(EXIT_FAILURE); } diff --git a/zdump.tproj/Makefile b/zdump.tproj/Makefile index 69179c2..332520f 100644 --- a/zdump.tproj/Makefile +++ b/zdump.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/sbin CFILES = zdump.c MANPAGES = zdump.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zdump.tproj/zdump.8 b/zdump.tproj/zdump.8 index 43344f2..065a1d6 100644 --- a/zdump.tproj/zdump.8 +++ b/zdump.tproj/zdump.8 @@ -9,27 +9,25 @@ .Nm zdump .Nd timezone dumper .Sh SYNOPSIS -.Nm zdump +.Nm .Op Fl -version .Op Fl v -.Op Fl c Ar cutoff_year -.Op Ar zone_name ... +.Op Fl c Ar cutoffyear +.Op Ar zonename ... .Sh DESCRIPTION The -.Nm zdump +.Nm utility prints the current time in each -.Ar zone_name +.Ar zonename named on the command line. .Pp The following options are available: .Bl -tag -width indent -.\" =========== -.It Fl c Ar cutoff_year -Cut off the verbose output near the start of the given year. -.\" =========== +.It Fl -version +Output version information and exit. .It Fl v For each -.Ar zone_name +.Ar zonename on the command line, print the time at the lowest possible time value, the time one day after the lowest possible time value, @@ -42,9 +40,8 @@ Each line ends with if the given time is Daylight Saving Time or .Em isdst=0 otherwise. -.\" =========== -.It Fl -version -Output version information and exit. +.It Fl c Ar cutoffyear +Cut off the verbose output near the start of the given year. .El .Sh "SEE ALSO" .Xr ctime 3 , diff --git a/zdump.tproj/zdump.c b/zdump.tproj/zdump.c index f98d117..6779ea1 100644 --- a/zdump.tproj/zdump.c +++ b/zdump.tproj/zdump.c @@ -2,7 +2,7 @@ static const char elsieid[] = "@(#)zdump.c 7.31"; #ifndef lint static const char rcsid[] = - "$FreeBSD: src/usr.sbin/zic/zdump.c,v 1.9 2004/06/20 21:41:11 stefanf Exp $"; + "$FreeBSD: src/usr.sbin/zic/zdump.c,v 1.10 2008/02/19 07:09:19 ru Exp $"; #endif /* not lint */ /* @@ -18,6 +18,7 @@ static const char rcsid[] = #include /* for time_t */ #include /* for struct tm */ #include +#include #ifndef MAX_STRING_LENGTH #define MAX_STRING_LENGTH 1024 @@ -148,7 +149,16 @@ char * argv[]; time_t now; time_t t; time_t newt; +#ifndef __APPLE__ +// +// The approach of walking through every day from the minimum +// possible time_t value to the maximum possible time_t value +// falls apart with 64-bit time_t (takes too long to iterate, +// and causes gmtime(3) and localtime(3) to return EOVERFLOW +// which this code does not anticipate). Limiting the time_t +// range to [INT_MIN:INT_MAX] even on LP64. time_t hibit; +#endif struct tm tm; struct tm newtm; @@ -170,7 +180,7 @@ char * argv[]; if (c == 'v') vflag = 1; else cutoff = optarg; - if ((c != EOF && c != -1) || + if ((c != -1) || (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { usage(); } @@ -188,8 +198,10 @@ char * argv[]; for (i = optind; i < argc; ++i) if (strlen(argv[i]) > longest) longest = strlen(argv[i]); +#ifndef __APPLE__ for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) continue; +#endif { register int from; register int to; @@ -222,9 +234,13 @@ char * argv[]; /* ** Get lowest value of t. */ +#ifdef __APPLE__ + t = INT_MIN; +#else t = hibit; if (t > 0) /* time_t is unsigned */ t = 0; +#endif show(argv[i], t, TRUE); t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); @@ -236,8 +252,13 @@ char * argv[]; newt = t + SECSPERHOUR * 12; if (cutoff != NULL && newt >= cuttime) break; +#ifdef __APPLE__ + if (newt > INT_MAX) + break; +#else if (newt <= t) break; +#endif newtm = *localtime(&newt); if (delta(&newtm, &tm) != (newt - t) || newtm.tm_isdst != tm.tm_isdst || @@ -253,9 +274,13 @@ char * argv[]; /* ** Get highest value of t. */ +#ifdef __APPLE__ + t = INT_MAX; +#else t = ~((time_t) 0); if (t < 0) /* time_t is signed */ t &= ~hibit; +#endif t -= SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); t += SECSPERHOUR * HOURSPERDAY; diff --git a/zic.tproj/Makefile b/zic.tproj/Makefile index f2d77db..04a05f7 100644 --- a/zic.tproj/Makefile +++ b/zic.tproj/Makefile @@ -5,6 +5,9 @@ HFILES = private.h CFILES = ialloc.c scheck.c zic.c MANPAGES = zic.8 +Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_LD_Flags = -dead_strip + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make LOCALTIME= US/Pacific @@ -53,10 +56,12 @@ after_install: $(INSTALL_FILE) $(DATFILES)/iso3166.tab $(ZONEINFO) ifeq "$(Embedded)" "YES" $(INSTALL_DIRECTORY) $(DSTROOT)/private/var/db - $(LN) -hfs /usr/share/zoneinfo/$(LOCALTIME) $(DSTROOT)/private/var/db/localtime + $(INSTALL_DIRECTORY) -m a+rwx $(DSTROOT)/private/var/db/timezone + $(LN) -hfs /usr/share/zoneinfo/$(LOCALTIME) $(DSTROOT)/private/var/db/timezone/localtime else $(INSTALL_DIRECTORY) $(DSTROOT)/private/etc $(LN) -hfs /usr/share/zoneinfo/$(LOCALTIME) $(DSTROOT)/private/etc/localtime endif + $(RM) $(VERSIONFILE) echo $(DATVERS) > $(VERSIONFILE) chmod 444 $(VERSIONFILE) diff --git a/zic.tproj/zic.8 b/zic.tproj/zic.8 index 4ca9487..b2a60aa 100644 --- a/zic.tproj/zic.8 +++ b/zic.tproj/zic.8 @@ -1,4 +1,4 @@ -.\" $FreeBSD: src/usr.sbin/zic/zic.8,v 1.17 2004/07/02 23:13:00 ru Exp $ +.\" $FreeBSD: src/usr.sbin/zic/zic.8,v 1.19 2005/02/13 23:45:54 ru Exp $ .Dd June 20, 2004 .Dt ZIC 8 .Os @@ -6,7 +6,7 @@ .Nm zic .Nd timezone compiler .Sh SYNOPSIS -.Nm zic +.Nm .Op Fl -version .Op Fl Dsv .Op Fl d Ar directory @@ -20,7 +20,7 @@ .Op Ar filename ... .Sh DESCRIPTION The -.Nm zic +.Nm utility reads text from the file(s) named on the command line and creates the time conversion information files specified in this input. If a @@ -31,7 +31,8 @@ the standard input is read. .Pp The following options are available: .Bl -tag -width indent -.\" ========== +.It Fl -version +Output version information and exit. .It Fl D Do not automatically create directories. If the input file(s) specify @@ -40,65 +41,52 @@ default behavior is to attempt to create the directory. If .Fl D is specified, -.Nm zic +.Nm will instead error out immediately. -.\" ========== .It Fl d Ar directory Create time conversion information files in the named directory rather than in the standard directory named below. -.\" ========== .It Fl g Ar group After creating each output file, change its group ownership to the specified .Ar group (which can be either a name or a numeric group ID). -.\" ========== .It Fl L Ar leapsecondfilename Read leap second information from the file with the given name. If this option is not used, no leap second information appears in output files. -.\" ========== .It Fl l Ar timezone Use the given .Ar time zone as local time. The -.Nm zic +.Nm utility will act as if the input contained a link line of the form -.Bd -literal -offset indent -.No "Link timezone localtime -.Ed +.Pp +.D1 No "Link timezone localtime" +.Pp (Note that this action has no effect on .Fx , since the local time zone is specified in .Pa /etc/localtime and not .Pa /usr/share/zoneinfo/localtime . ) -.\" ========== .It Fl m Ar mode After creating each output file, change its access mode to .Ar mode . Both numeric and alphabetic modes are accepted (see .Xr chmod 1 ) . -.\" ========== .It Fl p Ar timezone Use the given .Ar "time zone" Ns 's rules when handling POSIX-format time zone environment variables. The -.Nm zic +.Nm utility will act as if the input contained a link line of the form -.Bd -literal -offset indent -.No "Link timezone posixrules -.Ed -.\" ========== -.It Fl s -Limit time values stored in output files to values that are the same -whether they're taken to be signed or unsigned. -You can use this option to generate SVVS-compatible files. -.\" ========== +.Pp +.D1 No "Link timezone posixrules" .It Fl u Ar user After creating each output file, change its owner to .Ar user @@ -108,10 +96,10 @@ Complain if a year that appears in a data file is outside the range of years representable by .Xr time 3 values. -.\" ========== -.It Fl -version -Output version information and exit. -.\" ========== +.It Fl s +Limit time values stored in output files to values that are the same +whether they are taken to be signed or unsigned. +You can use this option to generate SVVS-compatible files. .It Fl y Ar command Use the given .Ar command @@ -126,7 +114,7 @@ Leading and trailing white space on input lines is ignored. An unquoted sharp character (#) in the input introduces a comment which extends to the end of the line the sharp character appears on. White space characters and sharp characters may be enclosed in double quotes -(") if they're to be used as part of a field. +(") if they are to be used as part of a field. Any line that is blank (after comment stripping) is ignored. Non-blank lines are expected to be of one of three types: rule lines, zone lines, and link lines. @@ -179,7 +167,7 @@ inclusive. If .Em TYPE is something else, then -.Nm zic +.Nm executes the command .Li yearistype Ar year Ar type to check the type of a year: diff --git a/zic.tproj/zic.c b/zic.tproj/zic.c index 12659d0..7d02a4c 100644 --- a/zic.tproj/zic.c +++ b/zic.tproj/zic.c @@ -2,7 +2,7 @@ static const char elsieid[] = "@(#)zic.c 7.116"; #ifndef lint static const char rcsid[] = - "$FreeBSD: src/usr.sbin/zic/zic.c,v 1.17 2004/10/19 20:30:09 ru Exp $"; + "$FreeBSD: src/usr.sbin/zic/zic.c,v 1.18 2007/12/03 10:45:44 kevlo Exp $"; #endif /* not lint */ #include "private.h" @@ -1990,7 +1990,10 @@ register char * cp; else while ((*dp = *cp++) != '"') if (*dp != '\0') ++dp; - else error(_("odd number of quotation marks")); + else { + error(_("odd number of quotation marks")); + exit(EXIT_FAILURE); + } } while (*cp != '\0' && *cp != '#' && (!isascii(*cp) || !isspace((unsigned char) *cp))); if (isascii(*cp) && isspace((unsigned char) *cp)) diff --git a/zprint.tproj/Makefile b/zprint.tproj/Makefile index 662c497..508fdcf 100644 --- a/zprint.tproj/Makefile +++ b/zprint.tproj/Makefile @@ -4,4 +4,7 @@ Install_Dir = /usr/bin CFILES = zprint.c MANPAGES = zprint.1 +Extra_CC_Flags = -mdynamic-no-pic +Extra_LD_Flags = -dead_strip -lutil + include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zprint.tproj/zprint.c b/zprint.tproj/zprint.c index 8187b1b..e637a45 100644 --- a/zprint.tproj/zprint.c +++ b/zprint.tproj/zprint.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #define streql(a, b) (strcmp((a), (b)) == 0) #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0) @@ -90,6 +92,11 @@ main(argc, argv) kern_return_t kr; int i, j; + if (0 != reexec_to_match_kernel()) { + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); + } + program = strrchr(argv[0], '/'); if (program == NULL) program = argv[0]; -- 2.45.2