]> git.saurik.com Git - apple/shell_cmds.git/commitdiff
shell_cmds-175.tar.gz os-x-109 os-x-1091 os-x-1092 os-x-1093 os-x-1094 os-x-1095 v175
authorApple <opensource@apple.com>
Wed, 12 Dec 2012 23:34:33 +0000 (23:34 +0000)
committerApple <opensource@apple.com>
Wed, 12 Dec 2012 23:34:33 +0000 (23:34 +0000)
hexdump/display.c
hexdump/parse.c
killall/killall.c
shell_cmds.xcodeproj/project.pbxproj
systime/systime.1 [new file with mode: 0644]
systime/systime.c [new file with mode: 0644]

index c0070a12c3456c2011bc37f75dfc60624878cd86..978a50c9d3e35c7e49d83ab84e00c09ab7c90e3f 100644 (file)
@@ -270,7 +270,12 @@ get(void)
                         * XXX bcmp() is not quite right in the presence
                         * of multibyte characters.
                         */
+#ifdef __APPLE__
+                       /* 5650060 */
+                       if (!need && vflag != ALL && 
+#else
                        if (vflag != ALL && 
+#endif
                            valid_save && 
                            bcmp(curp, savp, nread) == 0) {
                                if (vflag != DUP)
index 4f81cb7f33969436fdcd387bca934d2ac7a69742..5445f1800245076d1f38bf01b085d0b5e4825055 100644 (file)
@@ -295,6 +295,11 @@ isint:                             cs[2] = '\0';
                                case 2:
                                        pr->bcnt = 2;
                                        break;
+#ifdef __APPLE__
+                               case 8:
+                                       pr->bcnt = 8;
+                                       break;
+#endif /* __APPLE__ */
                                default:
                                        p1[1] = '\0';
                                        badcnt((char *)p1);
index 6f23a70e1dbf832e3fb54e1dea79bebc7695b0c7..cf2aabb24d68b4ea1d5912db7b008986a94d424d 100644 (file)
@@ -360,7 +360,7 @@ main(int ac, char **av)
 
        for (i = 0; i < nprocs; i++) {
 #ifdef __APPLE__
-               if ((procs[i].kp_proc.p_stat & SZOMB) == SZOMB && !zflag)
+               if (procs[i].kp_proc.p_stat == SZOMB && !zflag)
                        continue;
                thispid = procs[i].kp_proc.p_pid;
 
@@ -424,7 +424,7 @@ main(int ac, char **av)
 
                thistdev = procs[i].kp_eproc.e_tdev;
 #else /* !__APPLE__ */
-               if ((procs[i].ki_stat & SZOMB) == SZOMB && !zflag)
+               if (procs[i].ki_stat == SZOMB && !zflag)
                        continue;
                thispid = procs[i].ki_pid;
                strncpy(thiscmd, procs[i].ki_comm, MAXCOMLEN);
index 8bbe58d4c81cb210d4cd85ab1c451286d1331129..5f0eff8965a58a4702c90fc8737a9cf97cafe52f 100644 (file)
@@ -14,6 +14,7 @@
                                FCE30EB814B531EC00CC0294 /* ShellScript */,
                        );
                        dependencies = (
+                               C6868583154725A30025D623 /* PBXTargetDependency */,
                                FCBA150114A144F700AA698B /* PBXTargetDependency */,
                                FCBA150314A144F700AA698B /* PBXTargetDependency */,
                                FCBA150514A144F700AA698B /* PBXTargetDependency */,
@@ -73,6 +74,7 @@
                                FCE30F4D14B619C900CC0294 /* Run Script */,
                        );
                        dependencies = (
+                               C6868581154725990025D623 /* PBXTargetDependency */,
                                FCE30F4F14B619E600CC0294 /* PBXTargetDependency */,
                                FCE30F5114B619E600CC0294 /* PBXTargetDependency */,
                                FCE30F5314B619E600CC0294 /* PBXTargetDependency */,
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+               C686857A154725700025D623 /* systime.c in Sources */ = {isa = PBXBuildFile; fileRef = C6868579154725700025D623 /* systime.c */; };
+               C686857C154725700025D623 /* systime.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C686857B154725700025D623 /* systime.1 */; };
                FC2B5BFB14B3CCC600ECF511 /* uname.c in Sources */ = {isa = PBXBuildFile; fileRef = FCBA140914A141A300AA698B /* uname.c */; };
                FC2B5BFD14B3CCD200ECF511 /* uname.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCBA140814A141A300AA698B /* uname.1 */; };
                FC2B5BFE14B3CCD700ECF511 /* true.c in Sources */ = {isa = PBXBuildFile; fileRef = FCBA140414A141A300AA698B /* true.c */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+               C6868580154725990025D623 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FC80BF5714A05A2F00C6F7F5 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = C6868575154725700025D623;
+                       remoteInfo = systime;
+               };
+               C6868582154725A30025D623 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FC80BF5714A05A2F00C6F7F5 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = C6868575154725700025D623;
+                       remoteInfo = systime;
+               };
                FC5D63A114B9864400123E48 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = FC80BF5714A05A2F00C6F7F5 /* Project object */;
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
+               C6868574154725700025D623 /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/local/share/man/man1/;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               C686857C154725700025D623 /* systime.1 in CopyFiles */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
                FC5D638614B9819E00123E48 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               C6868576154725700025D623 /* systime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = systime; sourceTree = BUILT_PRODUCTS_DIR; };
+               C6868579154725700025D623 /* systime.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = systime.c; sourceTree = "<group>"; };
+               C686857B154725700025D623 /* systime.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = systime.1; sourceTree = "<group>"; };
                FC5D636814B9808E00123E48 /* conv.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = conv.c; sourceTree = "<group>"; };
                FC5D636914B9808E00123E48 /* display.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = display.c; sourceTree = "<group>"; };
                FC5D636A14B9808E00123E48 /* hexdump.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = hexdump.1; sourceTree = "<group>"; };
                FCBA13A914A141A300AA698B /* locate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = locate.h; sourceTree = "<group>"; };
                FCBA13AA14A141A300AA698B /* locate.rc */ = {isa = PBXFileReference; lastKnownFileType = text; path = locate.rc; sourceTree = "<group>"; };
                FCBA13AB14A141A300AA698B /* locate.updatedb.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = locate.updatedb.8; sourceTree = "<group>"; };
-               FCBA13AC14A141A300AA698B /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                FCBA13AD14A141A300AA698B /* mklocatedb.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = mklocatedb.sh; sourceTree = "<group>"; };
                FCBA13AE14A141A300AA698B /* pathnames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = "<group>"; };
                FCBA13AF14A141A300AA698B /* updatedb.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = updatedb.sh; sourceTree = "<group>"; };
                FCBA13B014A141A300AA698B /* util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = "<group>"; };
                FCBA13B114A141A300AA698B /* locate.code.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = locate.code.8; sourceTree = "<group>"; };
-               FCBA13B214A141A300AA698B /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                FCBA13B414A141A300AA698B /* logname.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = logname.1; sourceTree = "<group>"; };
                FCBA13B514A141A300AA698B /* logname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = logname.c; sourceTree = "<group>"; };
                FCBA13C014A141A300AA698B /* mktemp.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = mktemp.1; sourceTree = "<group>"; };
                FCBA13E914A141A300AA698B /* shlock.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = shlock.c; sourceTree = "<group>"; };
                FCBA13EC14A141A300AA698B /* sleep.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sleep.1; sourceTree = "<group>"; };
                FCBA13ED14A141A300AA698B /* sleep.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sleep.c; sourceTree = "<group>"; };
-               FCBA13EF14A141A300AA698B /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                FCBA13F014A141A300AA698B /* su.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = su.1; sourceTree = "<group>"; };
                FCBA13F114A141A300AA698B /* su.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = su.c; sourceTree = "<group>"; };
                FCBA13F214A141A300AA698B /* su.pam */ = {isa = PBXFileReference; lastKnownFileType = text; path = su.pam; sourceTree = "<group>"; };
                FCBA140D14A141A300AA698B /* users.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = users.c; sourceTree = "<group>"; };
                FCBA140F14A141A300AA698B /* extern.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = "<group>"; };
                FCBA141014A141A300AA698B /* fmt.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fmt.c; sourceTree = "<group>"; };
-               FCBA141114A141A300AA698B /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                FCBA141214A141A300AA698B /* pr_time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pr_time.c; sourceTree = "<group>"; };
                FCBA141314A141A300AA698B /* proc_compare.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = proc_compare.c; sourceTree = "<group>"; };
                FCBA141414A141A300AA698B /* uptime.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = uptime.1; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+               C6868573154725700025D623 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FC5D638514B9819E00123E48 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               C6868578154725700025D623 /* systime */ = {
+                       isa = PBXGroup;
+                       children = (
+                               C6868579154725700025D623 /* systime.c */,
+                               C686857B154725700025D623 /* systime.1 */,
+                       );
+                       path = systime;
+                       sourceTree = "<group>";
+               };
                FC5D636714B9808E00123E48 /* hexdump */ = {
                        isa = PBXGroup;
                        children = (
                                FCBA13E614A141A300AA698B /* shlock */,
                                FCBA13EA14A141A300AA698B /* sleep */,
                                FCBA13EE14A141A300AA698B /* su */,
+                               C6868578154725700025D623 /* systime */,
                                FCBA13F314A141A300AA698B /* tee */,
                                FCBA13F714A141A300AA698B /* test */,
                                FCBA13FD14A141A300AA698B /* time */,
                                FCE30EDE14B536C900CC0294 /* locate.code */,
                                FC5D638B14B9819E00123E48 /* what */,
                                FC5D639714B9822D00123E48 /* hexdump */,
+                               C6868576154725700025D623 /* systime */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                FCBA139D14A141A300AA698B /* bigram */,
                                FCBA13A014A141A300AA698B /* code */,
                                FCBA13A314A141A300AA698B /* locate */,
-                               FCBA13B214A141A300AA698B /* Makefile */,
                        );
                        path = locate;
                        sourceTree = "<group>";
                                FCBA13A914A141A300AA698B /* locate.h */,
                                FCBA13AA14A141A300AA698B /* locate.rc */,
                                FCBA13AB14A141A300AA698B /* locate.updatedb.8 */,
-                               FCBA13AC14A141A300AA698B /* Makefile */,
                                FCBA13AD14A141A300AA698B /* mklocatedb.sh */,
                                FCBA13AE14A141A300AA698B /* pathnames.h */,
                                FCBA13AF14A141A300AA698B /* updatedb.sh */,
                FCBA13EE14A141A300AA698B /* su */ = {
                        isa = PBXGroup;
                        children = (
-                               FCBA13EF14A141A300AA698B /* Makefile */,
                                FCBA13F014A141A300AA698B /* su.1 */,
                                FCBA13F114A141A300AA698B /* su.c */,
                                FCBA13F214A141A300AA698B /* su.pam */,
                        children = (
                                FCBA140F14A141A300AA698B /* extern.h */,
                                FCBA141014A141A300AA698B /* fmt.c */,
-                               FCBA141114A141A300AA698B /* Makefile */,
                                FCBA141214A141A300AA698B /* pr_time.c */,
                                FCBA141314A141A300AA698B /* proc_compare.c */,
                                FCBA141414A141A300AA698B /* uptime.1 */,
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
+               C6868575154725700025D623 /* systime */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = C686857E154725700025D623 /* Build configuration list for PBXNativeTarget "systime" */;
+                       buildPhases = (
+                               C6868572154725700025D623 /* Sources */,
+                               C6868573154725700025D623 /* Frameworks */,
+                               C6868574154725700025D623 /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = systime;
+                       productName = systime;
+                       productReference = C6868576154725700025D623 /* systime */;
+                       productType = "com.apple.product-type.tool";
+               };
                FC5D637F14B9819E00123E48 /* what */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = FC5D638914B9819E00123E48 /* Build configuration list for PBXNativeTarget "what" */;
                                FCBA15C614A145A200AA698B /* shlock */,
                                FCBA15CE14A145A500AA698B /* sleep */,
                                FCBA15D614A145A700AA698B /* su */,
+                               C6868575154725700025D623 /* systime */,
                                FCBA15DE14A145A900AA698B /* tee */,
                                FCBA15E614A145AE00AA698B /* test */,
                                FCBA15EE14A145B000AA698B /* time */,
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+               C6868572154725700025D623 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               C686857A154725700025D623 /* systime.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FC5D638014B9819E00123E48 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+               C6868581154725990025D623 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = C6868575154725700025D623 /* systime */;
+                       targetProxy = C6868580154725990025D623 /* PBXContainerItemProxy */;
+               };
+               C6868583154725A30025D623 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = C6868575154725700025D623 /* systime */;
+                       targetProxy = C6868582154725A30025D623 /* PBXContainerItemProxy */;
+               };
                FC5D63A214B9864400123E48 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = FC5D638F14B9822D00123E48 /* hexdump */;
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
+               C686857D154725700025D623 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               INSTALL_PATH = /usr/local/bin;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                FC5D638A14B9819E00123E48 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+               C686857E154725700025D623 /* Build configuration list for PBXNativeTarget "systime" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               C686857D154725700025D623 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                FC5D638914B9819E00123E48 /* Build configuration list for PBXNativeTarget "what" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/systime/systime.1 b/systime/systime.1
new file mode 100644 (file)
index 0000000..43fb81f
--- /dev/null
@@ -0,0 +1,53 @@
+.Dd April 24, 2012\r
+.Dt systime 1\r
+.Os Darwin\r
+.Sh NAME\r
+.Nm systime\r
+.Nd gather system-wide time during program execution\r
+.Sh SYNOPSIS\r
+.Nm\r
+.Op Fl P\r
+.Ar utility Op Ar argument ...\r
+.Nm\r
+.Fl p\r
+.Nm\r
+.Op Fl P\r
+.Fl u Ar user\r
+.Fl s Ar sys\r
+.Fl i Ar idle\r
+.Sh DESCRIPTION\r
+.Nm\r
+is similar to\r
+.Xr time 1\r
+in that it allows you to execute a utility program. However after execution\r
+completes, it reports the system-wide time that was spent\r
+during that time period, instead of just the portion directly caused\r
+by the utility. This can be used to gather information about CPU\r
+utilization by kernel threads (AIO, networking) and interrupt routines\r
+on behalf of a program, but not directly attributed to it.\r
+.Pp\r
+The\r
+.Nm\r
+program can also be used to snapshot counters with\r
+.Fl p\r
+and then later used with\r
+.Fl u Fl s Fl i\r
+to calculate time spent during a time interval that doesn't correlate\r
+to a specific command execution. For example:\r
+.Pp\r
+.Bd -ragged -offset indent\r
+$ eval `systime -p`\r
+.Pp\r
+$ ... time passes ...\r
+.Pp\r
+$ systime -u $systime_user -s $systime_sys -i $systime_idle\r
+.Pp\r
+18.79 real 2.03 user 1.04 sys\r
+.Ed\r
+.Pp\r
+.Fl P\r
+can be used to print time spent as a percentage of overall CPU capacity\r
+of the system (capped at 100%)\r
+.Sh SEE ALSO\r
+.Xr time 1 ,\r
+.Xr top 1\r
diff --git a/systime/systime.c b/systime/systime.c
new file mode 100644 (file)
index 0000000..746a8bd
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2012 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 <mach/mach.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void usage(void);
+static void do_print(void);
+static void do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle);
+static kern_return_t get_processor_time(uint64_t *user, uint64_t *sys, uint64_t *idle);
+static kern_return_t get_processor_count(int *ncpu);
+
+int
+main(int argc, char *argv[])
+{
+       int ch;
+       const char *optu = NULL;
+       const char *opts = NULL;
+       const char *opti = NULL;
+       int pid;
+       int status;
+       uint64_t olduser, oldsystem, oldidle;
+       kern_return_t kret;
+       bool usepercent = false;
+
+       while ((ch = getopt(argc, argv, "Ppu:s:i:")) != -1) {
+               switch (ch) {
+               case 'P':
+                       usepercent = true;
+                       break;
+               case 'p':
+                       do_print();
+                       exit(0);
+                       break;
+               case 'u':
+                       optu = optarg;
+                       break;
+               case 's':
+                       opts = optarg;
+                       break;
+               case 'i':
+                       opti = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       }
+
+       if (optu || opts || opti) {
+               char *endstr;
+
+               if (!optu)
+                       usage();
+               olduser = strtoull(optu, &endstr, 0);
+               if (optu[0] == '\0' || endstr[0] != '\0')
+                       usage();
+
+               if (!opts)
+                       usage();
+               oldsystem = strtoull(opts, &endstr, 0);
+               if (opts[0] == '\0' || endstr[0] != '\0')
+                       usage();
+
+               if (!opti)
+                       usage();
+               oldidle = strtoull(opti, &endstr, 0);
+               if (opti[0] == '\0' || endstr[0] != '\0')
+                       usage();
+
+               do_difftime(usepercent, olduser, oldsystem, oldidle);
+               exit(0);
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc == 0)
+               usage();
+
+       kret = get_processor_time(&olduser, &oldsystem, &oldidle);
+       if (kret)
+               errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
+
+       switch(pid = vfork()) {
+               case -1:                        /* error */
+                       perror("time");
+                       exit(1);
+                       /* NOTREACHED */
+               case 0:                         /* child */
+                       execvp(*argv, argv);
+                       perror(*argv);
+                       _exit((errno == ENOENT) ? 127 : 126);
+                       /* NOTREACHED */
+       }
+
+       /* parent */
+       (void)signal(SIGINT, SIG_IGN);
+       (void)signal(SIGQUIT, SIG_IGN);
+       while (wait(&status) != pid);
+
+       do_difftime(usepercent, olduser, oldsystem, oldidle);
+
+       exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
+
+    return 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage: systime [-P] utility [argument ...]\n"
+                       "       systime -p\n"
+                       "       systime [-P] -u user -s sys -i idle\n");
+       exit(1);
+}
+
+static void
+do_print(void)
+{
+       uint64_t user, system, idle;
+       kern_return_t kret;
+
+       kret = get_processor_time(&user, &system, &idle);
+       if (kret)
+               errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
+
+       printf("systime_user=%llu\n",   user);
+       printf("systime_sys=%llu\n",    system);
+       printf("systime_idle=%llu\n",   idle);
+}
+
+static void
+do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle)
+{
+       uint64_t user, system, idle;
+       uint64_t userelapsed, systemelapsed, idleelapsed, totalelapsed;
+       kern_return_t kret;
+
+       kret = get_processor_time(&user, &system, &idle);
+       if (kret)
+               errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
+
+       userelapsed = user - olduser;
+       systemelapsed = system - oldsystem;
+       idleelapsed = idle - oldidle;
+       totalelapsed = userelapsed + systemelapsed + idleelapsed;
+
+       if (usepercent) {
+               fprintf(stderr, "%1.02f%% user %1.02f%% sys %1.02f%% idle\n",
+                          ((double)userelapsed * 100)/totalelapsed,
+                          ((double)systemelapsed * 100)/totalelapsed,
+                          ((double)idleelapsed * 100)/totalelapsed);
+       } else {
+               int ncpu;
+
+               kret = get_processor_count(&ncpu);
+               if (kret)
+                       errx(1, "Error getting processor count: %s (%d)", mach_error_string(kret), kret);
+
+               fprintf(stderr, "%1.02f real %1.02f user %1.02f sys\n",
+                               ((double)totalelapsed) / 1000 /* ms per sec */ / ncpu,
+                               ((double)userelapsed) / 1000,
+                               ((double)systemelapsed) / 1000);
+       }
+}
+
+static kern_return_t
+get_processor_time(uint64_t *user, uint64_t *sys, uint64_t *idle)
+{
+       host_name_port_t        host;
+       kern_return_t           kret;
+       host_cpu_load_info_data_t       host_load;
+       mach_msg_type_number_t  count;
+
+       host = mach_host_self();
+
+       count = HOST_CPU_LOAD_INFO_COUNT;
+
+       kret = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)&host_load, &count);
+       if (kret)
+               return kret;
+
+       *user = ((uint64_t)host_load.cpu_ticks[CPU_STATE_USER]) * 10 /* ms per tick */;
+       *sys = ((uint64_t)host_load.cpu_ticks[CPU_STATE_SYSTEM]) * 10;
+       *idle = ((uint64_t)host_load.cpu_ticks[CPU_STATE_IDLE]) * 10;
+
+       return KERN_SUCCESS;
+}
+
+static kern_return_t
+get_processor_count(int *ncpu)
+{
+       host_name_port_t        host;
+       kern_return_t           kret;
+       host_basic_info_data_t  hi;
+       mach_msg_type_number_t  count;
+
+       host = mach_host_self();
+
+       count = HOST_BASIC_INFO_COUNT;
+
+       kret = host_info(host, HOST_BASIC_INFO, (host_info_t)&hi, &count);
+       if (kret)
+               return kret;
+
+       *ncpu = hi.avail_cpus;
+
+       return KERN_SUCCESS;
+}