PROJECTVERSION = 2.8
PROJECT_TYPE = Aggregate
-TOOLS = dynamic_pager.tproj ac.tproj accton.tproj arch.tproj at.tproj\
- auditd.tproj audit.tproj\
- atrun.tproj chkpasswd.tproj chpass.tproj dmesg.tproj\
- getconf.tproj getty.tproj hostinfo.tproj iostat.tproj kgmon.tproj\
- ktrace.tproj login.tproj makekey.tproj\
- mkfile.tproj nvram.tproj passwd.tproj pwd_mkdb.tproj\
- reboot.tproj shutdown.tproj sync.tproj sysctl.tproj\
- update.tproj vipw.tproj zic.tproj zdump.tproj vm_stat.tproj\
+Embedded=$(shell tconf --test TARGET_OS_EMBEDDED)
+
+TOOLS = dynamic_pager.tproj ac.tproj accton.tproj arch.tproj\
+ bootlog.tproj\
+ dirhelper.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\
- kdump.tproj sadc.tproj sar.tproj pt_chown.tproj sa.tproj\
- utmp_update.tproj
+ sadc.tproj sar.tproj sa.tproj
+
+ifeq "$(Embedded)" "NO"
+TOOLS += at.tproj atrun.tproj\
+ auditd.tproj audit.tproj\
+ chkpasswd.tproj chpass.tproj\
+ shutdown.tproj
+endif
LIBRARIES = dp_notify_lib
CLEAN_ALL_SUBPROJECTS = YES
SUBPROJECTS =
OTHER_CFLAGS = -mdynamic-no-pic
+ifeq "$(shell tconf --test TARGET_OS_EMBEDDED)" "YES"
+OTHER_LDFLAGS = -dead_strip
+endif
"auditd.tproj",
"chkpasswd.tproj",
"chpass.tproj",
+ "dirhelper.tproj",
"dmesg.tproj",
"getconf.tproj",
"getty.tproj",
"hostinfo.tproj",
"iostat.tproj",
"kgmon.tproj",
- "ktrace.tproj",
"login.tproj",
"makekey.tproj",
"mkfile.tproj",
+ "newgrp.tproj",
"nologin.tproj",
"nvram.tproj",
"pagesize.tproj",
"latency.tproj",
"sc_usage.tproj",
"fs_usage.tproj",
- "kdump.tproj",
"sadc.tproj",
"sar.tproj"
);
.Os BSD 4
.Sh NAME
.Nm ac
-.Nd display connect time accounting
+.Nd display connect-time accounting
.Sh SYNOPSIS
.Nm ac
.Op Fl d
.Op Fl w Ar file
.Op Ar users ...
.Sh DESCRIPTION
-If the file
-.Pa /var/log/wtmp
-exists,
-a record of individual
-login and logout times are written to it by
-.Xr init 8
-and
+A record of individual
+login and logout times are written to the system log by
.Xr login 8
+and
+.Xr launchd 8 ,
respectively.
The program
.Nm ac
-examines these
-records and writes the accumulated connect time for all logins to the
-standard output.
+examines these records
+and writes the accumulated connect time (in decimal hours)
+for all logins to the standard output.
.Pp
Options available:
.Bl -tag -width people
Display individual user totals.
.It Fl w Ar file
Read raw connect time data from
-.Ar file
-instead of the default file
-.Pa /var/log/wtmp .
+.Ar file ,
+instead of the system log.
.It Ar users ...
Display totals for the given individuals
only.
.El
.Pp
If no arguments are given,
-.Nm
-displays the total amount of login time for all active accounts on the
-system.
-.Pp
-The default
-.Pa wtmp
-file is an infinitely increasing file
-unless frequently truncated. This is normally
-done by the daily daemon scripts scheduled by
-.Xr cron 8
-which rename and rotate the
-.Pa wtmp
-files before truncating them (and keeping about a weeks worth on hand).
-No login times are collected however, if the file does not exist.
-.Sh FILES
-.Bl -tag -width /var/log/wtmp.[0-7] -compact
-.It Pa /var/log/wtmp
-.It Pa /var/log/wtmp.[0-7]
-rotated files
-.El
+.Nm ac
+displays the total amount of login time
+for all active accounts on the system.
.Sh SEE ALSO
-.Xr init 8 ,
-.Xr sa 8 ,
.Xr login 1 ,
-.Xr utmp 5 .
+.Xr utmpx 5 ,
+.Xr launchd 8 ,
+.Xr sa 8
.Sh HISTORY
-A
-.Nm
+An
+.Nm ac
command appeared in Version 6 AT&T UNIX.
*/
#ifndef lint
-static char rcsid[] = "$Id: ac.c,v 1.1.1.2 2000/01/11 02:09:57 wsanchez Exp $";
+#include <sys/cdefs.h>
+__unused static char rcsid[] = "$Id: ac.c,v 1.2 2006/02/07 05:51:22 lindak Exp $";
#endif
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <utmp.h>
+#include <utmpx.h>
#include <unistd.h>
+#define UT_NAMESIZE 8 /* from utmp.h; only for formatting */
+
/*
* this is for our list of currently logged in sessions
*/
struct utmp_list {
struct utmp_list *next;
- struct utmp usr;
+ struct utmpx usr;
};
/*
*/
struct user_list {
struct user_list *next;
- char name[UT_NAMESIZE+1];
+ char name[_UTX_USERSIZE+1];
time_t secs;
};
*/
struct tty_list {
struct tty_list *next;
- char name[UT_LINESIZE+3];
+ char name[_UTX_USERSIZE+3];
int len;
int ret;
};
#endif
int main __P((int, char **));
-int ac __P((FILE *));
+int ac __P((void));
struct tty_list *add_tty __P((char *));
int do_tty __P((char *));
-FILE *file __P((char *));
-struct utmp_list *log_in __P((struct utmp_list *, struct utmp *));
-struct utmp_list *log_out __P((struct utmp_list *, struct utmp *));
+struct utmp_list *log_in __P((struct utmp_list *, struct utmpx *));
+struct utmp_list *log_out __P((struct utmp_list *, struct utmpx *));
int on_console __P((struct utmp_list *));
void show __P((char *, time_t));
void show_today __P((struct user_list *, struct utmp_list *,
struct user_list *update_user __P((struct user_list *, char *, time_t));
void usage __P((void));
-/*
- * open wtmp or die
- */
-FILE *
-file(name)
- char *name;
-{
- FILE *fp;
-
- if ((fp = fopen(name, "r")) == NULL)
- err(1, "%s", name);
- /* in case we want to discriminate */
- if (strcmp(_PATH_WTMP, name))
- Flags |= AC_W;
- return fp;
-}
-
struct tty_list *
add_tty(name)
char *name;
add_tty(optarg);
break;
case 'w':
- fp = file(optarg);
+ wtmpxname(optarg);
break;
case '?':
default:
}
if (Flags & AC_D)
Flags &= ~AC_P;
- if (fp == NULL) {
- /*
- * if _PATH_WTMP does not exist, exit quietly
- */
- if (access(_PATH_WTMP, 0) != 0 && errno == ENOENT)
- return 0;
-
- fp = file(_PATH_WTMP);
- }
- ac(fp);
+ ac();
return 0;
}
yesterday++;
for (lp = logins; lp != NULL; lp = lp->next) {
- secs = yesterday - lp->usr.ut_time;
- Users = update_user(Users, lp->usr.ut_name, secs);
- lp->usr.ut_time = yesterday; /* as if they just logged in */
+ secs = yesterday - lp->usr.ut_tv.tv_sec;
+ Users = update_user(Users, lp->usr.ut_user, secs);
+ lp->usr.ut_tv.tv_sec = yesterday; /* as if they just logged in */
}
secs = 0;
for (up = users; up != NULL; up = up->next) {
struct utmp_list *
log_out(head, up)
struct utmp_list *head;
- struct utmp *up;
+ struct utmpx *up;
{
struct utmp_list *lp, *lp2, *tlp;
time_t secs;
for (lp = head, lp2 = NULL; lp != NULL; )
- if (*up->ut_line == '~' || strncmp(lp->usr.ut_line, up->ut_line,
+ if (up->ut_type == BOOT_TIME || up->ut_type == SHUTDOWN_TIME || strncmp(lp->usr.ut_line, up->ut_line,
sizeof (up->ut_line)) == 0) {
- secs = up->ut_time - lp->usr.ut_time;
- Users = update_user(Users, lp->usr.ut_name, secs);
+ secs = up->ut_tv.tv_sec - lp->usr.ut_tv.tv_sec;
+ Users = update_user(Users, lp->usr.ut_user, secs);
#ifdef DEBUG
if (Debug)
printf("%-.*s %-.*s: %-.*s logged out (%2d:%02d:%02d)\n",
- 19, ctime(&up->ut_time),
- sizeof (lp->usr.ut_line), lp->usr.ut_line,
- sizeof (lp->usr.ut_name), lp->usr.ut_name,
+ 19, ctime(&up->ut_tv.tv_sec),
+ (int)sizeof (lp->usr.ut_line), lp->usr.ut_line,
+ (int)sizeof (lp->usr.ut_user), lp->usr.ut_user,
secs / 3600, (secs % 3600) / 60, secs % 60);
#endif
/*
struct utmp_list *
log_in(head, up)
struct utmp_list *head;
- struct utmp *up;
+ struct utmpx *up;
{
struct utmp_list *lp;
return head;
/*
* ok, no recorded login, so they were here when wtmp
- * started! Adjust ut_time!
+ * started! Adjust ut_tv.tv_sec!
*/
- up->ut_time = FirstTime;
+ up->ut_tv.tv_sec = FirstTime;
/*
* this allows us to pick the right logout
*/
err(1, "malloc");
lp->next = head;
head = lp;
- memmove((char *)&lp->usr, (char *)up, sizeof (struct utmp));
+ memmove((char *)&lp->usr, (char *)up, sizeof (struct utmpx));
#ifdef DEBUG
if (Debug) {
printf("%-.*s %-.*s: %-.*s logged in", 19,
- ctime(&lp->usr.ut_time), sizeof (up->ut_line),
- up->ut_line, sizeof (up->ut_name), up->ut_name);
+ ctime(&lp->usr.ut_tv.tv_sec), (int)sizeof (up->ut_line),
+ up->ut_line, (int)sizeof (up->ut_user), up->ut_user);
if (*up->ut_host)
- printf(" (%-.*s)", sizeof (up->ut_host), up->ut_host);
+ printf(" (%-.*s)", (int)sizeof (up->ut_host), up->ut_host);
putchar('\n');
}
#endif
}
int
-ac(fp)
- FILE *fp;
+ac()
{
struct utmp_list *lp, *head = NULL;
- struct utmp usr;
+ struct utmpx *u, end;
struct tm *ltm;
time_t secs = 0;
int day = -1;
- while (fread((char *)&usr, sizeof(usr), 1, fp) == 1) {
+ setutxent_wtmp(1); /* read in forward direction */
+ while ((u = getutxent_wtmp()) != NULL) {
if (!FirstTime)
- FirstTime = usr.ut_time;
+ FirstTime = u->ut_tv.tv_sec;
if (Flags & AC_D) {
- ltm = localtime(&usr.ut_time);
+ ltm = localtime(&u->ut_tv.tv_sec);
if (day >= 0 && day != ltm->tm_yday) {
day = ltm->tm_yday;
/*
* print yesterday's total
*/
- secs = usr.ut_time;
+ secs = u->ut_tv.tv_sec;
secs -= ltm->tm_sec;
secs -= 60 * ltm->tm_min;
secs -= 3600 * ltm->tm_hour;
} else
day = ltm->tm_yday;
}
- switch(*usr.ut_line) {
- case '|':
- secs = usr.ut_time;
+ switch(u->ut_type) {
+ case OLD_TIME:
+ secs = u->ut_tv.tv_sec;
break;
- case '{':
- secs -= usr.ut_time;
+ case NEW_TIME:
+ secs -= u->ut_tv.tv_sec;
/*
* adjust time for those logged in
*/
for (lp = head; lp != NULL; lp = lp->next)
- lp->usr.ut_time -= secs;
+ lp->usr.ut_tv.tv_sec -= secs;
break;
- case '~': /* reboot or shutdown */
- head = log_out(head, &usr);
- FirstTime = usr.ut_time; /* shouldn't be needed */
+ case BOOT_TIME: /* reboot or shutdown */
+ case SHUTDOWN_TIME:
+ head = log_out(head, u);
+ FirstTime = u->ut_tv.tv_sec; /* shouldn't be needed */
break;
- default:
+ case USER_PROCESS:
/*
* if they came in on tty[p-y]*, then it is only
* a login session if the ut_host field is non-empty
*/
- if (*usr.ut_name) {
- if (strncmp(usr.ut_line, "tty", 3) != 0 ||
- strchr("pqrstuvwxy", usr.ut_line[3]) == 0 ||
- *usr.ut_host != '\0')
- head = log_in(head, &usr);
- } else
- head = log_out(head, &usr);
+ if (strncmp(u->ut_line, "tty", 3) != 0 ||
+ strchr("pqrstuvwxy", u->ut_line[3]) == 0 ||
+ *u->ut_host != '\0')
+ head = log_in(head, u);
+ break;
+ case DEAD_PROCESS:
+ head = log_out(head, u);
break;
}
}
- (void)fclose(fp);
- usr.ut_time = time((time_t *)0);
- (void)strcpy(usr.ut_line, "~");
+ endutxent_wtmp();
+ bzero(&end, sizeof(end));
+ end.ut_tv.tv_sec = time((time_t *)0);
+ end.ut_type = SHUTDOWN_TIME;
if (Flags & AC_D) {
- ltm = localtime(&usr.ut_time);
+ ltm = localtime(&end.ut_tv.tv_sec);
if (day >= 0 && day != ltm->tm_yday) {
/*
* print yesterday's total
*/
- secs = usr.ut_time;
+ secs = end.ut_tv.tv_sec;
secs -= ltm->tm_sec;
secs -= 60 * ltm->tm_min;
secs -= 3600 * ltm->tm_hour;
/*
* anyone still logged in gets time up to now
*/
- head = log_out(head, &usr);
+ head = log_out(head, &end);
if (Flags & AC_D)
show_today(Users, head, time((time_t *)0));
CFILES = accton.c
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble accton.8
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
# Makefile API), which are rules that get invoked before and after the install
# target runs. Such rules should be specified with the '::' syntax rather than
# a single colon.
+
+after_install:
+ install -d $(DSTROOT)/usr/share/man/man8
+ install -m 0444 accton.8 $(DSTROOT)/usr/share/man/man8/accton.8
+
--- /dev/null
+.\" Copyright (c) 1993 Christopher G. Demetriou
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. 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
+.Dt ACCTON 8
+.Os BSD 4
+.Sh NAME
+.Nm accton
+.Nd enable/disable system accounting
+.Sh SYNOPSIS
+.Nm accton
+.Op Ar file
+.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.
+.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.
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
+__unused static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)accton.c 8.1 (Berkeley) 6/6/93";
+__unused static char sccsid[] = "@(#)accton.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#include <sys/types.h>
PROJECTVERSION = 2.8
PROJECT_TYPE = Tool
-CFILES = arch.c
+MFILES = arch.m
+FRAMEWORKS = -framework Foundation
-OTHERSRCS = Makefile PB.project Makefile.postamble arch.1 machine.1
+OTHERSRCS = Makefile PB.project Makefile.postamble arch.1 machine.1 arch_helper.pl
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+HELPERDIR = /AppleInternal/Developer/Tools
after_install::
install -d $(DSTROOT)/usr/share/man/man1
install -c -m 444 arch.1 $(DSTROOT)/usr/share/man/man1
install -c -m 444 machine.1 $(DSTROOT)/usr/share/man/man1
@-$(RM) -f $(DSTROOT)$(INSTALLDIR)/machine
ln $(DSTROOT)$(INSTALLDIR)/arch $(DSTROOT)$(INSTALLDIR)/machine
+ install -d $(DSTROOT)$(HELPERDIR)
+ install -c -m 755 arch_helper.pl $(DSTROOT)$(HELPERDIR)
.\" $OpenBSD: arch.1,v 1.2 1996/06/29 20:29:34 tholo Exp $
.\"
.\" Modifications made 8/20/97 (c) Apple Computer, Inc.
+.\" Modifications made 11/12/06 (c) Apple Computer, Inc.
-.Dd August 20, 1997
+.Dd November 12, 2006
.Dt ARCH 1
-.Os Mac OS X
+.Os "Mac OS X"
.Sh NAME
.Nm arch
-.Nd print architecture type
+.Nd print architecture type or run selected architecture of a universal binary
.Sh SYNOPSIS
.Nm arch
+.Nm arch
+.Op Fl h
+.Oo
+.Oo Fl Ns Ar arch_name | Fl arch Ar arch_name Oc Ns ...
+.Oc
+.Ar prog
+.Op Ar args No ...
.Sh DESCRIPTION
The
.Nm arch
-command displays the machine's architecture type.
+command with no arguments, displays the machine's architecture type.
+.Pp
+The other use of the
+.Nm arch
+command it to run a selected architecture of a universal binary.
+A universal binary contains code that can run on different architectures.
+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
+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
+try to pick another architecture.
+On 64-bit processors, a 32-bit architecture is tried.
+If this is also unavailable, the operating system on an intel processor will
+try running a 32-bit powerpc architecture.
+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.
+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
+The
+.Fl h
+option prints a usage message and exits.
+.Pp
+The
+.Ar arch_name
+argument must be one of the currently supported architectures:
+.Bl -tag -width x86_64 -offset indent
+.It i386
+32-bit intel
+.It ppc
+32-bit powerpc
+.It ppc64
+64-bit powerpc
+.It x86_64
+64-bit intel
+.El
+.Pp
+Either prefix the architecture with a hyphen, or (for compatibility with
+other commands), use
+.Fl arch
+followed by the architecture.
+.Pp
+If more than one architecture is specified, the operating system will try each
+one in order, skipping an architecture that is not supported on the current
+processor, or is unavailable in the universal binary.
+.Pp
+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
+command search path.
+.Pp
+If no architectures are specified on the command line, the
+.Nm arch
+command takes the basename of the
+.Ar prog
+argument and searches for the first property list file with that basename and
+the
+.Pa \&.plist
+suffix, in the
+.Pa archSettings
+sub-directory in each of the standard domains, in the following order:
+.Bl -tag -width ".Pa /Network/Library/archSettings" -offset indent
+.It ~/Library/archSettings
+User settings
+.It /Library/archSettings
+Local settings
+.It /Network/Library/archSettings
+Network settings
+.It /System/Library/archSettings
+System settings
+.El
+.Pp
+This property list contains the architecture order preferences, as well
+as the full path to the real executable.
+For examples of the property list format, look at the files in
+.Pa /System/Library/archSettings .
+.Ss Example
+On an intel processor:
+.Bd -literal -offset indent
+% perl -MConfig -e 'printf "%s\\n", $Config{byteorder}'
+1234
+.Ed
+.Pp
+shows the intel little endian byte order, while:
+.Bd -literal -offset indent
+% arch -ppc perl -MConfig -e 'printf "%s\\n", $Config{byteorder}'
+4321
+.Ed
+.Pp
+runs the powerpc architecture, and displays big endian byte order.
+.Ss Making links to the arch command
+When a link is made to
+.Nm arch
+command with a different name, that name is used to find
+the corresponding property list file.
+Thus, other commands can be wrapped so that they have custom architecture
+selection order.
+.Pp
+Because of some internal logic in the code, hard links to the
+.Nm arch
+command may not work quite right.
+It is best to avoid using hard links, and only use symbolic links to the
+.Nm arch
+command.
+.Ss Environment
+The environment variable
+.Ev ARCHPREFERENCE
+can be used to provide architecture order preferences.
+It is checked before looking for the corresponding property list file.
+.Pp
+The value of the environment variable
+.Ev ARCHPREFERENCE
+is composed of one or more specifiers, separated by semicolons.
+A specifier is made up of one, two or three fields, separated by colons.
+Architectures specified in order, are separated by commas and make up the last
+(mandatory) field.
+The first field, if specified, is a name of a program, which selects this
+specifier if that name matches the program name in question.
+If the name field is empty or there is no name field, the specifier matches
+any program name.
+Thus, ordering of specifiers is important, and the one with no name should
+be last.
+.Pp
+When the
+.Nm arch
+command is called directly, the
+.Ar prog
+name provides the path information to the executable (possibly via the command
+search path).
+When a name is specified in a
+.Ev ARCHPREFERENCE
+specifier, the path information can alternately be specified as a second
+field following the name.
+When the
+.Nm arch
+command is called indirectly via a link, this path information must be
+specified.
+If not specified as a second field in a specifier, the executable path will
+be looked up in the corresponding property list file.
+.Ss Example ARCHPREFERENCE Values
+.Bl -tag -width " "
+.It ppc,i386,ppc64,x86_64
+A specifier that matches any name.
+.It foo:ppc,i386,ppc64,x86_64
+A specifier that matches the program named
+.Nm foo
+(the full executable path is in the
+.Pa foo.plist
+file).
+.It foo:/op/bin/boo:ppc,i386,ppc64,x86_64
+A specifier with all fields specified.
+.It baz:ppc,i386;i386,ppc
+A specifier for
+.Nm baz
+and a second specifier that would match any other name.
+.El
+.Sh BUGS
+Running the
+.Nm arch
+command on an interpreter script may not work if the interpreter is a link
+to the arch command, especially if a 64-bit architecture is specified (since the
+.Nm arch
+command is 2-way universal, 32-bit only).
.Sh SEE ALSO
.Xr machine 1
+++ /dev/null
-/*
- * 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@
- */
-/*
- * arch.c - determine the architecture of the machine ran on
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <mach/mach.h>
-#include <mach-o/arch.h>
-
-char *
- get_progname (char *name)
-{
- char *tmp;
- if (tmp = strrchr(name,'/'))
- return tmp+1;
- else return name;
-}
-
-int
- main (int argc, char **argv)
-{
- char *progname;
- const NXArchInfo *arch;
-
- if (argc > 1)
- {
- fprintf (stderr,"*error: %s takes no arguments\n",argv[0]);
- exit (-1);
- }
- arch = NXGetLocalArchInfo();
- if (arch == NULL)
- {
- fprintf (stderr,"Unknown architecture.\n");
- exit(-1);
- }
- progname = get_progname(argv[0]);
- if (strcmp (progname,ARCH_PROG) == 0) {
- arch = NXGetArchInfoFromCpuType(arch->cputype, CPU_SUBTYPE_MULTIPLE);
- if (arch == NULL)
- {
- fprintf (stderr,"Unknown architecture.\n");
- exit(-1);
- }
- }
- else if (strcmp (progname,MACHINE_PROG) == 0)
- ;
- else
- {
- fprintf
- (stderr,"*error: This program must be named either %s or %s\n",ARCH_PROG,MACHINE_PROG);
- exit (-1);
- }
- if (!isatty(fileno(stdin)))
- printf("%s", arch->name);
- else
- printf ("%s\n", arch->name);
- return 0;
-}
--- /dev/null
+/*
+ * Copyright (c) 1999, 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@
+ */
+
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <spawn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <err.h>
+#include <mach/mach.h>
+#include <mach-o/arch.h>
+#include <Foundation/Foundation.h>
+
+#ifndef ARCH_PROG
+#define ARCH_PROG "arch"
+#endif
+#define CPUDELTA 10
+#ifndef MACHINE_PROG
+#define MACHINE_PROG "machine"
+#endif
+
+#define CPUCOUNT(c) ((c)->ptr - (c)->buf)
+
+static NSMutableDictionary *ArchDict;
+static NSString *KeyExecPath = @"ExecutablePath";
+static NSString *KeyPlistVersion = @"PropertyListVersion";
+static NSString *KeyPrefOrder = @"PreferredOrder";
+static NSString *PlistExtension = @"plist";
+static NSString *SettingsDir = @"archSettings";
+
+static const char envname[] = "ARCHPREFERENCE";
+
+typedef struct {
+ cpu_type_t *buf;
+ cpu_type_t *ptr;
+ cpu_type_t *end;
+ int errs;
+} CPU;
+
+typedef struct {
+ char *str;
+ int i;
+} StrInt;
+
+static StrInt initArches[] = {
+ {"i386", CPU_TYPE_I386},
+ {"ppc", CPU_TYPE_POWERPC},
+ {"ppc64", CPU_TYPE_POWERPC64},
+ {"x86_64", CPU_TYPE_X86_64},
+ {NULL, 0}
+};
+
+/*
+ * arch - perform the original behavior of the arch and machine commands.
+ * The archcmd flag is non-zero for the arch command, zero for the machine
+ * command. This routine never returns.
+ */
+static void __dead2
+arch(int archcmd)
+{
+ const NXArchInfo *arch = NXGetLocalArchInfo();
+
+ if(!arch)
+ errx(-1, "Unknown architecture.");
+ if(archcmd) {
+ arch = NXGetArchInfoFromCpuType(arch->cputype, CPU_SUBTYPE_MULTIPLE);
+ if(!arch)
+ errx(-1, "Unknown architecture.");
+ }
+ printf("%s%s", arch->name, (isatty(STDIN_FILENO) ? "\n" : ""));
+ exit(0);
+}
+
+/*
+ * 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
+ * call posix_spawn. str is the name/path to pass to posix_spawn{,p}, and
+ * argv and environ are the argument and environment arrays to pass. This
+ * routine never returns.
+ */
+static void __dead2
+spawnIt(int count, cpu_type_t *prefs, int pflag, const char *str, char **argv, char **environ)
+{
+
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int ret;
+ size_t copied;
+
+ if((ret = posix_spawnattr_init(&attr)) != 0)
+ errc(1, ret, "posix_spawnattr_init");
+ /* do the equivalent of exec, rather than creating a separate process */
+ if((ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC)) != 0)
+ errc(1, ret, "posix_spawnattr_setflags");
+ if((ret = posix_spawnattr_setbinpref_np(&attr, count, prefs, &copied)) != 0)
+ errc(1, ret, "posix_spawnattr_setbinpref_np");
+ if(copied != count)
+ errx(1, "posix_spawnattr_setbinpref_np only copied %d of %d", (int)copied, count);
+ if(pflag)
+ ret = posix_spawnp(&pid, str, NULL, &attr, argv, environ);
+ else
+ ret = posix_spawn(&pid, str, NULL, &attr, argv, environ);
+ errc(1, ret, "posix_spawn%s: %s", (pflag ? "p" : ""), str);
+}
+
+/*
+ * initCPU - initialize a CPU structure, a dynamically expanding CPU types
+ * array.
+ */
+static void
+initCPU(CPU *cpu)
+{
+ cpu->buf = (cpu_type_t *)malloc(CPUDELTA * sizeof(cpu_type_t));
+ if(!cpu->buf)
+ err(1, "Failed to malloc CPU buffer");
+ cpu->ptr = cpu->buf;
+ cpu->end = cpu->buf + CPUDELTA;
+ cpu->errs = 0;
+}
+
+/*
+ * addCPU - add a new CPU type value to the CPU structure, expanding
+ * the array as necessary.
+ */
+static void
+addCPU(CPU *cpu, int n)
+{
+ if(cpu->ptr >= cpu->end) {
+ cpu_type_t *new = realloc(cpu->buf, (cpu->end - cpu->buf + CPUDELTA) * sizeof(cpu_type_t));
+ if(!new)
+ err(1, "Out of memory realloc-ing CPU structure");
+ ptrdiff_t diff = (void *)new - (void *)cpu->buf;
+ cpu->buf = new;
+ cpu->ptr = (cpu_type_t *)((void *)cpu->ptr + diff);
+ cpu->end = (cpu_type_t *)((void *)cpu->end + diff) + CPUDELTA;
+ }
+ *cpu->ptr++ = n;
+}
+
+/*
+ * addCPUbyname - add a new CPU type, given by name, to the CPU structure,
+ * expanding the array as necessary. The name is converted to a type value
+ * by the ArchDict dictionary.
+ */
+static void
+addCPUbyname(CPU *cpu, const char *name)
+{
+ NSNumber *n = (NSNumber *)[ArchDict objectForKey: [[NSString stringWithUTF8String: name] lowercaseString]];
+ if(n == nil) {
+ warnx("Unknown architecture: %s", name);
+ cpu->errs++;
+ return;
+ }
+ addCPU(cpu, [n intValue]);
+}
+
+/*
+ * useEnv - parse the environment variable for CPU preferences. Use name
+ * to look for program-specific preferences, and append any CPU types to cpu.
+ * Returns the number of CPU types. Returns any specified execute path in
+ * execpath.
+ *
+ * The environment variable ARCHPREFERENCE has the format:
+ * spec[;spec]...
+ * a semicolon separated list of specifiers. Each specifier has the format:
+ * [prog:[execpath:]]type[,type]...
+ * a comma separate list of CPU type names, optionally proceeded by a program
+ * name and an execpath. If program name exist, that types only apply to that
+ * program. If execpath is specified, it is returned. If no program name
+ * exists, then it applies to all programs. So ordering of the specifiers is
+ * important, as the default (no program name) specifier must be last.
+ */
+static int
+useEnv(CPU *cpu, const char *name, char **execpath)
+{
+ char *val = getenv(envname);
+ if(!val)
+ return 0;
+
+ /* cp will point to the basename of name */
+ const char *cp = strrchr(name, '/');
+ if(cp) {
+ cp++;
+ if(!*cp)
+ errx(1, "%s: no name after last slash", name);
+ } else
+ cp = name;
+ /* make a copy of the environment variable value, so we can modify it */
+ val = strdup(val);
+ if(!val)
+ err(1, "Can't copy environment %s", envname);
+ char *str = val;
+ char *blk;
+ /* for each specifier */
+ while((blk = strsep(&str, ";")) != NULL) {
+ if(*blk == 0)
+ continue; /* two adjacent semicolons */
+ /* now split on colons */
+ char *n = strsep(&blk, ":");
+ if(blk) {
+ char *p = strsep(&blk, ":");
+ if(!blk) { /* there is only one colon, so no execpath */
+ blk = p;
+ p = NULL;
+ } else if(!*p) /* two consecutive colons, so no execpath */
+ p = NULL;
+ if(!*blk)
+ continue; /* no cpu list, so skip */
+ /* if the name matches, or there is no name, process the cpus */
+ if(!*n || strcmp(n, cp) == 0) {
+ if(CPUCOUNT(cpu) <= 0) { /* only if we don't already have cpu types */
+ char *t;
+ while((t = strsep(&blk, ",")) != NULL)
+ addCPUbyname(cpu, t);
+ }
+ *execpath = (*n ? p : NULL); /* only use the exec path is name is set */
+ break;
+ }
+ } else { /* no colons at all, so process as default */
+ if(CPUCOUNT(cpu) <= 0) { /* only if we don't already have cpu types */
+ blk = n;
+ while((n = strsep(&blk, ",")) != NULL)
+ addCPUbyname(cpu, n);
+ }
+ *execpath = NULL;
+ break;
+ }
+ }
+ if(cpu->errs) /* errors during addCPUbyname are fatal */
+ exit(1);
+ return CPUCOUNT(cpu); /* return count of cpus */
+}
+
+/*
+ * spawnFromPreference - called when argv[0] is not "arch" or "machine", or
+ * argv[0] was arch, but no commandline architectures were specified.
+ * If the environment variable ARCHPREFERENCE is specified, and there is a
+ * match to argv[0], use the specified cpu preferences. If no exec path
+ * is specified in ARCHPREFERENCE, or no match is found in ARCHPREFERENCE,
+ * get any additional information from a .plist file with the name of argv[0].
+ * This routine never returns.
+ */
+static void __dead2
+spawnFromPreferences(CPU *cpu, int needexecpath, char **argv, char **environ)
+{
+ char *epath = NULL;
+ int count;
+ const char *prog = strrchr(*argv, '/');
+ if(prog)
+ prog++;
+ else
+ prog = *argv;
+ if(!*prog)
+ errx(1, "Not program name specified");
+
+ /* check the environment variable first */
+ if((count = useEnv(cpu, prog, &epath)) > 0) {
+ /* if we were called as arch, use posix_spawnp */
+ if(!needexecpath)
+ spawnIt(count, cpu->buf, 1, (epath ? epath : *argv), argv, environ);
+ /* otherwise, if we have the executable path, call posix_spawn */
+ if(epath)
+ spawnIt(count, cpu->buf, 0, epath, argv, environ);
+ }
+
+ /* pathArray is use to build the .plist file path for each domain */
+ NSMutableArray *pathArray = [NSMutableArray arrayWithCapacity: 3];
+ if(!pathArray)
+ errx(1, "Can't create NSMutableArray");
+ [pathArray addObject: @""]; // placeholder for domain directory
+ [pathArray addObject: SettingsDir];
+ [pathArray addObject: [[NSString stringWithUTF8String: prog] stringByAppendingPathExtension: PlistExtension]];
+
+ /* get the list of top level directories for all domains */
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, true);
+ int cnt = [paths count];
+ if(!cnt)
+ errx(1, "No domains");
+
+ /* create the .plist path, and try to read it */
+ int i;
+ NSString *path = NULL;
+ NSData *data = NULL;
+ for(i = 0; i < cnt; i++) {
+ [pathArray replaceObjectAtIndex: 0 withObject: [paths objectAtIndex: i]];
+ path = [NSString pathWithComponents: pathArray];
+ data = [NSData dataWithContentsOfFile: path];
+ if(data) /* found it */
+ break;
+ }
+ if(!data)
+ errx(1, "Can't find any plists for %s", prog);
+
+ /* try to convert the file into a NSDictionary */
+ NSString *error;
+ id plist = [NSPropertyListSerialization propertyListFromData: data mutabilityOption: NSPropertyListImmutable format: nil errorDescription: &error];
+ if(!plist)
+ errx(1, "%s: NSPropertyListSerialization error: %s", [path UTF8String], [error UTF8String]);
+ if(![plist isKindOfClass: [NSDictionary class]])
+ errx(1, "%s: plist not a dictionary", [path UTF8String]);
+
+ NSString *execpath;
+ int errs = 0; /* scan for all errors and fail later */
+ do { /* begin block */
+ /* check the plist version */
+ NSString *vers = [(NSDictionary *)plist objectForKey: KeyPlistVersion];
+ if(!vers) {
+ warnx("%s: No key %s", [path UTF8String], [KeyPlistVersion UTF8String]);
+ errs++;
+ } else if(![vers isKindOfClass: [NSString class]]) {
+ warnx("%s: %s is not a string", [path UTF8String], [KeyPlistVersion UTF8String]);
+ errs++;
+ } else if(![vers isEqualToString: @"1.0"]) {
+ warnx("%s: %s not 1.0", [path UTF8String], [KeyPlistVersion UTF8String]);
+ errs++;
+ }
+ /* get the execpath */
+ execpath = [(NSDictionary *)plist objectForKey: KeyExecPath];
+ if(!execpath) {
+ warnx("%s: No key %s", [path UTF8String], [KeyExecPath UTF8String]);
+ errs++;
+ } else if(![execpath isKindOfClass: [NSString class]]) {
+ warnx("%s: %s is not a string", [path UTF8String], [KeyExecPath UTF8String]);
+ errs++;
+ }
+ /* if we already got cpu preferences from ARCHPREFERENCE, we are done */
+ if(count > 0)
+ break;
+ /* otherwise, parse the cpu preferences from the plist */
+ id p = [(NSDictionary *)plist objectForKey: KeyPrefOrder];
+ if(!p) {
+ warnx("%s: No key %s", [path UTF8String], [KeyPrefOrder UTF8String]);
+ errs++;
+ } else if(![p isKindOfClass: [NSArray class]]) {
+ warnx("%s: %s is not an array", [path UTF8String], [KeyPrefOrder UTF8String]);
+ errs++;
+ } else if((count = [p count]) == 0) {
+ warnx("%s: no entries in %s", [path UTF8String], [KeyPrefOrder UTF8String]);
+ errs++;
+ } else {
+ /* finally but the cpu type array */
+ for(i = 0; i < count; i++) {
+ id a = [(NSArray *)p objectAtIndex: i];
+ NSNumber *n;
+ if(![a isKindOfClass: [NSString class]]) {
+ warnx("%s: entries %d of %s is not a string", [path UTF8String], i, [KeyPrefOrder UTF8String]);
+ errs++;
+ } else if((n = (NSNumber *)[ArchDict objectForKey: [(NSString *)a lowercaseString]]) == nil) {
+ warnx("%s: %s: unknown architecture %s", [path UTF8String], [KeyPrefOrder UTF8String], [(NSString *)a UTF8String]);
+ errs++;
+ } else {
+ addCPU(cpu, [n intValue]);
+ }
+ }
+ }
+ } while(0); /* end block */
+ if(errs) /* exit if there were any reported errors */
+ exit(1);
+
+ /* call posix_spawn */
+ spawnIt(count, cpu->buf, 0, [execpath fileSystemRepresentation], argv, environ);
+}
+
+static void __dead2
+usage(int ret)
+{
+ fprintf(stderr,
+ "Usage: %s\n"
+ " Display the machine's architecture type\n"
+ "Usage: %s [-h] [[-arch_name | -arch arch_name] ...] prog [arg ...]\n"
+ " Run prog with any arguments, using the given architecture\n"
+ " order. If no architectures are specified, use the\n"
+ " ARCHPREFERENCE environment variable, or a property list file.\n"
+ " -h will print usage message and exit.\n",
+ ARCH_PROG, ARCH_PROG);
+ exit(ret);
+}
+
+/*
+ * wrapped - check the path to see if it is a link to /usr/bin/arch.
+ */
+static int
+wrapped(const char *name)
+{
+ int lp, ln;
+ char *p;
+ char *bp = NULL;
+ char *cur, *path;
+ char buf[MAXPATHLEN], rpbuf[MAXPATHLEN];
+ struct stat sb;
+
+ ln = strlen(name);
+
+ do { /* begin block */
+ /* If it's an absolute or relative path name, it's easy. */
+ if(index(name, '/')) {
+ if(stat(name, &sb) == 0 && S_ISREG(sb.st_mode) && access(name, X_OK) == 0) {
+ bp = (char *)name;
+ break;
+ }
+ errx(1, "%s isn't executable", name);
+ }
+
+ /* search the PATH, looking for name */
+ if((path = getenv("PATH")) == NULL)
+ path = _PATH_DEFPATH;
+
+ cur = alloca(strlen(path) + 1);
+ if(cur == NULL)
+ err(1, "alloca");
+ strcpy(cur, path);
+ while((p = strsep(&cur, ":")) != NULL) {
+ /*
+ * It's a SHELL path -- double, leading and trailing colons
+ * mean the current directory.
+ */
+ if(*p == '\0') {
+ p = ".";
+ lp = 1;
+ } else
+ lp = strlen(p);
+
+ /*
+ * If the path is too long complain. This is a possible
+ * security issue; given a way to make the path too long
+ * the user may execute the wrong program.
+ */
+ if(lp + ln + 2 > sizeof(buf)) {
+ warn("%s: path too long", p);
+ continue;
+ }
+ bcopy(p, buf, lp);
+ buf[lp] = '/';
+ bcopy(name, buf + lp + 1, ln);
+ buf[lp + ln + 1] = '\0';
+ if(stat(buf, &sb) == 0 && S_ISREG(sb.st_mode) && access(buf, X_OK) == 0) {
+ bp = buf;
+ break;
+ }
+ }
+ if(p == NULL)
+ errx(1, "Can't find %s in PATH", name);
+ } while(0); /* end block */
+ if(realpath(bp, rpbuf) == NULL)
+ errx(1, "realpath failed on %s", bp);
+ return (strcmp(rpbuf, "/usr/bin/" ARCH_PROG) == 0);
+}
+
+/*
+ * spawnFromArgs - called when arch has arguments specified. The arch command
+ * line arguments are:
+ * % arch [[{-xxx | -arch xxx}]...] prog [arg]...
+ * where xxx is a cpu name, and the command to execute and its arguments follow.
+ * If no commandline cpu names are given, the environment variable
+ * ARCHPREFERENCE is used. This routine never returns.
+ */
+static void __dead2
+spawnFromArgs(CPU *cpu, char **argv, char **environ)
+{
+ char *ap;
+
+ /* process cpu options */
+ for(argv++; *argv && **argv == '-'; argv++) {
+ if(strcmp(*argv, "-arch") == 0) {
+ if(*++argv == NULL) {
+ warnx("-arch without architecture");
+ usage(1);
+ }
+ ap = *argv;
+ } else if(strcmp(*argv, "-h") == 0) {
+ usage(0);
+ } else
+ ap = *argv + 1;
+ addCPUbyname(cpu, ap);
+ }
+ if(cpu->errs)
+ exit(1);
+ if(!*argv || !**argv) {
+ warnx("No command to execute");
+ usage(1);
+ }
+ /* if the program is already a link to arch, then force execpath */
+ int needexecpath = wrapped(*argv);
+
+ /*
+ * If we don't have any architecutures, try ARCHPREFERENCE and plist
+ * files.
+ */
+ int count = CPUCOUNT(cpu);
+ if(count <= 0 || needexecpath)
+ spawnFromPreferences(cpu, needexecpath, argv, environ); /* doesn't return */
+
+ /*
+ * Call posix_spawnp on the program name.
+ */
+ spawnIt(count, cpu->buf, 1, *argv, argv, environ);
+}
+
+/*
+ * init - initializes the ArchDict dictionary from the values in initArches,
+ * and the CPU structure.
+ */
+static void
+init(CPU *cpu)
+{
+ ArchDict = [NSMutableDictionary dictionaryWithCapacity: 4];
+ if(!ArchDict)
+ errx(1, "Can't create NSMutableDictionary");
+ StrInt *sp;
+ for(sp = initArches; sp->str; sp++) {
+ NSString *s = [NSString stringWithUTF8String: sp->str];
+ if(!s)
+ errx(1, "Can't create NSString for %s", sp->str);
+ NSNumber *n = [NSNumber numberWithInt: sp->i];
+ if(!n)
+ errx(1, "Can't create NSNumber for %s", sp->str);
+ [ArchDict setObject: n forKey: s];
+ }
+ initCPU(cpu);
+}
+
+/* the main() routine */
+int
+main(int argc, char **argv, char **environ)
+{
+ const char *prog = getprogname();
+ int my_name_is_arch;
+ CPU cpu;
+
+ if(strcmp(prog, MACHINE_PROG) == 0) {
+ if(argc > 1)
+ errx(-1, "no arguments accepted");
+ arch(0); /* the "machine" command was called */
+ } else if((my_name_is_arch = (strcmp(prog, ARCH_PROG) == 0))) {
+ if(argc == 1)
+ arch(1); /* the "arch" command with no arguments was called */
+ }
+
+ /* set up Objective C autorelease pool */
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ init(&cpu); /* initialize */
+
+ if(my_name_is_arch)
+ spawnFromArgs(&cpu, argv, environ);
+ else
+ spawnFromPreferences(&cpu, 1, argv, environ);
+ /* should never get here */
+ [pool release];
+ errx(1, "returned from spawn");
+}
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Copyright (c) 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@
+#
+# arch_helper.pl is a perl script that automates the process of wrapping
+# a command (in the DSTROOT) to use the architecture selection feature of
+# the arch command. The first argument is the full path (relative to root)
+# of the command, and the second argument is the DSTROOT. arch_helper.pl
+# will move the command to a new directory in the DSTROOT, create a symbolic
+# link from to old command path to the arch command, and create a plist file
+# in /System/Library/archSettings to default to 32-bit over 64-bit
+# architectures.
+
+use strict;
+use File::Basename ();
+use File::Path ();
+use File::Spec;
+use IO::File;
+
+my $ArchSettings = '/System/Library/archSettings';
+my %Known = (
+ '/usr/bin' => '/usr/archexec',
+ '/usr/local/bin' => '/usr/local/archexec',
+);
+my $MyName = File::Basename::basename($0);
+
+sub usage {
+ print STDERR <<USAGE;
+Usage: $MyName prog_path dstroot
+ $MyName takes prog_path (full path relative to the dstroot)
+ and dstroot, and moves the program to the corresponding archexec
+ directory. It then creates a symbolic from prog_path to the arch
+ command. Finally, a plist file is created in
+ /System/Library/archSettings to default to using the 32-bit
+ architectures.
+USAGE
+ exit 1;
+}
+
+usage() unless scalar(@ARGV) == 2;
+my($vol, $dir, $file) = File::Spec->splitpath($ARGV[0]); # unix assumes $vol we be empty
+$dir = File::Spec->canonpath($dir);
+my $new = $Known{$dir};
+die "$MyName: Unsupported directory $dir\n" unless defined($new);
+my $dstroot = $ARGV[1];
+die "$MyName: $dstroot: Not a full path\n" unless File::Spec->file_name_is_absolute($dstroot);
+File::Path::mkpath(File::Spec->join($dstroot, $new), 1, 0755);
+File::Path::mkpath(File::Spec->join($dstroot, $ArchSettings), 1, 0755);
+my $execpath = File::Spec->canonpath(File::Spec->join($new, $file));
+my $do = File::Spec->join($dstroot, $dir, $file);
+my $dn = File::Spec->join($dstroot, $execpath);
+rename($do, $dn) or die "$MyName: Can't move $file to $dn: $!\n";
+print "renamed $do -> $dn\n";
+my $l = File::Spec->abs2rel('/usr/bin/arch', $dir);
+symlink($l, $do) or die "$MyName: Can't symlink $do -> $l: $!\n";
+print "symlink $do -> $l\n";
+my $plist = File::Spec->join($dstroot, $ArchSettings, $file . '.plist');
+my $p = IO::File->new($plist, 'w') or die "$MyName: $plist: $!\n";
+$p->print( <<PLIST );
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ExecutablePath</key>
+ <string>$execpath</string>
+ <key>PreferredOrder</key>
+ <array>
+ <string>i386</string>
+ <string>x86_64</string>
+ <string>ppc</string>
+ <string>ppc64</string>
+ </array>
+ <key>PropertyListVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
+PLIST
+$p->close();
+print "created $plist\n";
.Nm machine
command displays the machine type.
.Sh SEE ALSO
+.Xr arch 1 ,
.Xr make 1
.Sh HISTORY
The
CFILES = at.c panic.c parsetime.c perm.c
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
- at.1
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble at.man
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
NEXTSTEP_PB_CFLAGS += -D__FBSDID=__RCSID -DDAEMON_UID=1 -DDAEMON_GID=1 \
-DDEFAULT_AT_QUEUE=\'a\' -DDEFAULT_BATCH_QUEUE=\'b\' \
- -DPERM_PATH=\"/var/at/\" -I/System/Library/Frameworks/System.framework/PrivateHeaders
+ -DPERM_PATH=\"/usr/lib/cron/\" \
+ -I/System/Library/Frameworks/System.framework/PrivateHeaders
NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(NAME)/Build
+++ /dev/null
-# $Id: Makefile.dist,v 1.1 1999/05/02 04:21:18 wsanchez Exp $
-
-PROG= at
-SRCS= at.c panic.c parsetime.c
-LINKS= ${BINDIR}/at ${BINDIR}/atq \
- ${BINDIR}/at ${BINDIR}/atrm \
- ${BINDIR}/at ${BINDIR}/batch
-MLINKS= at.1 batch.1 \
- at.1 atq.1 \
- at.1 atrm.1
-
-BINOWN= root
-BINMODE= 4555
-
-.include <bsd.prog.mk>
$(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/batch
install -o daemon -d "$(DSTROOT)/private/var/at/spool"
touch "$(DSTROOT)/private/var/at/at.deny"
+ mkdir -p "$(DSTROOT)/usr/lib"
+ ln -sf ../../var/at "$(DSTROOT)/usr/lib/cron"
mkdir -p "$(DSTROOT)/usr/share/man/man1"
- install -c -m 644 at.1 "$(DSTROOT)/usr/share/man/man1/at.1"
+ install -c -m 644 at.man "$(DSTROOT)/usr/share/man/man1/at.1"
ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/atrm.1"
ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/atq.1"
ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/batch.1"
+++ /dev/null
-.\"
-.\" Copyright (c) 1993 Christopher G. Demetriou
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by Christopher G. Demetriou.
-.\" 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: at.1,v 1.5 2005/02/18 00:22:38 lindak Exp $
-.\"
-.Dd December 5, 1993
-.Dt "AT" 1
-.Os NetBSD 0.9a
-.Sh NAME
-.Nm at, batch, atq, atrm
-.Nd queue, examine, or delete jobs for later execution
-.\"
-.Sh SYOPSIS
-.Nm at
-.Op Fl q Ar queue
-.Op Fl f Ar file
-.Op Fl m
-.Ar time
-.Pp
-.Nm atq
-.Op Fl q Ar queue
-.Op Fl v
-.Pp
-.Nm atrm
-.Ar job
-.Op Ar job ...
-.Pp
-.Nm batch
-.Op Fl f Ar file
-.Op Fl m
-.Ar time
-.Sh NOTE
-.Nm at ,
-.Nm batch ,
-.Nm atq ,
-.Nm atrm
-are all disabled by default on Mac OS X.
-Each of these commands depend on the execution of
-.Xr atrun 8
-which has been disabled due to power management concerns.
-Those who would like to use these commands, must first (as root) re-enable
-.Nm atrun
-by running:
-.Bd -literal
-launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
-.Ed
-.Sh DESCRIPTION
-The
-.Nm at
-and
-.Nm batch
-utilities read commands from the standard input or a specified file
-which are to be executed at a later time, using
-.Xr sh 1 .
-.Pp
-The functions of the commands are as follows:
-.Bl -tag -width indent
-.It Nm at
-Executes commands at a specified time.
-.It Nm atq
-Lists the user's pending jobs, unless the user is
-the superuser. In that case, everybody's jobs are
-listed.
-.It Nm atrm
-Deletes jobs.
-.It Nm batch
-Executes commands when system load levels drop below a user-specifed threshold.
-The load threshold for batch jobs is specifed
-as an argument when executing
-.Xr atrun 8 .
-.El
-.Pp
-For both
-.Nm at
-and
-.Nm batch ,
-the working directory, environment (except for the variables
-.Nm TERM ,
-.Nm TERMCAP ,
-.Nm DISPLAY ,
-and
-.Nm _ )
-and the umask are retained from the time of invocation. The user
-will be mailed the standard output and standard error from
-his commands if any output is generated. If
-.Nm at
-is executed from a
-.Xr su 1
-shell, the owner of the login shell will receive the mail.
-.Sh OPTIONS
-.Bl -tag -width indent
-The available options are as follows:
-.It Fl q Ar queue
-Use the specified queue. A queue designation consists
-of a single letter; valid queue designation range from
-.Ar a
-to
-.Ar l .
-The
-.Ar a
-queue is the default, and
-.Ar b
-is the batch queue. Queues with higher letters run with
-increased niceness. If
-.Nm atq
-is given a specific queue, it will only show jobs pending
-in that queue.
-.It Fl m
-Send mail to the user when the job has completed, even if
-there was no output.
-.It Fl f Ar file
-Reads the job from
-.Ar file
-rather than the standard input.
-.It Fl v
-Shows completed but not yet deleted jobs in the queue.
-.El
-.Sh TIME SPECIFICATION
-.Nm At
-allows some moderately complex time specifications.
-It accepts times of the form
-.Ar HHMM
-or
-.Ar HH:MM
-to run a job at a specific time of day. If
-that time is already passed, the next day is assumed.
-You may also specify
-.Nm midnight ,
-.Nm noon ,
-or
-.Nm teatime
-(4PM) and you can give a time of day suffixed with
-.Nm AM
-or
-.Nm PM
-for running in the morning or the evening. You can
-also specify the date on which the job will be run
-by giving a date in the form
-.Ar month-name day
-with an optional
-.Ar year ,
-or giving a date of the form
-.Ar MMDDYY ,
-.Ar MM/DD/YY
-or
-.Ar DD.MM.YY .
-You can also give times like
-.Nm now +
-.Ar count time-units ,
-where the time units can be
-.Nm minutes, hours, days,
-or
-.Nm weeks
-You can suffix the time with
-.Nm today
-to run the job today, or
-.Nm tomorrow
-to run the job tomorrow.
-.Pp
-For example, to run a job at 4PM three days from now, you
-would specify a time of
-.Nm 4PM + 3 days .
-To run a job at 10:00AM on on July 31, you would specify
-a time of
-.Nm 10AM Jul 31 .
-Finally, to run a job at 1AM tomorrow, you would specify
-a time of
-.Nm 1AM tomorrow .
-.Sh FILES
-.Bl -tag -width /var/at/lockfile -compact
-.It Pa /var/at/jobs
-Directory containing job files
-.It Pa /var/at/spool
-Directory containing output spool files
-.It Pa /var/at/lockfile
-Job-creation lock file.
-.It Pa /var/run/utmp
-.El
-.Sh SEE ALSO
-.Xr launchctl 1 ,
-.Xr launchd 8 ,
-.Xr nice 1 ,
-.Xr sh 1 ,
-.Xr compat 5 ,
-.Xr atrun 8
-.Sh AUTHOR
-.Bl -tag
-Thomas Koenig, ig25@rz.uni-karlsruhe.de
-.El
-.Sh BUGS
-Traditional access control to
-.Nm at
-and
-.Nm batch
-via the files
-.Pa /var/at/at.allow
-and
-.Pa /var/at/at.deny
-is not implemented.
-.Pp
-If the file
-.Pa /var/run/utmp
-is not available or corrupted, or if the user is not
-logged in at the time
-.Nm at
-is invoked, the mail is sent to the userid found in the
-environment variable
-.Nm LOGNAME .
-If that is undefined or empty, the current userid is assumed.
int ch;
mode_t cmask;
struct flock lock;
+ char * oldpwd_str = NULL;
#ifdef __FreeBSD__
(void) setlocale(LC_TIME, "");
else
{
size_t i;
- for (i=0; i<sizeof(no_export)/sizeof(no_export[0]); i++)
- {
- export = export
- && (strncmp(*atenv, no_export[i],
+
+ if(strncmp(*atenv, "OLDPWD", (size_t) (eqp-*atenv)) == 0) {
+ oldpwd_str = *atenv;
+ }
+ if (!posixly_correct) {
+ /* Test 891 expects TERM, etc. to show up in "at" env
+ so exclude them only when not posixly_correct */
+ for (i=0; i<sizeof(no_export)/sizeof(no_export[0]); i++)
+ {
+ export = export
+ && (strncmp(*atenv, no_export[i],
(size_t) (eqp-*atenv)) != 0);
+ }
}
eqp++;
}
fprintf(fp, " || {\n\t echo 'Execution directory "
"inaccessible' >&2\n\t exit 1\n}\n");
+ /* Put OLDPWD back, since the cd has set it */
+ /* Although this is added to fix conformance test at.ex 891, it seems like */
+ /* the right thing to do always, so the code is not posix_pedantic only */
+ if (oldpwd_str) {
+ fprintf(fp, "%s; export OLDPWD\n", oldpwd_str);
+ } else {
+ fprintf(fp, "unset OLDPWD\n");
+ }
+
while((ch = getchar()) != EOF)
fputc(ch, fp);
timer = -1;
RELINQUISH_PRIVS
+ if (argv[0] == NULL)
+ usage();
/* Eat any leading paths
*/
if ((pgm = strrchr(argv[0], '/')) == NULL)
--- /dev/null
+.\" $FreeBSD: src/usr.bin/at/at.man,v 1.34 2003/03/26 02:38:18 keramida Exp $
+.Dd January 13, 2002
+.Dt "AT" 1
+.Os
+.Sh NAME
+.Nm at ,
+.Nm batch ,
+.Nm atq ,
+.Nm atrm
+.Nd queue, examine, or delete jobs for later execution
+.Sh SYNOPSIS
+.Nm at
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mldbv
+.Ar time
+.Nm at
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mldbv
+.Fl t
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Ar MM DD hh mm Op . Ar SS
+.Sm on
+.Nm at
+.Fl c Ar job Op Ar job ...
+.Nm at
+.Fl l Op Ar job ...
+.Nm at
+.Fl l
+.Fl q Ar queue
+.Nm at
+.Fl r Ar job Op Ar job ...
+.Pp
+.Nm atq
+.Op Fl q Ar queue
+.Op Fl v
+.Pp
+.Nm atrm
+.Ar job
+.Op Ar job ...
+.Pp
+.Nm batch
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mv
+.Op Ar time
+.Sh DESCRIPTION
+The
+.Nm at
+and
+.Nm batch
+utilities
+read commands from standard input or a specified file.
+The commands are executed at a later time, using
+.Xr sh 1 .
+.Bl -tag -width indent
+.It Nm at
+executes commands at a specified time;
+.It Nm atq
+lists the user's pending jobs, unless the user is the superuser; in that
+case, everybody's jobs are listed;
+.It Nm atrm
+deletes jobs;
+.It Nm batch
+executes commands when system load levels permit; in other words, when the load average
+drops below _LOADAVG_MX, or the value specified in the invocation of
+.Nm atrun .
+.El
+.Pp
+The
+.Nm at
+utility allows some moderately complex
+.Ar time
+specifications.
+It accepts times of the form
+.Ar HHMM
+or
+.Ar HH:MM
+to run a job at a specific time of day.
+(If that time is already past, the next day is assumed.)
+As an alternative, the following keywords may be specified:
+.Em midnight ,
+.Em noon ,
+or
+.Em teatime
+(4pm)
+and time-of-day may be suffixed with
+.Em AM
+or
+.Em PM
+for running in the morning or the evening.
+The day on which the job is to be run may also be specified
+by giving a date in the form
+.Ar \%month-name day
+with an optional
+.Ar year ,
+or giving a date of the forms
+.Ar DD.MM.YYYY ,
+.Ar DD.MM.YY ,
+.Ar MM/DD/YYYY ,
+.Ar MM/DD/YY ,
+.Ar MMDDYYYY , or
+.Ar MMDDYY .
+The specification of a date must follow the specification of
+the time of day.
+Time can also be specified as:
+.Op Em now
+.Em + Ar count \%time-units ,
+where the time-units can be
+.Em minutes ,
+.Em hours ,
+.Em days ,
+.Em weeks ,
+.Em months
+or
+.Em years
+and
+.Nm at
+may be told to run the job today by suffixing the time with
+.Em today
+and to run the job tomorrow by suffixing the time with
+.Em tomorrow .
+.Pp
+For example, to run a job at 4pm three days from now, use
+.Nm at Ar 4pm + 3 days ,
+to run a job at 10:00am on July 31, use
+.Nm at Ar 10am Jul 31
+and to run a job at 1am tomorrow, use
+.Nm at Ar 1am tomorrow .
+.Pp
+The
+.Nm at
+utility also supports the
+.Tn POSIX
+time format (see
+.Fl t
+option).
+.Pp
+For both
+.Nm at
+and
+.Nm batch ,
+commands are read from standard input or the file specified
+with the
+.Fl f
+option.
+The working directory, the environment (except for the variables
+.Ev TERM ,
+.Ev TERMCAP ,
+.Ev DISPLAY
+and
+.Em _ ) ,
+and the
+.Ar umask
+are retained from the time of invocation.
+An
+.Nm at
+or
+.Nm batch
+command invoked from a
+.Xr su 1
+shell will retain the current userid.
+The user will be mailed standard error and standard output from his
+commands, if any.
+Mail will be sent using the command
+.Xr sendmail 8 .
+If
+.Nm at
+is executed from a
+.Xr su 1
+shell, the owner of the login shell will receive the mail.
+.Pp
+The superuser may use these commands in any case.
+For other users, permission to use
+.Nm at
+is determined by the files
+.Pa _PERM_PATH/at.allow
+and
+.Pa _PERM_PATH/at.deny .
+.Pp
+If the file
+.Pa _PERM_PATH/at.allow
+exists, only usernames mentioned in it are allowed to use
+.Nm at .
+In these two files,
+a user is considered to be listed
+only if the user name has no blank or other characters
+before it on its line and a newline character immediately after the name,
+even at the end of the file.
+Other lines are ignored and may be used for comments.
+.Pp
+If
+.Pa _PERM_PATH/at.allow
+does not exist,
+.Pa _PERM_PATH/at.deny
+is checked, every username not mentioned in it is then allowed
+to use
+.Nm at .
+.Pp
+If neither exists, only the superuser is allowed use of
+.Nm at .
+This is the default configuration.
+.Sh IMPLEMENTATION NOTES
+Note that
+.Nm at
+is implemented through the
+.Xr cron 8
+daemon by calling
+.Xr atrun 8
+every five minutes.
+This implies that the granularity of
+.Nm at
+might not be optimal for every deployment.
+If a finer granularity is needed, the system crontab at
+.Pa /etc/crontab
+needs to be changed.
+.Sh OPTIONS
+.Bl -tag -width indent
+.\" ==========
+.It Fl b
+Is an alias for
+.Nm batch .
+.\" ==========
+.It Fl c
+Cat the jobs listed on the command line to standard output.
+.\" ==========
+.It Fl d
+Is an alias for
+.Nm atrm
+(this option is deprecated; use
+.Fl r
+instead).
+.\" ==========
+.It Fl f Ar file
+Read the job from
+.Ar file
+rather than standard input.
+.\" ==========
+.It Fl l
+With no arguments, list all jobs for the invoking user.
+If one or more
+job numbers are given, list only those jobs.
+.\" ==========
+.It Fl m
+Send mail to the user when the job has completed even if there was no
+output.
+.\" ==========
+.It Fl q Ar queue
+Use the specified queue.
+A queue designation consists of a single letter; valid queue designations
+range from
+.Ar a
+to
+.Ar z
+and
+.Ar A
+to
+.Ar Z .
+The
+.Ar _DEFAULT_AT_QUEUE
+queue (a) is the default for
+.Nm at
+and the
+.Ar _DEFAULT_BATCH_QUEUE
+queue (b) is the default for
+.Nm batch .
+Queues with higher letters run with increased niceness.
+If a job is submitted to a queue designated with an uppercase letter, it
+is treated as if it had been submitted to batch at that time.
+If
+.Nm atq
+is given a specific queue, it will only show jobs pending in that queue.
+.\" ==========
+.It Fl r
+Remove the specified jobs.
+.\" ==========
+.It Fl t
+Specify the job time using the \*[Px] time format.
+The argument should be in the form
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Ar MM DD hh mm Op . Ar SS
+.Sm on
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width indent -compact -offset indent
+.\" ==========
+.It Ar CC
+The first two digits of the year (the century).
+.\" ==========
+.It Ar YY
+The second two digits of the year.
+.\" ==========
+.It Ar MM
+The month of the year, from 1 to 12.
+.\" ==========
+.It Ar DD
+the day of the month, from 1 to 31.
+.\" ==========
+.It Ar hh
+The hour of the day, from 0 to 23.
+.\" ==========
+.It Ar mm
+The minute of the hour, from 0 to 59.
+.\" ==========
+.It Ar SS
+The second of the minute, from 0 to 61.
+.El
+.Pp
+If the
+.Ar CC
+and
+.Ar YY
+letter pairs are not specified, the values default to the current
+year.
+If the
+.Ar SS
+letter pair is not specified, the value defaults to 0.
+.\" ==========
+.It Fl v
+For
+.Nm atq ,
+shows completed but not yet deleted jobs in the queue; otherwise
+shows the time the job will be executed.
+.El
+.Sh FILES
+.Bl -tag -width _ATJOB_DIR/_LOCKFILE -compact
+.\" ==========
+.It Pa _ATJOB_DIR
+directory containing job files
+(/usr/lib/cron/jobs/)
+.\" ==========
+.It Pa _ATJOB_DIR/_LOCKFILE
+job-creation lock file
+(/usr/lib/cron/jobs/...)
+.\" ==========
+.It Pa _ATSPOOL_DIR
+directory containing output spool files
+(/usr/lib/cron/spool/)
+.\" ==========
+.It Pa _PERM_PATH/at.allow
+allow permission control
+(/usr/lib/cron/at.allow)
+.\" ==========
+.It Pa _PERM_PATH/at.deny
+deny permission control
+(/usr/lib/cron/at.deny)
+.It Pa /var/run/utmpx
+login records
+.El
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr sh 1 ,
+.Xr umask 2 ,
+.Xr compat 5 ,
+.Xr atrun 8 ,
+.Xr cron 8 ,
+.Xr sendmail 8
+.Sh BUGS
+If the file
+.Pa /var/run/utmpx
+is not available or corrupted,
+or if the user is not logged on at the time
+.Nm at
+is invoked, the mail is sent to the userid found
+in the environment variable
+.Ev LOGNAME .
+If that is undefined or empty, the current userid is assumed.
+.Pp
+The
+.Nm at
+and
+.Nm batch
+utilities
+as presently implemented are not suitable when users are competing for
+resources.
+If this is the case, another batch system such as
+.Em nqs
+may be more suitable.
+.Pp
+Specifying a date past 2038 may not work on some systems.
+.Sh AUTHORS
+At was mostly written by
+.An Thomas Koenig Aq ig25@rz.uni-karlsruhe.de .
+The time parsing routines are by
+.An David Parsons Aq orc@pell.chi.il.us ,
+with minor enhancements by
+.An Joe Halpin Aq joe.halpin@attbi.com .
* (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: pathnames.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ * $Id: pathnames.h,v 1.2 2005/07/30 01:30:01 lindak Exp $
*/
#ifndef _PATHNAMES_H_
#include <paths.h>
-#define _PATH_ATJOBS "/var/at/jobs/"
-#define _PATH_ATSPOOL "/var/at/spool/"
-#define _PATH_LOCKFILE "/var/at/.lockfile"
-#define _PATH_AT "/var/at/"
+#define _PATH_ATJOBS "/usr/lib/cron/jobs/"
+#define _PATH_ATSPOOL "/usr/lib/cron/spool/"
+/* Note: _PATH_LOCKFILE appears to be unused; /usr/lib/cron/jobs/.lockfile
+ is the file currently being used by at.*/
+#define _PATH_LOCKFILE "/usr/lib/cron/.lockfile"
+#define _PATH_AT "/usr/lib/cron/"
#endif /* !_PATHNAMES_H_ */
/* Local headers */
#include "at.h"
+#include "panic.h"
#include "perm.h"
#include "privs.h"
Job-creation lock file.
.El
.Sh SEE ALSO
-.Xr crond 8 ,
-.Xr at 1
+.Xr at 1 ,
+.Xr crond 8
.Sh AUTHOR
.Bl -tag
Thomas Koenig, ig25@rz.uni-karlsruhe.de
.Sh BUGS
The functionality of
.Nm atrun
-should arguaby be merged into
+should arguably be merged into
.Xr crond 8 .
.Sh CAVEATS
-Since the default configuration causes
+Because the default configuration causes
.Nm atrun
to be invoked every ten minutes,
commands queued by
#include <syslog.h>
#include <time.h>
#include <unistd.h>
-#include <utmp.h>
+#include <utmpx.h>
#if 1
#include <paths.h>
#else
#include <getopt.h>
#endif
+#if (MAXLOGNAME-1) > _UTX_USERSIZE
+#define LOGNAMESIZE _UTX_USERSIZE
+#else
#define LOGNAMESIZE (MAXLOGNAME-1)
+#endif
/* Local headers */
else if (pid != 0)
return;
+#ifdef __APPLE__
+ {
+ pid_t pg = setsid();
+ if (pg == -1) syslog(LOG_ERR,"setsid() failed: %m");
+ }
+#endif
+
/* Let's see who we mail to. Hopefully, we can read it from
* the command file; if not, send it to the owner, or, failing that,
* to root.
nice(tolower(queue) - 'a');
- if (initgroups(pentry->pw_name,pentry->pw_gid))
- perr("cannot delete saved userids");
-
if (setgid(gid) < 0 || setegid(pentry->pw_gid) < 0)
perr("cannot change group");
+ if (initgroups(pentry->pw_name,pentry->pw_gid))
+ perr("cannot delete saved userids");
+
if (setlogin(pentry->pw_name))
perr("cannot set login name");
{
PRIV_START
- if (initgroups(pentry->pw_name,pentry->pw_gid))
- perr("cannot delete saved userids");
-
if (setgid(gid) < 0 || setegid(pentry->pw_gid) < 0)
perr("cannot change group");
+ if (initgroups(pentry->pw_name,pentry->pw_gid))
+ perr("cannot delete saved userids");
+
if (setlogin(pentry->pw_name))
perr("cannot set login name");
run_file(batch_name, batch_uid, batch_gid);
closelog();
+#if __APPLE__
+ // allow enough time for child processes to call setsid(2)
+ sleep(1);
+#endif
exit(EXIT_SUCCESS);
}
<string>/usr/libexec/atrun</string>
</array>
<key>StartInterval</key>
- <integer>300</integer>
+ <integer>30</integer>
<key>Disabled</key>
<true/>
</dict>
Default audit policy file used to configure the auditing system.
.El
.Sh SEE ALSO
+.Xr audit_control 5 ,
.Xr auditd 8
-.Xr audit_control 5
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
#include <auditd.h>
#include <sys/mman.h>
#include <sys/queue.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>
KernelUser
auditd_control 456;
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
--- /dev/null
+#
+# 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 = bootlog
+
+PROJECTVERSION = 1.0
+PROJECT_TYPE = Tool
+
+CFILES = bootlog.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+ com.apple.bootlog.plist bootlog.8
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+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
--- /dev/null
+after_install:
+ mkdir -p $(DSTROOT)/usr/share/man/man8
+ install -c -m 444 bootlog.8 $(DSTROOT)/usr/share/man/man8
+ mkdir -p $(DSTROOT)/System/Library/LaunchDaemons
+ install -c -m 444 com.apple.bootlog.plist $(DSTROOT)/System/Library/LaunchDaemons
--- /dev/null
+{
+ DOCICONFILES = ();
+ FILESTABLE = {
+ CLASSES = ();
+ OTHER_LIBS = ();
+ OTHER_LINKED = (dummy.c);
+ OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble);
+ SUBPROJECTS = ();
+ };
+ LANGUAGE = English;
+ LOCALIZABLE_FILES = {};
+ NEXTSTEP_INSTALLDIR = /usr/bin;
+ NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
+ NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
+ PDO_UNIX_INSTALLDIR = /usr/bin;
+ PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac";
+ PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
+ PROJECTNAME = usr-share-locale;
+ PROJECTTYPE = Tool;
+ PROJECTVERSION = 2.8;
+ WINDOWS_INSTALLDIR = /usr/bin;
+ WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
+ WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
+}
--- /dev/null
+.\"
+.\" Copyright (c) 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@
+.\"
+.Dd Dec 15, 2006
+.Dt BOOTLOG 8
+.Sh NAME
+.Nm bootlog
+.Nd log a utmpx boot record
+.\"
+.Sh SYOPSIS
+.Nm bootlog
+.Sh DESCRIPTION
+The
+.Nm bootlog
+command simply creates a
+.Xr utmpx 5
+boot record at boot time.
+It is run by
+.Xr launchd 8 .
+.Sh SEE ALSO
+.Xr utmpx 5 ,
+.Xr launchd 8
--- /dev/null
+/*
+ * Copyright (c) 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 OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utmpx.h>
+
+#define _PATH_ASL_IN "/var/run/asl_input"
+
+#define REPEAT 100
+#define SLEEP 2
+
+static void
+asl_running(void)
+{
+ int sock, i;
+ struct sockaddr_un server;
+ socklen_t len;
+ int status;
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ exit(1);
+
+ memset(&server, 0, sizeof(struct sockaddr_un));
+ server.sun_family = AF_UNIX;
+
+ strcpy(server.sun_path, _PATH_ASL_IN);
+ server.sun_len = strlen(server.sun_path) + 1;
+ len = sizeof(server.sun_len) + sizeof(server.sun_family) + server.sun_len;
+
+ i = REPEAT;
+ for(;;) {
+ status = connect(sock, (const struct sockaddr *)&server, len);
+ if (status >= 0)
+ break;
+ if(--i <= 0)
+ exit(1);
+ sleep(SLEEP);
+ }
+
+ close(sock);
+}
+
+int
+main()
+{
+ int mib[2] = {CTL_KERN, KERN_BOOTTIME};
+ struct utmpx utx;
+ size_t len;
+
+ bzero(&utx, sizeof(utx));
+ utx.ut_type = BOOT_TIME;
+ utx.ut_pid = 1; // on behave of launchd
+
+ /* get the boot time */
+ len = sizeof(struct timeval);
+ if(sysctl(mib, 2, &utx.ut_tv, &len, NULL, 0) < 0)
+ gettimeofday(&utx.ut_tv, NULL); /* fallback to now */
+
+ /* wait for asl before logging */
+ asl_running();
+ pututxline(&utx);
+ return 0;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.bootlog</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/libexec/bootlog</string>
+ </array>
+ <key>RunAtLoad</key>
+ <true/>
+ <key>LaunchOnlyOnce</key>
+ <true/>
+</dict>
+</plist>
HFILES = stringops.h
-CFILES = ds_passwd.c nis_passwd.c file_passwd.c netinfo_passwd.c passwd.c\
+CFILES = ds_passwd.c nis_passwd.c file_passwd.c passwd.c\
stringops.c
OTHERSRCS = Makefile.preamble Makefile Makefile.postamble chkpasswd.8
C_FILES = ();
H_FILES = (stringops.h);
OTHER_LIBS = ();
- OTHER_LINKED = (nis_passwd.c, file_passwd.c, netinfo_passwd.c, passwd.c, stringops.c);
+ OTHER_LINKED = (nis_passwd.c, file_passwd.c, passwd.c, stringops.c);
OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble);
SUBPROJECTS = ();
};
.Nm chkpasswd
.Nd verifies user password against various systems
.Sh SYNOPSIS
-.Nm
+.Nm chkpasswd
.Op Fl i Ar infosystem
.Op Fl l Ar location
.Op Fl c
.Op Ar name
.Sh DESCRIPTION
-.Nm
-verifies a supplied username and password against NetInfo, file, NIS, or OpenDirectory backends.
+.Nm chkpasswd
+verifies a supplied username and password against file, NIS,
+or OpenDirectory infosystems.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.Fl i Ar infosystem
-Specify the system against which to check the password (default is OpenDirectory). Valid systems:
-.Pp
-.Bl -tag -width "opendirectory" -compact
-.It Cm netinfo
-NetInfo database
-.It Cm file
+.\" ==========
+.It Fl c
+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:
+.Bl -tag -width "opendirectory"
+.It Ar file
File-based passwords
-.It Cm nis
+.It Ar nis
NIS/YP authentication
-.It Cm opendirectory
-OpenDirectory (Directory Services) authentication
+.It Ar opendirectory
+OpenDirectory (Directory Services) authentication.
+If no
+.Fl l
+option is specified, the search node is used.
.El
-.Fl l Ar location
-Specify a location; varies based on info system type:
.Pp
-.Bl -tag -width "opendirectory" -compact
-.It Cm netinfo
-Domain name or server/tag.
-.It Cm file
-Filename (default: /etc/passwd).
-.It Cm nis
+.\" ==========
+.It Fl l Ar location
+Specify a location; varies based on infosystem type:
+.Bl -tag -width "for opendirectory"
+.It for file
+Filename (default: /etc/master.passwd).
+.It for nis
NIS domainname.
-.It Cm opendirectory
-Directory node name.
+.It for opendirectory
+A directory node name such as /Local/Default.
.El
-.Fl c
-The supplied password is compared verbatim without first being crypted.
-.Ar name
-Username
+.Pp
.El
+.Ar name
+username
.Sh SEE ALSO
-.Xr nicl 1 ,
-.Xr passwd 5 ,
-.Xr dscl 1
+.Xr dscl 1 ,
+.Xr passwd 5
#include <unistd.h>
#include <pwd.h>
#include <errno.h>
+#include <string.h>
#include "stringops.h"
#define TEMP_FILE "/tmp/.pwtmp"
extern void checkpasswd(char *, char *);
-static int do_compat = 1;
-
char *
getline(FILE *fp)
{
continue;
}
- fprintf(tfp, "%s:%s:%d:%d:%s:%d:%d:%s:%s:%s\n",
+ fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid,
newpw->pw_class, newpw->pw_change, newpw->pw_expire,
newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell);
fname = _PASSWD_FILE;
if (locn != NULL) fname = locn;
- fp = fopen(fname, "r");
- if (fp == NULL)
+ if (access(fname,R_OK) || (fp = fopen(fname, "r")) == NULL)
{
fprintf(stderr, "can't read file \"%s\": ", fname);
perror("");
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <string.h>
-#include <netinfo/ni.h>
-
-extern void checkpasswd(char *, char *);
-
-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;
- int i, len;
-
- 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;
-}
-
-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);
-}
*
* @APPLE_LICENSE_HEADER_END@
*/
-#define INFO_NETINFO 0
#define INFO_FILE 1
#define INFO_NIS 2
#define INFO_DIRECTORYSERVICES 3
#include <ctype.h>
#include <string.h>
#include <pwd.h>
-#include <netinfo/ni.h>
#include "stringops.h"
#ifdef __SLICK__
static int literal = 0;
extern int file_check_passwd(char *, char *);
-extern int netinfo_check_passwd(char *, char *);
extern int nis_check_passwd(char *, char *);
extern int ds_check_passwd(char *, char *);
{
fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n");
fprintf(stderr, "supported infosystems are:\n");
- fprintf(stderr, " netinfo\n");
fprintf(stderr, " file\n");
fprintf(stderr, " nis\n");
fprintf(stderr, " opendirectory\n");
- fprintf(stderr, "for netinfo, location may be a domain name or server/tag\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");
usage();
}
- if (!strcmp(argv[i], "NetInfo")) infosystem = INFO_NETINFO;
- else if (!strcmp(argv[i], "netinfo")) infosystem = INFO_NETINFO;
- else if (!strcmp(argv[i], "File")) infosystem = INFO_FILE;
+ 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;
switch (infosystem)
{
- case INFO_NETINFO:
- netinfo_check_passwd(user, locn);
- break;
case INFO_FILE:
file_check_passwd(user, locn);
break;
PROJECTVERSION = 2.8
PROJECT_TYPE = Tool
-HFILES = chpass.h pathnames.h pw_copy.h pw_scan.h pw_util.h directory_service.h
+HFILES = chpass.h open_directory.h pw_copy.h
CFILES = chpass.c edit.c field.c pw_copy.c table.c util.c \
- directory_service.c ds_pw_util.c
+ open_directory.c
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble chpass.1 \
- Makefile.dist
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble chpass.1
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
PROF_LIBS = $(LIBS)
-HEADER_PATHS = -I../pwd_mkdb.tproj -I../vipw.tproj
-FRAMEWORKS = -framework DirectoryService
+HEADER_PATHS = -I../pwd_mkdb.tproj -I../vipw.tproj
+FRAMEWORK_PATHS = -F/System/Library/PrivateFrameworks
+FRAMEWORKS = -framework OpenDirectory -framework CoreFoundation
PROJECT_HEADERS = pw_copy.h
+++ /dev/null
-# @(#)Makefile 8.2 (Berkeley) 4/2/94
-
-PROG= chpass
-SRCS= chpass.c edit.c field.c pw_copy.c pw_scan.c pw_util.c table.c util.c
-BINOWN= root
-BINMODE=4555
-.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../usr.sbin/vipw
-CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../usr.sbin/vipw
-LINKS= ${BINDIR}/chpass ${BINDIR}/chfn ${BINDIR}/chpass ${BINDIR}/chsh
-MLINKS= chpass.1 chfn.1 chpass.1 chsh.1
-
-afterinstall:
- chflags schg /usr/bin/chpass
-
-.include <bsd.prog.mk>
-VPATH += :../pwd_mkdb.tproj:../vipw.tproj
+#VPATH += :../pwd_mkdb.tproj:../vipw.tproj
INSTALL_AS_USER = root
INSTALL_AS_GROUP = wheel
-INSTALL_PERMISSIONS =4555
-#CHFLAGS = /usr/bin/chflags
+INSTALL_PERMISSIONS = 4555
+
after_install::
install -o $(INSTALL_AS_USER) -m 755 -d $(DSTROOT)/usr/share/man/man1
install -o $(INSTALL_AS_USER) -m 644 -c chpass.1 \
$(DSTROOT)/usr/share/man/man1
- $(LN) -s chpass.1 $(DSTROOT)/usr/share/man/man1/chfn.1
- $(LN) -s chpass.1 $(DSTROOT)/usr/share/man/man1/chsh.1
+ $(LN) -sf chpass.1 $(DSTROOT)/usr/share/man/man1/chfn.1
+ $(LN) -sf chpass.1 $(DSTROOT)/usr/share/man/man1/chsh.1
chown $(INSTALL_AS_USER):$(INSTALL_AS_GROUP) \
$(DSTROOT)/usr/share/man/man1/chfn.1
chown $(INSTALL_AS_USER):$(INSTALL_AS_GROUP) \
$(DSTROOT)/usr/share/man/man1/chsh.1
$(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/chfn
$(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/chsh
-# $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
-
CLEAN_ALL_SUBPROJECTS = YES
-OTHER_CFLAGS = -DDIRECTORY_SERVICE
-OTHER_OFILES = pw_scan.o
+OTHER_CFLAGS = -DOPEN_DIRECTORY -fconstant-cfstrings
+OTHER_LDFLAGS =
+OTHER_OFILES =
OTHER_GENERATED_OFILES = $(VERS_OFILE)
FILESTABLE = {
CLASSES = ();
C_FILES = ();
- HEADERSEARCH = (../pwd_mkdb.tproj, ../vipw.tproj);
- H_FILES = (chpass.h, pathnames.h, pw_copy.h);
+ HEADERSEARCH = ();
+ H_FILES = (chpass.h, pw_copy.h, open_directory.h);
OTHER_LIBS = ();
- OTHER_LINKED = (chpass.c, edit.c, field.c, pw_copy.c, table.c, util.c);
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, chpass.1, Makefile.dist);
+ OTHER_LINKED = (chpass.c, edit.c, field.c, pw_copy.c, table.c, util.c, open_directory.c);
+ OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, chpass.1);
PROJECT_HEADERS = (pw_copy.h);
SUBPROJECTS = ();
};
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with 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
+.\" 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.
.\"
.\" SUCH DAMAGE.
.\"
.\" @(#)chpass.1 8.2 (Berkeley) 12/30/93
-.\" $FreeBSD: src/usr.bin/chpass/chpass.1,v 1.34 2002/12/24 13:41:47 ru Exp $
+.\" $FreeBSD: src/usr.bin/chpass/chpass.1,v 1.38.2.1 2005/09/24 01:59:39 keramida Exp $
.\"
.Dd December 30, 1993
.Dt CHPASS 1
.Sh NAME
.Nm chpass ,
.Nm chfn ,
-.Nm chsh ,
+.Nm chsh
+.\".Nm ypchpass ,
+.\".Nm ypchfn ,
+.\".Nm ypchsh
.Nd add or change user database information
.Sh SYNOPSIS
.Nm
-.Op Fl a Ar list
-.Op Fl p Ar encpass
-.Op Fl e Ar expiretime
+.\".Op Fl a Ar list
+.\".Op Fl p Ar encpass
+.\".Op Fl e Ar expiretime
+.Op Fl l Ar location
+.Op Fl u Ar authname
.Op Fl s Ar newshell
.Op user
.Sh DESCRIPTION
or, by default, the current user.
.Pp
The
+.Nm
+utility
+.Em cannot
+change the user's password on Open Directory
+systems. Use the
+.Xr passwd 1
+utility instead.
+.Pp
+The
.Nm chfn ,
and
.Nm chsh
+.\".Nm ypchpass ,
+.\".Nm ypchfn
+.\"and
+.\".Nm ypchsh
utilities behave identically to
.Nm .
(There is only one program.)
.Pp
The options are as follows:
.Bl -tag -width indent
-.It Fl a
-The super-user is allowed to directly supply a user database
-entry, in the format specified by
-.Xr passwd 5 ,
-as an argument.
-This argument must be a colon
-.Pq Dq \&:
-separated list of all the
-user database fields, although they may be empty.
-[Note that this only changes the user database,
-.Li master.passwd Ns .]
-.It Fl p
-The super-user is allowed to directly supply an encrypted password field,
-in the format used by
-.Xr crypt 3 ,
-as an argument.
-[See the discussion in
-.Xr getpwent 3
-about types of passwords; this option may not be appropriate.]
-.It Fl e Ar expiretime
-Change the account expire time.
-This option is used to set the expire time
-from a script as if it was done in the interactive editor.
+.\".It Fl a
+.\"The super-user is allowed to directly supply a user database
+.\"entry, in the format specified by
+.\".Xr passwd 5 ,
+.\"as an argument.
+.\"This argument must be a colon
+.\".Pq Dq \&:
+.\"separated list of all the
+.\"user database fields, although they may be empty.
+.\".It Fl p
+.\"The super-user is allowed to directly supply an encrypted password field,
+.\"in the format used by
+.\".Xr crypt 3 ,
+.\"as an argument.
+.\".It Fl e Ar expiretime
+.\"Change the account expire time.
+.\"This option is used to set the expire time
+.\"from a script as if it were done in the interactive editor.
+.It Fl l Ar location
+If not specified,
+.Nm
+will perform a search for the user record on all available
+Open Directory nodes.
+When specified,
+.Nm
+will edit the user record on the directory node at the given
+.Ar location .
+.It Fl u Ar authname
+The user name to use when authenticating to the directory node containing the
+user.
.It Fl s Ar newshell
Attempt to change the user's shell to
.Ar newshell .
.Bl -tag -width "Other Information:" -compact -offset indent
.It Login:
user's login name
-.It Password:
-user's encrypted password
-[do
-.Em not
-use this to change a password; use
-.Xr passwd 1
-instead]
+.\".It Password:
+.\"user's encrypted password
.It Uid:
user's login
.It Gid:
user's login group
-.It Class:
-user's general classification
-.It Change:
-password change time
-.It Expire:
-account expiration time
+.It Generated uid:
+user's UUID
+.\".It Class:
+.\"user's general classification
+.\".It Change:
+.\"password change time
+.\".It Expire:
+.\"account expiration time
.It Full Name:
-user's real name (*)
-.\"user's real name
-.\".It Office Location:
-.\"user's office location (1)
-.\".It Office Phone:
-.\"user's office phone (1)
-.\".It Home Phone:
-.\"user's home phone (1)
+user's real name
+.It Office Location:
+user's office location
+.It Office Phone:
+user's office phone
+.It Home Phone:
+user's home phone
.\".It Other Information:
-.\"any locally defined parameters for user (1)
+.\"any locally defined parameters for user
.It Home Directory:
user's home directory
.It Shell:
user's login shell
.Pp
-.It NOTE(*) -
+.\".It NOTE(1) -
.\"In the actual master.passwd file, these fields are comma-delimited
.\"fields embedded in the FullName field.
-Historically, the so-call
-.Qq GECOS
-field in the user database entry contain the full name plus other information.
-Only the full name is currently supported.
.El
.Pp
The
.Ar login
field is the user name used to access the computer account.
-.Pp
-The
-.Ar password
-field contains the encrypted form of the user's password.
-Do
-.Em not
-use this to change a password; use
-.Xr passwd 1
-instead.
+.\".Pp
+.\"The
+.\".Ar password
+.\"field contains the encrypted form of the user's password.
.Pp
The
.Ar uid
across a group of systems) as they control file access.
.Pp
While it is possible to have multiple entries with identical login names
-and/or identical user id's, it is usually a mistake to do so. Routines
+and/or identical user id's, it is usually a mistake to do so.
+Routines
that manipulate these files will often return only one of the multiple
entries, and that one by random selection.
.Pp
.Xr group 5 ) .
.Pp
The
-.Ar class
-field references class descriptions in
-.Pa /etc/login.conf
-and is typically used to initialize the user's system resource limits
-when they login.
-.Pp
-The
-.Ar change
-field is the date by which the password must be changed.
-.Pp
-The
-.Ar expire
-field is the date on which the account expires.
-.Pp
-Both the
-.Ar change
-and
-.Ar expire
-fields should be entered in the form
-.Dq month day year
-where
-.Ar month
-is the month name (the first three characters are sufficient),
-.Ar day
-is the day of the month, and
-.Ar year
-is the year.
-.Pp
+.Ar generated uid
+field is the globally unique identifier (UUID) for the user.
+.\".Pp
+.\"The
+.\".Ar class
+.\"field references class descriptions in
+.\".Pa /etc/login.conf
+.\"and is typically used to initialize the user's system resource limits
+.\"when they login.
+.\".Pp
+.\"The
+.\".Ar change
+.\"field is the date by which the password must be changed.
+.\".Pp
+.\"The
+.\".Ar expire
+.\"field is the date on which the account expires.
+.\".Pp
+.\"Both the
+.\".Ar change
+.\"and
+.\".Ar expire
+.\"fields should be entered in the form
+.\".Dq month day year
+.\"where
+.\".Ar month
+.\"is the month name (the first three characters are sufficient),
+.\".Ar day
+.\"is the day of the month, and
+.\".Ar year
+.\"is the year.
+.\".Pp
.\"Five fields are available for storing the user's
.\".Ar full name , office location ,
.\".Ar work
Non-standard is defined as a shell not found in
.Pa /etc/shells .
.Pp
-Once the information has been verified,
-.Nm
-uses
-.Xr pwd_mkdb 8
-to update the user database.
-.Sh LOOKUPD AND DIRECTORY SERVICE AWARENESS
-User database entries (among other things) are under the control of
-.Xr lookupd 8
-and may be physically located in many different places, including local
-and remote
-.Xr netinfo 5
-databases, directory service agents such as LDAP servers and flat file databases
-such as
-.Li master.passwd .
+The
+.Ar picture
+field is the path to a picture to be displayed for the user.
+.Sh OPEN DIRECTORY
+User database entries are under the control of
+.Xr DirectoryService 8
+and may be physically located in many different places,
+including the local Directory Service node,
+and remote LDAP servers.
This version of
.Nm
-is currently limited to changing user database entries in the flat file
-and local netinfo databases.
+uses Open Directory to change user database information.
+It does not interact with the historic flat file
+database
+.Pa /etc/master.passwd
+.
.Sh ENVIRONMENT
The
.Xr vi 1
update the user database itself.
Only the user, or the super-user, may edit the information associated
with the user.
-.Pp
-See
-.Xr pwd_mkdb 8
-for an explanation of the impact of setting the
-.Ev PW_SCAN_BIG_IDS
-environment variable.
.Sh FILES
-.Bl -tag -width /etc/master.passwd -compact
-.It Pa /etc/master.passwd
-the user database
-.It Pa /etc/passwd
-a Version 7 format password file
-.It Pa /etc/chpass.XXXXXX
-temporary copy of the password file
+.Bl -tag -width /tmp/chpass.XXXXXX -compact
+.It Pa /tmp/chpass.XXXXXX
+temporary copy of the data to edit
.It Pa /etc/shells
the list of approved shells
.El
.Sh SEE ALSO
-.Xr finger 1 ,
+.\".Xr finger 1 ,
.Xr login 1 ,
.Xr passwd 1 ,
.Xr getusershell 3 ,
-.Xr login.conf 5 ,
-.Xr passwd 5 ,
-.Xr pwd_mkdb 8 ,
-.Xr vipw 8
+.Xr passwd 5
.Rs
.%A Robert Morris
-and
.%A Ken Thompson
.%T "UNIX Password security"
.Re
-.Sh BUGS
-User information should (and eventually will) be stored elsewhere.
.Sh HISTORY
The
.Nm
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* documentation and/or other materials provided with 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.
* SUCH DAMAGE.
*/
+#if 0
+#if 0
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1988, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
+#ifndef lint
+static char sccsid[] = "@(#)chpass.c 8.4 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/chpass/chpass.c,v 1.27.8.1 2006/09/29 06:13:20 marck Exp $");
+#endif
+
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <ctype.h>
#include <err.h>
#include <errno.h>
-#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef YP
+#include <ypclnt.h>
+#endif
+#ifndef OPEN_DIRECTORY
#include <pw_scan.h>
-#include <pw_util.h>
-#include "pw_copy.h"
+#include <libutil.h>
+#endif
#include "chpass.h"
-#include "pathnames.h"
-#ifdef DIRECTORY_SERVICE
-#include "directory_service.h"
-#define PWSETFIELD(field, in, out) if(in->field) out.field = strdup(in->field)
-#endif /* DIRECTORY_SERVICE */
+int master_mode;
-char *progname = "chpass";
-char *tempname;
-uid_t uid;
-#ifdef DIRECTORY_SERVICE
-int dswhere;
-#endif /* DIRECTORY_SERVICE */
+#ifdef OPEN_DIRECTORY
+#include "open_directory.h"
+char *progname = NULL;
+CFStringRef DSPath = NULL;
+#endif /* OPEN_DIRECTORY */
-void baduser __P((void));
-void usage __P((void));
+static void baduser(void);
+static void usage(void);
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char *argv[])
{
- enum { NEWSH, LOADENTRY, EDITENTRY } op;
- struct passwd *pw, lpw;
+ enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op;
+#ifndef OPEN_DIRECTORY
+ struct passwd lpw, *old_pw, *pw;
int ch, pfd, tfd;
- char *arg;
-#ifdef DIRECTORY_SERVICE
- struct passwd pworig;
- char *task_argv[3] = { NULL };
-#endif /* DIRECTORY_SERVICE */
+ const char *password;
+#else
+ struct passwd *old_pw, *pw;
+ int ch, tfd;
+ char tfn[MAXPATHLEN];
+#endif
+ char *arg = NULL;
+ uid_t uid;
+#ifdef YP
+ struct ypclnt *ypclnt;
+ const char *yp_domain = NULL, *yp_host = NULL;
+#endif
+#ifdef OPEN_DIRECTORY
+ CFStringRef username = NULL;
+ CFStringRef authname = NULL;
+ CFStringRef location = NULL;
+
+ progname = strrchr(argv[0], '/');
+ if (progname) progname++;
+ else progname = argv[0];
+#endif /* OPEN_DIRECTORY */
+ pw = old_pw = NULL;
op = EDITENTRY;
- while ((ch = getopt(argc, argv, "a:s:")) != EOF)
- switch(ch) {
+#ifdef OPEN_DIRECTORY
+ while ((ch = getopt(argc, argv, "a:s:l:u:")) != -1)
+#else /* OPEN_DIRECTORY */
+#ifdef YP
+ while ((ch = getopt(argc, argv, "a:p:s:e:d:h:loy")) != -1)
+#else
+ while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1)
+#endif
+#endif /* OPEN_DIRECTORY */
+ switch (ch) {
case 'a':
op = LOADENTRY;
arg = optarg;
op = NEWSH;
arg = optarg;
break;
+#ifndef OPEN_DIRECTORY
+ case 'p':
+ op = NEWPW;
+ arg = optarg;
+ break;
+ case 'e':
+ op = NEWEXP;
+ arg = optarg;
+ break;
+#ifdef YP
+ case 'd':
+ yp_domain = optarg;
+ break;
+ case 'h':
+ yp_host = optarg;
+ break;
+ case 'l':
+ case 'o':
+ case 'y':
+ /* compatibility */
+ break;
+#endif
+#else /* OPEN_DIRECTORY */
+ case 'l':
+ location = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+ break;
+ case 'u':
+ authname = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+ break;
+#endif
case '?':
default:
usage();
}
+
argc -= optind;
argv += optind;
+ if (argc > 1)
+ usage();
+
uid = getuid();
- if (op == EDITENTRY || op == NEWSH)
-#ifdef DIRECTORY_SERVICE
- {
-#endif /* DIRECTORY_SERVICE */
- switch(argc) {
- case 0:
- if (!(pw = getpwuid(uid)))
- errx(1, "unknown user: uid %u", uid);
- break;
- case 1:
- if (!(pw = getpwnam(*argv)))
+ if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) {
+ if (argc == 0) {
+ if ((pw = getpwuid(uid)) == NULL)
+ errx(1, "unknown user: uid %lu",
+ (unsigned long)uid);
+ } else {
+ if ((pw = getpwnam(*argv)) == NULL)
errx(1, "unknown user: %s", *argv);
-#ifndef DIRECTORY_SERVICE
- if (uid && uid != pw->pw_uid)
+#ifndef OPEN_DIRECTORY
+ if (uid != 0 && uid != pw->pw_uid)
baduser();
-#endif /* DIRECTORY_SERVICE */
- break;
- default:
- usage();
+#endif
}
- /* getpwnam(3) returns a pointer to local storage */
- lpw = *pw;
- PWSETFIELD(pw_name, pw, lpw);
- PWSETFIELD(pw_passwd, pw, lpw);
- PWSETFIELD(pw_class, pw, lpw);
- PWSETFIELD(pw_gecos, pw, lpw);
- PWSETFIELD(pw_dir, pw, lpw);
- PWSETFIELD(pw_shell, pw, lpw);
+#ifndef OPEN_DIRECTORY
+ /* Make a copy for later verification */
+ if ((pw = pw_dup(pw)) == NULL ||
+ (old_pw = pw_dup(pw)) == NULL)
+ err(1, "pw_dup");
+#endif
+ }
- pw = &lpw;
+#if OPEN_DIRECTORY
+ master_mode = (uid == 0);
-#ifdef DIRECTORY_SERVICE
- if ((dswhere = wherepwent(pw->pw_name)) < 0) {
- if(dswhere > E_NOTFOUND)
- errc(1, dswhere, "wherepwent");
- else
- errx(1, "wherepwent returned %d", dswhere);
- }
- switch(dswhere) {
- case WHERE_REMOTENI:
- errx(1,
-"Can't change info for user \"%s\", which resides in the\n"
-"netinfo domain \"%s\"",
- pw->pw_name, DSPath);
- case WHERE_DS:
- errx(1,
-"Can't change info for user \"%s\", which resides in the\n"
-"Directory Service path \"%s\"",
- pw->pw_name, DSPath);
- case WHERE_NIS:
- errx(1,
-"Can't change info for user \"%s\", which resides in NIS",
- pw->pw_name);
- case WHERE_LOCALNI:
- pworig = *pw;
- PWSETFIELD(pw_name, pw, pworig);
- PWSETFIELD(pw_passwd, pw, pworig);
- PWSETFIELD(pw_class, pw, pworig);
- PWSETFIELD(pw_gecos, pw, pworig);
- PWSETFIELD(pw_dir, pw, pworig);
- PWSETFIELD(pw_shell, pw, pworig);
- /* drop through */
- default:
- if (uid && uid != pw->pw_uid)
- baduser();
- }
+ /*
+ * Find the user record and copy its details.
+ */
+ username = CFStringCreateWithCString(NULL, pw->pw_name, kCFStringEncodingUTF8);
+
+ if (strcmp(progname, "chsh") == 0 || op == NEWSH) {
+ cfprintf(stderr, "Changing shell for %@.\n", username);
+ } else if (strcmp(progname, "chfn") == 0) {
+ cfprintf(stderr, "Changing finger information for %@.\n", username);
+ } else if (strcmp(progname, "chpass") == 0) {
+ cfprintf(stderr, "Changing account information for %@.\n", username);
}
-#endif /* DIRECTORY_SERVICE */
+
+ /*
+ * odGetUser updates DSPath global variable, performs authentication
+ * if necessary, and extracts the attributes.
+ */
+ CFDictionaryRef attrs_orig = NULL;
+ CFDictionaryRef attrs = NULL;
+ ODRecordRef rec = odGetUser(location, authname, username, &attrs_orig);
+
+ if (!rec || !attrs_orig) exit(1);
+#endif /* OPEN_DIRECTORY */
+
+#ifdef YP
+ if (pw != NULL && (pw->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
+ ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+ master_mode = (ypclnt != NULL &&
+ ypclnt_connect(ypclnt) != -1 &&
+ ypclnt_havepasswdd(ypclnt) == 1);
+ ypclnt_free(ypclnt);
+ } else
+#endif
+ master_mode = (uid == 0);
if (op == NEWSH) {
/* protect p_shell -- it thinks NULL is /bin/sh */
if (!arg[0])
usage();
- if (p_shell(arg, pw, (ENTRY *)NULL))
- pw_error((char *)NULL, 0, 1);
+ if (p_shell(arg, pw, (ENTRY *)NULL) == -1)
+ exit(1);
+#ifdef OPEN_DIRECTORY
+ else {
+ ENTRY* ep;
+
+ setrestricted(attrs_orig);
+
+ for (ep = list; ep->prompt; ep++) {
+ if (strncasecmp(ep->prompt, "shell", ep->len) == 0) {
+ if (!ep->restricted) {
+ CFStringRef shell = CFStringCreateWithCString(NULL, arg, kCFStringEncodingUTF8);
+ if (shell) {
+ attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (attrs) CFDictionarySetValue((CFMutableDictionaryRef)attrs, CFSTR(kDS1AttrUserShell), shell);
+ CFRelease(shell);
+ }
+ } else {
+ warnx("shell is restricted");
+ exit(1);
+ }
+ }
+ }
+ }
+#endif
}
+#ifndef OPEN_DIRECTORY
+ if (op == NEWEXP) {
+ if (uid) /* only root can change expire */
+ baduser();
+ if (p_expire(arg, pw, (ENTRY *)NULL) == -1)
+ exit(1);
+ }
+#endif
+
if (op == LOADENTRY) {
-#ifdef DIRECTORY_SERVICE
- warnx("-a is only supported for %s", MasterPasswd);
- dswhere = WHERE_FILES;
-#endif /* DIRECTORY_SERVICE */
if (uid)
baduser();
+#ifdef OPEN_DIRECTORY
+ warnx("-a is not supported for Open Directory.");
+ exit(1);
+#else
pw = &lpw;
- if (!pw_scan(arg, pw, NULL))
+ old_pw = NULL;
+ if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER))
exit(1);
+#endif /* OPEN_DIRECTORY */
}
- /*
- * The temporary file/file descriptor usage is a little tricky here.
- * 1: We start off with two fd's, one for the master password
- * file (used to lock everything), and one for a temporary file.
- * 2: Display() gets an fp for the temporary file, and copies the
- * user's information into it. It then gives the temporary file
- * to the user and closes the fp, closing the underlying fd.
- * 3: The user edits the temporary file some number of times.
- * 4: Verify() gets an fp for the temporary file, and verifies the
- * contents. It can't use an fp derived from the step #2 fd,
- * because the user's editor may have created a new instance of
- * the file. Once the file is verified, its contents are stored
- * in a password structure. The verify routine closes the fp,
- * closing the underlying fd.
- * 5: Delete the temporary file.
- * 6: Get a new temporary file/fd. Pw_copy() gets an fp for it
- * file and copies the master password file into it, replacing
- * the user record with a new one. We can't use the first
- * temporary file for this because it was owned by the user.
- * Pw_copy() closes its fp, flushing the data and closing the
- * underlying file descriptor. We can't close the master
- * password fp, or we'd lose the lock.
- * 7: Call pw_mkdb() (which renames the temporary file) and exit.
- * The exit closes the master passwd fp/fd.
- */
- pw_init();
-#ifdef DIRECTORY_SERVICE
- if (dswhere == WHERE_FILES)
-#endif /* DIRECTORY_SERVICE */
- pfd = pw_lock();
- tfd = pw_tmp();
+#ifndef OPEN_DIRECTORY
+ if (op == NEWPW) {
+ if (uid)
+ baduser();
- if (op == EDITENTRY) {
-#ifdef DIRECTORY_SERVICE
- setrestricted(dswhere, pw);
-#endif /* DIRECTORY_SERVICE */
- display(tfd, pw);
- edit(pw);
- (void)unlink(tempname);
-#ifdef DIRECTORY_SERVICE
- if (dswhere == WHERE_FILES)
-#endif /* DIRECTORY_SERVICE */
- tfd = pw_tmp();
+ if (strchr(arg, ':'))
+ errx(1, "invalid format for password");
+ pw->pw_passwd = arg;
}
-
-#ifdef DIRECTORY_SERVICE
- switch (dswhere) {
- case WHERE_LOCALNI:
- update_local_ni(&pworig, pw);
- break;
- case WHERE_FILES:
-#endif /* DIRECTORY_SERVICE */
- pw_copy(pfd, tfd, pw);
+#endif /* OPEN_DIRECTORY */
- if (pw_mkdb() != 0)
- pw_error((char *)NULL, 0, 1);
-#ifdef DIRECTORY_SERVICE
+ if (op == EDITENTRY) {
+#ifdef OPEN_DIRECTORY
+ setrestricted(attrs_orig);
+ snprintf(tfn, sizeof(tfn), "/tmp/%s.XXXXXX", progname);
+ if ((tfd = mkstemp(tfn)) == -1)
+ err(1, "%s", tfn);
+ attrs = (CFMutableDictionaryRef)edit(tfn, attrs_orig);
+ (void)unlink(tfn);
+#else
+ /*
+ * We don't really need pw_*() here, but pw_edit() (used
+ * by edit()) is just too useful...
+ */
+ if (pw_init(NULL, NULL))
+ err(1, "pw_init()");
+ if ((tfd = pw_tmp(-1)) == -1) {
+ pw_fini();
+ err(1, "pw_tmp()");
+ }
+ free(pw);
+ pw = edit(pw_tempname(), old_pw);
+ pw_fini();
+ if (pw == NULL)
+ err(1, "edit()");
+ /*
+ * pw_equal does not check for crypted passwords, so we
+ * should do it explicitly
+ */
+ if (pw_equal(old_pw, pw) &&
+ strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0)
+ errx(0, "user information unchanged");
+#endif /* OPEN_DIRECTORY */
}
- task_argv[0] = "/usr/sbin/lookupd";
- task_argv[1] = "-flushcache";
- task_argv[2] = NULL;
- LaunchTaskWithPipes( task_argv[0], task_argv, NULL, NULL );
-#endif /* DIRECTORY_SERVICE */
- exit(0);
-}
-#ifdef DIRECTORY_SERVICE
-// read from 0
-int LaunchTaskWithPipes(const char *path, char *const argv[], int *outPipe0, int *outPipe1)
-{
- int outputPipe[2];
- pid_t pid;
-
- if (outPipe0 != NULL)
- pipe(outputPipe);
-
- pid = fork();
- if (pid == -1)
- return -1;
-
- /* Handle the child */
- if (pid == 0)
- {
- int result = -1;
-
- if (outPipe0 != NULL)
- dup2(outputPipe[1], fileno(stdout));
-
- result = execv(path, argv);
- if (result == -1) {
- _exit(1);
- }
-
- /* This should never be reached */
- _exit(1);
+#ifndef OPEN_DIRECTORY
+ if (old_pw && !master_mode) {
+ password = getpass("Password: ");
+ if (strcmp(crypt(password, old_pw->pw_passwd),
+ old_pw->pw_passwd) != 0)
+ baduser();
+ } else {
+ password = "";
}
+#endif
+
+#ifdef OPEN_DIRECTORY
+ odUpdateUser(rec, attrs_orig, attrs);
- /* Now the parent */
- if ( outPipe0 != NULL )
- *outPipe0 = outputPipe[0];
- if ( outPipe1 != NULL )
- *outPipe1 = outputPipe[1];
+ if (rec) CFRelease(rec);
+ exit(0);
return 0;
+#else /* OPEN_DIRECTORY */
+ exit(0);
+ if (old_pw != NULL)
+ pw->pw_fields |= (old_pw->pw_fields & _PWF_SOURCE);
+ switch (pw->pw_fields & _PWF_SOURCE) {
+#ifdef YP
+ case _PWF_NIS:
+ ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+ if (ypclnt == NULL ||
+ ypclnt_connect(ypclnt) == -1 ||
+ ypclnt_passwd(ypclnt, pw, password) == -1) {
+ warnx("%s", ypclnt->error);
+ ypclnt_free(ypclnt);
+ exit(1);
+ }
+ ypclnt_free(ypclnt);
+ errx(0, "NIS user information updated");
+#endif /* YP */
+ case 0:
+ case _PWF_FILES:
+ if (pw_init(NULL, NULL))
+ err(1, "pw_init()");
+ if ((pfd = pw_lock()) == -1) {
+ pw_fini();
+ err(1, "pw_lock()");
+ }
+ if ((tfd = pw_tmp(-1)) == -1) {
+ pw_fini();
+ err(1, "pw_tmp()");
+ }
+ if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
+ pw_fini();
+ err(1, "pw_copy");
+ }
+ if (pw_mkdb(pw->pw_name) == -1) {
+ pw_fini();
+ err(1, "pw_mkdb()");
+ }
+ pw_fini();
+ errx(0, "user information updated");
+ break;
+ default:
+ errx(1, "unsupported passwd source");
+ }
+#endif /* OPEN_DIRECTORY */
}
-#endif /* DIRECTORY_SERVICE */
-void
-baduser()
+static void
+baduser(void)
{
errx(1, "%s", strerror(EACCES));
}
-void
-usage()
+static void
+usage(void)
{
- (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n");
+ (void)fprintf(stderr,
+ "usage: chpass%s %s [user]\n",
+#ifdef OPEN_DIRECTORY
+ "",
+ "[-l location] [-u authname] [-s shell]");
+#else /* OPEN_DIRECTORY */
+#ifdef YP
+ " [-d domain] [-h host]",
+#else
+ "",
+#endif
+ "[-a list] [-p encpass] [-s shell] [-e mmm dd yy]");
+#endif /* OPEN_DIRECTORY */
exit(1);
}
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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) 1988, 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 Technology, 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* documentation and/or other materials provided with 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.
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)chpass.h 8.4 (Berkeley) 4/2/94
+ * @(#)chpass.h 8.4 (Berkeley) 4/2/94
+ * $FreeBSD: src/usr.bin/chpass/chpass.h,v 1.7 2004/01/18 21:46:39 charnier Exp $
*/
-#ifdef DIRECTORY_SERVICE
-#include <stdio.h>
-#include <sys/types.h>
-
-struct display {
- struct passwd *pw;
- char *fullname;
- char *location;
- char *officephone;
- char *homephone;
-};
+#ifdef OPEN_DIRECTORY
+#include "open_directory.h"
-int LaunchTaskWithPipes(const char *path, char *const argv[], int *outPipe0, int *outPipe1);
-#endif /* DIRECTORY_SERVICE */
+extern char* progname;
+extern CFStringRef DSPath;
+#endif /* OPEN_DIRECTORY */
struct passwd;
typedef struct _entry {
- char *prompt;
-#ifdef DIRECTORY_SERVICE
+ const char *prompt;
+#ifdef OPEN_DIRECTORY
void (*display)();
-#endif /* DIRECTORY_SERVICE */
- int (*func)(), restricted, len;
+#endif
+ int (*func)(char *, struct passwd *, struct _entry *);
+ int restricted;
+ size_t len;
+#if OPEN_DIRECTORY
+ char *except;
+ CFStringRef attrName;
+#else /* OPEN_DIRECTORY */
char *except, *save;
+#endif /* OPEN_DIRECTORY */
} ENTRY;
/* Field numbers. */
-#ifdef DIRECTORY_SERVICE
-#define E_LOGIN 0
-#define E_PASSWD 1
-#define E_UID 2
-#define E_GID 3
-#define E_CHANGE 4
-#define E_EXPIRE 5
-#define E_CLASS 6
-#define E_HOME 7
-#define E_SHELL 8
-#define E_NAME 9
-#define E_LOCATE 10
-#define E_BPHONE 11
-#define E_HPHONE 12
-#else /* DIRECTORY_SERVICE */
#define E_BPHONE 8
#define E_HPHONE 9
#define E_LOCATE 10
#define E_NAME 7
-#define E_SHELL 12
-#endif /* DIRECTORY_SERVICE */
+#define E_OTHER 11
+#define E_SHELL 13
extern ENTRY list[];
-extern uid_t uid;
+extern int master_mode;
+
+#ifdef OPEN_DIRECTORY
+/* edit.c */
+void display_time(CFDictionaryRef, CFStringRef, const char*, FILE *);
+void display_string(CFDictionaryRef, CFStringRef, const char*, FILE *);
+CFDictionaryRef edit(const char *tfn, CFDictionaryRef pw);
+
+/* util.c */
+int cfprintf(FILE* file, const char* format, ...);
+int editfile(const char* tfn);
+#endif /* OPEN_DIRECTORY */
-int atot __P((char *, time_t *));
-#ifdef DIRECTORY_SERVICE
-void d_change __P((struct display *, FILE *));
-void d_class __P((struct display *, FILE *));
-void d_expire __P((struct display *, FILE *));
-void d_fullname __P((struct display *, FILE *));
-void d_gid __P((struct display *, FILE *));
-void d_hdir __P((struct display *, FILE *));
-void d_homephone __P((struct display *, FILE *));
-void d_login __P((struct display *, FILE *));
-void d_location __P((struct display *, FILE *));
-void d_officephone __P((struct display *, FILE *));
-void d_passwd __P((struct display *, FILE *));
-void d_shell __P((struct display *, FILE *));
-void d_uid __P((struct display *, FILE *));
-#endif /* DIRECTORY_SERVICE */
-void display __P((int, struct passwd *));
-void edit __P((struct passwd *));
-char *ok_shell __P((char *));
-int p_change __P((char *, struct passwd *, ENTRY *));
-int p_class __P((char *, struct passwd *, ENTRY *));
-int p_expire __P((char *, struct passwd *, ENTRY *));
-int p_gecos __P((char *, struct passwd *, ENTRY *));
-int p_gid __P((char *, struct passwd *, ENTRY *));
-int p_hdir __P((char *, struct passwd *, ENTRY *));
-int p_login __P((char *, struct passwd *, ENTRY *));
-int p_login __P((char *, struct passwd *, ENTRY *));
-int p_passwd __P((char *, struct passwd *, ENTRY *));
-int p_shell __P((char *, struct passwd *, ENTRY *));
-int p_uid __P((char *, struct passwd *, ENTRY *));
-char *ttoa __P((time_t));
-int verify __P((struct passwd *));
+int atot(char *, time_t *);
+#ifndef OPEN_DIRECTORY
+struct passwd *edit(const char *, struct passwd *);
+#endif /* OPEN_DIRECTORY */
+int ok_shell(char *);
+char *dup_shell(char *);
+int p_change(char *, struct passwd *, ENTRY *);
+int p_class(char *, struct passwd *, ENTRY *);
+int p_expire(char *, struct passwd *, ENTRY *);
+int p_gecos(char *, struct passwd *, ENTRY *);
+int p_gid(char *, struct passwd *, ENTRY *);
+int p_hdir(char *, struct passwd *, ENTRY *);
+int p_login(char *, struct passwd *, ENTRY *);
+int p_passwd(char *, struct passwd *, ENTRY *);
+int p_shell(char *, struct passwd *, ENTRY *);
+int p_uid(char *, struct passwd *, ENTRY *);
+#ifdef OPEN_DIRECTORY
+int p_uuid(char *, struct passwd *, ENTRY *);
+#endif /* OPEN_DIRECTORY */
+char *ttoa(time_t);
+++ /dev/null
-#ifdef DIRECTORY_SERVICE
-
-#include "directory_service.h"
-#include "chpass.h"
-#include <err.h>
-#include <sys/time.h>
-
-#include <sys/errno.h>
-extern int errno;
-
-#define CONFIGNAMELEN 14
-#define GLOBALCONFIGLEN 20
-#define LOOKUPORDERLEN 13
-#define LINESIZE 128
-#define NETINFOROOTLEN 13
-#define NLIST 13
-#define REMOTEINFOLEN 9
-#define USERCONFIGLEN 18
-
-/*---------------------------------------------------------------------------
- * Global variables
- *---------------------------------------------------------------------------*/
-char *DSPath = NULL;
-const char MasterPasswd[] = "/etc/master.passwd";
-
-/*---------------------------------------------------------------------------
- * Local variables
- *---------------------------------------------------------------------------*/
-static char Agent[] = "Agent";
-static char ConfigName[] = "_config_name: ";
-static char DSFiles[] = "/BSD/local";
-static char FFPatFmt[] = "^%s:";
-static char GlobalConfig[] = "Global Configuration";
-static char LocalNI[] = "/NetInfo/DefaultLocalNode";
-static char LookupOrder[] = "LookupOrder: ";
-static char LookupOrderSep[] = " ";
-static char NetinfoRoot[] = "/NetInfo/root";
-static char NiclPathFmt[] = "/users/%s";
-static char NISPatFmt[] = "/usr/bin/ypcat passwd.byname | /usr/bin/grep -q '^%s:'";
-static char RemoteNI[] = "/NetInfo/";
-static char UserConfig[] = "User Configuration";
-static unsigned char RestrictedFFRoot[] = {
- 0, /*E_LOGIN */
- 0, /*E_PASSWD */
- 0, /*E_UID */
- 0, /*E_GID */
- 0, /*E_CHANGE */
- 0, /*E_EXPIRE */
- 0, /*E_CLASS */
- 0, /*E_HOME */
- 0, /*E_SHELL */
- 0, /*E_NAME */
- 1, /*E_LOCATE */
- 1, /*E_BPHONE */
- 1, /*E_HPHONE */
-};
-static unsigned char RestrictedFFUser[] = {
- 1, /*E_LOGIN */
- 1, /*E_PASSWD */
- 1, /*E_UID */
- 1, /*E_GID */
- 1, /*E_CHANGE */
- 1, /*E_EXPIRE */
- 1, /*E_CLASS */
- 1, /*E_HOME */
- 0, /*E_SHELL */
- 0, /*E_NAME */
- 1, /*E_LOCATE */
- 1, /*E_BPHONE */
- 1, /*E_HPHONE */
-};
-static unsigned char RestrictedLocalNIRoot[] = {
- 0, /*E_LOGIN */
- 1, /*E_PASSWD */
- 0, /*E_UID */
- 0, /*E_GID */
- 0, /*E_CHANGE */
- 0, /*E_EXPIRE */
- 0, /*E_CLASS */
- 0, /*E_HOME */
- 0, /*E_SHELL */
- 0, /*E_NAME */
- 1, /*E_LOCATE */
- 1, /*E_BPHONE */
- 1, /*E_HPHONE */
-};
-static unsigned char RestrictedLocalNIUser[] = {
- 1, /*E_LOGIN */
- 1, /*E_PASSWD */
- 1, /*E_UID */
- 1, /*E_GID */
- 1, /*E_CHANGE */
- 1, /*E_EXPIRE */
- 1, /*E_CLASS */
- 1, /*E_HOME */
- 0, /*E_SHELL */
- 0, /*E_NAME */
- 1, /*E_LOCATE */
- 1, /*E_BPHONE */
- 1, /*E_HPHONE */
-};
-
-#define NWHERE 4
-
-typedef int (*wherefunc)(const char *);
-
-static int compar(const void *, const void *);
-static int runnicl(char *name, char *key, char *val);
-static int whereCache(const char *);
-static int whereDS(const char *);
-static int whereFF(const char *);
-static int whereNI(const char *);
-static int whereNIL(const char *);
-static int whereNIS(const char *);
-
-/*---------------------------------------------------------------------------
- * WhereList determines what functions to call when the LookupOrder is followed
- *---------------------------------------------------------------------------*/
-struct where {
- char *agent;
- int len;
- wherefunc func;
-} WhereList[] = {
- {"Cache", 5, whereCache},
- {"DS", 2, whereDS},
- {"FF", 2, whereFF},
- {"NI", 2, whereNI},
- {"NIL", 3, whereNIL},
- {"NIS", 3, whereNIS},
-};
-
-#define PATINDEX 2
-static char *Grep[] = {
- "/usr/bin/grep",
- "-q",
- NULL, /* pattern goes here */
- (char *)MasterPasswd,
- NULL
-};
-
-#define NICLPATHINDEX 3
-#define NICLKEYINDEX 4
-#define NICLVALUEINDEX 5
-static char *Nicl[] = {
- "/usr/bin/nicl",
- ".",
- "-create",
- NULL, /* path goes here */
- NULL, /* key goes here */
- NULL, /* value goes here */
- NULL
-};
-
-#define YPCATINDEX 2
-static char *Ypcat[] = {
- "/bin/sh",
- "-c",
- NULL, /* ypcat cmd goes here */
- NULL
-};
-
-/*---------------------------------------------------------------------------
- * compar - called by bsearch() to search WhereList for an agent
- *---------------------------------------------------------------------------*/
-#define A ((const struct where *)a)
-#define KEY ((const char *)key)
-static int
-compar(const void *key, const void *a)
-{
- int result = strncmp(KEY, A->agent, A->len);
- if(result)
- return result;
- if(KEY[A->len] == 0)
- return 0;
- return strcmp(KEY + A->len, Agent);
-}
-#undef KEY
-#undef A
-
-/*---------------------------------------------------------------------------
- * runnicl - run the nicl command to update local netinfo fields
- *---------------------------------------------------------------------------*/
-static int
-runnicl(char *name, char *key, char *val)
-{
- char path[128];
- pid_t pid;
- int estat;
- int status;
-
- IF((pid = fork()) >= 0) {
- if(pid == 0) {
- sprintf(path, NiclPathFmt, name);
- Nicl[NICLPATHINDEX] = path;
- Nicl[NICLKEYINDEX] = key;
- Nicl[NICLVALUEINDEX] = val;
- /*---------------------------------------------------------------
- * Become fully root to call nicl
- *---------------------------------------------------------------*/
- setuid(geteuid());
- execv(Nicl[0], Nicl);
- _exit(1);
- }
- if(waitpid(pid, &estat, 0) < 0) {
- status = errno;
- break;
- }
- if(!WIFEXITED(estat)) {
- status = E_NICLFAILED;
- break;
- }
- status = (WEXITSTATUS(estat) == 0 ? 0 : E_NICLFAILED);
- } CLEANUP {
- } ELSE {
- status = errno;
- } ENDIF
- return status;
-}
-/*---------------------------------------------------------------------------
- * PUBLIC setrestricted - sets the restricted flag
- *---------------------------------------------------------------------------*/
-void
-setrestricted(int where, struct passwd *pw)
-{
- unsigned char *restricted;
- int i;
- ENTRY *ep;
-
- switch(where)
- {
- case WHERE_FILES:
- restricted = uid ? RestrictedFFUser : RestrictedFFRoot;
- break;
- case WHERE_LOCALNI:
- restricted = uid ? RestrictedLocalNIUser : RestrictedLocalNIRoot;
- break;
- default:
- return;
- }
-
- for (ep = list, i = NLIST; i > 0; i--)
- (ep++)->restricted = *restricted++;
-
- if (uid && !ok_shell(pw->pw_shell))
- list[E_SHELL].restricted = 1;
-}
-
-/*---------------------------------------------------------------------------
- * PUBLIC update_local_ni - update local netinfo
- *---------------------------------------------------------------------------*/
-void
-update_local_ni(struct passwd *pworig, struct passwd *pw)
-{
- char buf[64];
- char *np, *op, *bp;
-
- if(pworig->pw_uid != pw->pw_uid) {
- sprintf(buf, "%d", pw->pw_uid);
- runnicl(pworig->pw_name, "uid", buf);
- }
- if(pworig->pw_gid != pw->pw_gid) {
- sprintf(buf, "%d", pw->pw_gid);
- runnicl(pworig->pw_name, "gid", buf);
- }
- if(pworig->pw_change != pw->pw_change) {
- sprintf(buf, "%lu", pw->pw_change);
- runnicl(pworig->pw_name, "change", buf);
- }
- if(pworig->pw_expire != pw->pw_expire) {
- sprintf(buf, "%lu", pw->pw_expire);
- runnicl(pworig->pw_name, "expire", buf);
- }
- if(strcmp(pworig->pw_dir, pw->pw_dir) != 0)
- runnicl(pworig->pw_name, "home", pw->pw_dir);
- if(strcmp(pworig->pw_shell, pw->pw_shell) != 0)
- runnicl(pworig->pw_name, "shell", pw->pw_shell);
- if(strcmp(pworig->pw_class, pw->pw_class) != 0)
- runnicl(pworig->pw_name, "class", pw->pw_class);
-
- bp = pworig->pw_gecos;
- op = strsep(&bp, ",");
- if(!op)
- op = "";
- bp = pw->pw_gecos;
- np = strsep(&bp, ",");
- if(!np)
- np = "";
- if(strcmp(op, np) != 0)
- runnicl(pworig->pw_name, "realname", np);
-
- if(strcmp(pworig->pw_name, pw->pw_name) != 0)
- runnicl(pworig->pw_name, "name", pw->pw_name);
-
- warnx("netinfo domain \"%s\" updated", DSPath);
-}
-
-/*---------------------------------------------------------------------------
- * whereCache - we skip the cache
- *---------------------------------------------------------------------------*/
-static int
-whereCache(const char *name)
-{
- return E_NOTFOUND;
-}
-
-/*---------------------------------------------------------------------------
- * whereDS - call DirectoryService. This does both netinfo and other directory
- * services, so we cache the value so we only process once.
- *---------------------------------------------------------------------------*/
-static int
-whereDS(const char *name)
-{
- tDirReference dsRef;
- static tDirStatus status;
- static int dsCached = 0;
-
- if(dsCached)
- return status;
- dsCached = 1;
- IF((status = dsOpenDirService(&dsRef)) == eDSNoErr) {
- tDataBuffer *dataBuff;
-
- IF((dataBuff = dsDataBufferAllocate(dsRef, 4096)) != NULL) {
- tContextData context = NULL;
- unsigned long nodeCount;
-
- /*---------------------------------------------------------------
- * Find and open the search node.
- *---------------------------------------------------------------*/
- IF((status = dsFindDirNodes(dsRef, dataBuff, NULL,
- eDSAuthenticationSearchNodeName, &nodeCount, &context))
- == eDSNoErr)
- {
- tDataListPtr nodeName;
- if(nodeCount < 1) {
- status = eDSNodeNotFound;
- break;
- }
- nodeName = NULL;
- IF((status = dsGetDirNodeName(dsRef, dataBuff, 1, &nodeName)) == eDSNoErr)
- {
- tDirNodeReference nodeRef;
-
- IF((status = dsOpenDirNode(dsRef, nodeName, &nodeRef)) == eDSNoErr) {
- tDataListPtr pRecType;
- tDataListPtr pAttrType;
- tDataListPtr pPattern;
- unsigned long recCount;
- tContextData context2 = NULL;
-
- /*---------------------------------------------------
- * Now search the search node for the given user name.
- *---------------------------------------------------*/
- pRecType = dsBuildListFromStrings(dsRef,
- kDSStdRecordTypeUsers, NULL);
- pAttrType = dsBuildListFromStrings(dsRef,
- kDSNAttrMetaNodeLocation, NULL);
- pPattern = dsBuildListFromStrings(dsRef, name, NULL);
- IF((status = dsGetRecordList(nodeRef, dataBuff,
- pPattern, eDSExact, pRecType, pAttrType, 0, &recCount,
- &context2)) == eDSNoErr) {
- tAttributeListRef attrListRef;
- tRecordEntry *pRecEntry;
-
- if(recCount < 1) {
- status = E_NOTFOUND;
- break;
- }
- /*-----------------------------------------------
- * Get the attributes for the first entry we find
- *-----------------------------------------------*/
- IF((status = dsGetRecordEntry(nodeRef,
- dataBuff, 1, &attrListRef, &pRecEntry)) ==
- eDSNoErr) {
- tAttributeValueListRef valueRef;
- tAttributeEntry *pAttrEntry;
-
- /*-------------------------------------------
- * Get the first (only) attribute
- *-------------------------------------------*/
- IF((status = dsGetAttributeEntry( nodeRef, dataBuff, attrListRef, 1, &valueRef,
- &pAttrEntry)) == eDSNoErr)
- {
- tAttributeValueEntry *pValueEntry;
-
- /*---------------------------------------
- * Put the attribute values into a data
- * list.
- *---------------------------------------*/
-
- status = dsGetAttributeValue(nodeRef, dataBuff, 1, valueRef, &pValueEntry);
- if ( status == eDSNoErr )
- {
- DSPath = (char *) malloc( pValueEntry->fAttributeValueData.fBufferLength + 1 );
- if ( DSPath != NULL )
- strlcpy( DSPath, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength + 1 );
-
- dsDeallocAttributeValueEntry(dsRef, pValueEntry);
- }
-
- if(status != eDSNoErr)
- break;
-
- if(strcmp(DSPath, LocalNI) == 0)
- {
- status = WHERE_LOCALNI;
- /*---------------------------
- * Translate to netinfo path
- *---------------------------*/
- free((void *)DSPath);
- DSPath = strdup(".");
- }
- else if(strcmp(DSPath, DSFiles) == 0)
- {
- status = WHERE_FILES;
- /*---------------------------
- * Translate to master.passwd
- * path
- *---------------------------*/
- free((void *)DSPath);
- DSPath = strdup(MasterPasswd);
- }
- else if(strncmp(DSPath, RemoteNI, REMOTEINFOLEN) == 0)
- {
- status = WHERE_REMOTENI;
- /*---------------------------
- * Translate to netinfo path
- *---------------------------*/
- if(strncmp(DSPath, NetinfoRoot,
- NETINFOROOTLEN) == 0) {
- if(DSPath[NETINFOROOTLEN]
- == 0) {
- free((void *)DSPath);
- DSPath = strdup("/");
- } else {
- char *tmp =
- strdup(DSPath +
- NETINFOROOTLEN);
- free((void *)DSPath);
- DSPath = tmp;
- }
- }
- }
- else
- {
- status = WHERE_DS;
- }
- } CLEANUP {
- dsCloseAttributeValueList(valueRef);
- dsDeallocAttributeEntry(dsRef, pAttrEntry);
- } ELSE {
- } ENDIF
- } CLEANUP {
- dsCloseAttributeList(attrListRef);
- dsDeallocRecordEntry(dsRef, pRecEntry);
- } ENDIF
- } CLEANUP {
- if(context2)
- dsReleaseContinueData(dsRef, context2);
- } ENDIF
- dsDataListDeallocate(dsRef, pRecType);
- free(pRecType);
- dsDataListDeallocate(dsRef, pAttrType);
- free(pAttrType);
- dsDataListDeallocate(dsRef, pPattern);
- free(pPattern);
- } CLEANUP {
- dsCloseDirNode(nodeRef);
- } ENDIF
- } CLEANUP {
- dsDataListDeallocate(dsRef, nodeName);
- } ENDIF
- } CLEANUP {
- if(context)
- dsReleaseContinueData(dsRef, context);
- } ENDIF
- } CLEANUP {
- dsDataBufferDeAllocate(dsRef, dataBuff);
- } ELSE {
- status = eMemoryAllocError;
- } ENDIF
- } CLEANUP {
- dsCloseDirService(dsRef);
- } ENDIF
- return status;
-}
-
-/*---------------------------------------------------------------------------
- * whereFF - check the flat file (/etc/master.passwd)
- *---------------------------------------------------------------------------*/
-static int
-whereFF(const char *name)
-{
- pid_t pid;
- int estat;
- int status;
-
- IF((pid = fork()) >= 0) {
- if(pid == 0) {
- char pat[64];
-
- sprintf(pat, FFPatFmt, name);
- Grep[PATINDEX] = pat;
- /*---------------------------------------------------------------
- * Become fully root to read /etc/master.passwd
- *---------------------------------------------------------------*/
- setuid(geteuid());
- execv(Grep[0], Grep);
- _exit(1);
- }
- if(waitpid(pid, &estat, 0) < 0) {
- status = errno;
- break;
- }
- if(!WIFEXITED(estat)) {
- status = E_CHILDFAILED;
- break;
- }
- status = (WEXITSTATUS(estat) == 0 ? WHERE_FILES : E_NOTFOUND);
- } CLEANUP {
- } ELSE {
- status = errno;
- } ENDIF
- return status;
-}
-
-/*---------------------------------------------------------------------------
- * whereNI - call whereDS to do the work, then the entry is found in directory
- * service (and not netinfo), mark as not found.
- *---------------------------------------------------------------------------*/
-static int
-whereNI(const char *name)
-{
- int status = whereDS(name);
-
- if(status == WHERE_DS)
- status = E_NOTFOUND;
- return status;
-}
-
-/*---------------------------------------------------------------------------
- * whereNIL - we skip the NILAgent
- *---------------------------------------------------------------------------*/
-static int
-whereNIL(const char *name)
-{
- return E_NOTFOUND;
-}
-
-/*---------------------------------------------------------------------------
- * whereNIS - check NIS passwd.byname
- *---------------------------------------------------------------------------*/
-static int
-whereNIS(const char *name)
-{
- pid_t pid;
- int estat;
- int status;
-
- IF((pid = fork()) >= 0) {
- if(pid == 0) {
- char cmd[256];
-
- sprintf(cmd, NISPatFmt, name);
- Ypcat[YPCATINDEX] = cmd;
- execv(Ypcat[0], Ypcat);
- _exit(1);
- }
- if(waitpid(pid, &estat, 0) < 0) {
- status = errno;
- break;
- }
- if(!WIFEXITED(estat)) {
- status = E_CHILDFAILED;
- break;
- }
- status = (WEXITSTATUS(estat) == 0 ? WHERE_NIS : E_NOTFOUND);
- } CLEANUP {
- } ELSE {
- status = errno;
- } ENDIF
- return status;
-}
-
-/*---------------------------------------------------------------------------
- * PUBLIC wherepwent - Given a const char *, determine lookupd's LookupOrder
- * and then search for the corresponding record for each agent.
- *---------------------------------------------------------------------------*/
-int
-wherepwent(const char *name)
-{
- char user[LINESIZE];
- char *cp, *str;
- struct where *w;
- FILE *fp = NULL;
- int status = 0;
- fd_set fdset;
- struct timeval selectTimeout = { 2, 0 };
- int result;
- char order[LINESIZE], line[LINESIZE];
- char *task_argv[3] = {NULL};
- int readPipe = -1;
- int writePipe = -1;
-
- /*-------------------------------------------------------------------
- * Save the first LookupOrder as the global setting. We make sure
- * that the first _config_name is Global Configuration.
- *-------------------------------------------------------------------*/
-
- do
- {
- task_argv[0] = "/usr/sbin/lookupd";
- task_argv[1] = "-configuration";
- task_argv[2] = NULL;
-
- if ( LaunchTaskWithPipes(task_argv[0], task_argv, &readPipe, &writePipe) != 0 )
- return E_NOTFOUND;
-
- // close this pipe now so the forked process quits on completion
- if ( writePipe != -1 )
- close( writePipe );
-
- // wait for data (and skip signals)
- FD_ZERO( &fdset );
- FD_SET( readPipe, &fdset );
- do {
- result = select( FD_SETSIZE, &fdset, NULL, NULL, &selectTimeout );
- }
- while ( result == -1 && errno == EINTR );
- if ( result == -1 || result == 0 ) {
- status = E_NOTFOUND;
- break;
- }
-
- // now that the descriptor is ready, parse the configuration
- fp = fdopen(readPipe, "r");
- if ( fp == NULL ) {
- status = E_NOTFOUND;
- break;
- }
- *user = 0;
- while(fgets(line, LINESIZE, fp))
- {
- if(strncasecmp(line, LookupOrder, LOOKUPORDERLEN) == 0) {
- if((cp = strchr(line, '\n')) != NULL)
- *cp = 0;
- strcpy(user, line + LOOKUPORDERLEN);
- continue;
- }
- if(strncasecmp(line, ConfigName, CONFIGNAMELEN) == 0) {
- if(strncasecmp(line + CONFIGNAMELEN, GlobalConfig, GLOBALCONFIGLEN) != 0) {
- status = E_NOGLOBALCONFIG;
- }
- break;
- }
- }
- if(status < 0)
- break;
- /*-------------------------------------------------------------------
- * Save the each LookupOrder and look for _config_name of User
- * Configuration. If found, replace the global order with this one.
- *-------------------------------------------------------------------*/
- *order = 0;
- while(fgets(line, LINESIZE, fp))
- {
- if(strncasecmp(line, LookupOrder, LOOKUPORDERLEN) == 0) {
- if((cp = strchr(line, '\n')) != NULL)
- *cp = 0;
- strcpy(order, line + LOOKUPORDERLEN);
- continue;
- }
- if(strncasecmp(line, ConfigName, CONFIGNAMELEN) == 0) {
- if(strncasecmp(line + CONFIGNAMELEN, UserConfig, USERCONFIGLEN) == 0) {
- if(*order)
- strcpy(user, order);
- break;
- }
- *order = 0;
- }
- }
- if(*user == 0) {
- status = E_NOLOOKUPORDER;
- break;
- }
- }
- while ( 0 );
-
- if ( fp != NULL )
- fclose( fp );
- else if ( readPipe != -1 )
- close( readPipe );
-
- if(status < 0)
- return status;
-
- /*-----------------------------------------------------------------------
- * Now for each agent, call the corresponding where function. If the
- * return value is no E_NOTFOUND, then we either have found it or have
- * detected an error.
- *-----------------------------------------------------------------------*/
- str = user;
- while((cp = strtok(str, LookupOrderSep)) != NULL) {
- if((w = bsearch(cp, WhereList, NWHERE, sizeof(struct where),
- compar)) != NULL) {
- if((status = w->func(name)) != E_NOTFOUND)
- return status;
- } else
- printf("%s not supported\n", cp);
- str = NULL;
- }
- return E_NOTFOUND;
-}
-#endif /* DIRECTORY_SERVICE */
+++ /dev/null
-#ifndef _DIRECTORY_SERVICE_H_
-#define _DIRECTORY_SERVICE_H_
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <errno.h>
-#include <DirectoryService/DirectoryService.h>
-
-/*---------------------------------------------------------------------------
- * Convenience macros: to be used to provide a cleanup section (eg, to
- * deallocate memory, etc). IF, CLEANUP and ENDIF must always be used, and
- * must be used with braces; ELSE is optional, but must also be used with
- * braces.
- *
- * IF(expression) {
- * ...
- * } CLEANUP {
- * ...
- * } ELSE {
- * ...
- * } ENDIF
- *
- * "break" may be used in the IF section to exit the block prematurely; the
- * CLEANUP section will still be performed. "break" in the CLEANUP and ELSE
- * sections apply to higher level blocks.
- *---------------------------------------------------------------------------*/
-#define IF(x) if(x) { do
-#define CLEANUP while(0);
-#define ELSE } else {
-#define ENDIF }
-
-/*---------------------------------------------------------------------------
- * Error codes (not including DirectoryService error codes and standard error
- * codes)
- *---------------------------------------------------------------------------*/
-#define E_NOTFOUND -1000
-#define E_NOGLOBALCONFIG -1001
-#define E_NOLOOKUPORDER -1002
-#define E_POPENFAILED -1003
-#define E_CHILDFAILED -1004
-#define E_DATALISTOUTOFMEM -1005
-#define E_PATHOUTOFMEM -1006
-#define E_NICLFAILED -1007
-
-/*---------------------------------------------------------------------------
- * Success return values from wherepwent()
- *---------------------------------------------------------------------------*/
-enum {
- WHERE_FILES = 0,
- WHERE_LOCALNI,
- WHERE_REMOTENI,
- WHERE_DS,
- WHERE_NIS,
-};
-
-/*---------------------------------------------------------------------------
- * Global variables
- *---------------------------------------------------------------------------*/
-extern char *DSPath;
-extern const char MasterPasswd[];
-
-/*---------------------------------------------------------------------------
- * Function prototypes
- *---------------------------------------------------------------------------*/
-extern void setrestricted(int where, struct passwd *pw);
-extern void update_local_ni(struct passwd *pworig, struct passwd *pw);
-extern int wherepwent(const char *name);
-
-#endif /* _DIRECTORY_SERVICE_H_ */
+++ /dev/null
-/*
- * 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, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)pw_util.c 8.4 (Berkeley) 4/28/95";
-#endif /* not lint */
-
-/*
- * This file is used by all the "password" programs; vipw(8), chpass(1),
- * and passwd(1).
- */
-
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "pw_util.h"
-#ifdef DIRECTORY_SERVICE
-#include "directory_service.h"
-#endif /* DIRECTORY_SERVICE */
-
-extern char *tempname;
-static pid_t editpid = -1;
-static int lockfd;
-
-void
-pw_cont(sig)
- int sig;
-{
-
- if (editpid != -1)
- kill(editpid, sig);
-}
-
-void
-pw_init()
-{
- struct rlimit rlim;
-
- /* Unlimited resource limits. */
- rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
- (void)setrlimit(RLIMIT_CPU, &rlim);
- (void)setrlimit(RLIMIT_FSIZE, &rlim);
- (void)setrlimit(RLIMIT_STACK, &rlim);
- (void)setrlimit(RLIMIT_DATA, &rlim);
- (void)setrlimit(RLIMIT_RSS, &rlim);
-
- /* Don't drop core (not really necessary, but GP's). */
- rlim.rlim_cur = rlim.rlim_max = 0;
- (void)setrlimit(RLIMIT_CORE, &rlim);
-
- /* Turn off signals. */
- (void)signal(SIGALRM, SIG_IGN);
- (void)signal(SIGHUP, SIG_IGN);
- (void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGPIPE, SIG_IGN);
- (void)signal(SIGQUIT, SIG_IGN);
- (void)signal(SIGTERM, SIG_IGN);
- (void)signal(SIGCONT, pw_cont);
-
- /* Create with exact permissions. */
- (void)umask(0);
-}
-
-int
-pw_lock()
-{
- /*
- * If the master password file doesn't exist, the system is hosed.
- * Might as well try to build one. Set the close-on-exec bit so
- * that users can't get at the encrypted passwords while editing.
- * Open should allow flock'ing the file; see 4.4BSD. XXX
- */
- lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
- if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
- err(1, "%s", _PATH_MASTERPASSWD);
- if (flock(lockfd, LOCK_EX|LOCK_NB))
- errx(1, "the password db file is busy");
- return (lockfd);
-}
-
-int
-pw_tmp()
-{
- static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
- int fd;
- char *p;
-
- if (p = strrchr(path, '/'))
- ++p;
- else
- p = path;
- strcpy(p, "pw.XXXXXX");
- if ((fd = mkstemp(path)) == -1)
- err(1, "%s", path);
- tempname = path;
- return (fd);
-}
-
-int
-pw_mkdb()
-{
- int pstat;
- pid_t pid;
-
- warnx("rebuilding the database...");
- (void)fflush(stderr);
- if (!(pid = vfork())) {
- execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
- pw_error(_PATH_PWD_MKDB, 1, 1);
- }
- pid = waitpid(pid, &pstat, 0);
- if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
- return (1);
- warnx("done");
- return (0);
-}
-
-void
-pw_edit(notsetuid)
- int notsetuid;
-{
- int pstat;
- char *p, *editor;
-
- if (!(editor = getenv("EDITOR")))
- editor = _PATH_VI;
- if (p = strrchr(editor, '/'))
- ++p;
- else
- p = editor;
-
- if (!(editpid = vfork())) {
- if (notsetuid) {
- (void)setgid(getgid());
- (void)setuid(getuid());
- }
- execlp(editor, p, tempname, NULL);
- _exit(1);
- }
- for (;;) {
- editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
- if (editpid == -1)
- pw_error(editor, 1, 1);
- else if (WIFSTOPPED(pstat))
- raise(WSTOPSIG(pstat));
- else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
- break;
- else
- pw_error(editor, 1, 1);
- }
- editpid = -1;
-}
-
-void
-pw_prompt()
-{
- int c;
-
- (void)printf("re-edit the password file? [y]: ");
- (void)fflush(stdout);
- c = getchar();
- if (c != EOF && c != '\n')
- while (getchar() != '\n');
- if (c == 'n')
- pw_error(NULL, 0, 0);
-}
-
-void
-pw_error(name, err, eval)
- char *name;
- int err, eval;
-{
-#ifdef DIRECTORY_SERVICE
- extern int dswhere;
-#endif /* DIRECTORY_SERVICE */
- if (err)
- warn("%s", name);
-
-#ifdef DIRECTORY_SERVICE
- switch(dswhere) {
- case WHERE_LOCALNI:
- warnx("netinfo domain \"%s\": unchanged", DSPath);
- break;
- case WHERE_FILES:
-#endif /* DIRECTORY_SERVICE */
- warnx("%s: unchanged", _PATH_MASTERPASSWD);
-#ifdef DIRECTORY_SERVICE
- }
-#endif /* DIRECTORY_SERVICE */
- (void)unlink(tempname);
- exit(eval);
-}
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*-
* Copyright (c) 1990, 1993, 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 Technology, 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* documentation and/or other materials provided with 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.
* SUCH DAMAGE.
*/
+#if 0
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)edit.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/chpass/edit.c,v 1.23 2003/04/09 18:18:42 des Exp $");
+#endif
+
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
+#ifndef OPEN_DIRECTORY
#include <pw_scan.h>
-#include <pw_util.h>
+#include <libutil.h>
+#endif
#include "chpass.h"
-#ifdef DIRECTORY_SERVICE
-#include "directory_service.h"
-
-extern int dswhere;
-#endif /* DIRECTORY_SERVICE */
-extern char *tempname;
+#ifdef OPEN_DIRECTORY
+static int display(const char *tfn, CFDictionaryRef attrs);
+static CFDictionaryRef verify(const char *tfn, CFDictionaryRef attrs);
+#else
+static int display(const char *tfn, struct passwd *pw);
+static struct passwd *verify(const char *tfn, struct passwd *pw);
+#endif
-void
-edit(pw)
- struct passwd *pw;
+#ifdef OPEN_DIRECTORY
+CFDictionaryRef
+edit(const char *tfn, CFDictionaryRef pw)
+#else
+struct passwd *
+edit(const char *tfn, struct passwd *pw)
+#endif
{
- struct stat begin, end;
+#ifdef OPEN_DIRECTORY
+ CFDictionaryRef npw;
+#else
+ struct passwd *npw;
+#endif
+ char *line;
+ size_t len;
+ if (display(tfn, pw) == -1)
+ return (NULL);
for (;;) {
- if (stat(tempname, &begin))
- pw_error(tempname, 1, 1);
- pw_edit(1);
- if (stat(tempname, &end))
- pw_error(tempname, 1, 1);
- if (begin.st_mtime == end.st_mtime) {
- warnx("no changes made");
- pw_error(NULL, 0, 0);
- }
- if (verify(pw))
+#ifdef OPEN_DIRECTORY
+ switch (editfile(tfn)) {
+#else
+ switch (pw_edit(1)) {
+#endif
+ case -1:
+ return (NULL);
+ case 0:
+#ifdef OPEN_DIRECTORY
+ return (NULL);
+#else
+ return (pw_dup(pw));
+#endif
+ default:
break;
- pw_prompt();
+ }
+ if ((npw = verify(tfn, pw)) != NULL)
+ return (npw);
+#ifndef OPEN_DIRECTORY
+ free(npw);
+#endif
+ printf("re-edit the password file? ");
+ fflush(stdout);
+ if ((line = fgetln(stdin, &len)) == NULL) {
+ warn("fgetln()");
+ return (NULL);
+ }
+ if (len > 0 && (*line == 'N' || *line == 'n'))
+ return (NULL);
}
}
* print out the file for the user to edit; strange side-effect:
* set conditional flag if the user gets to edit the shell.
*/
-void
-display(fd, pw)
- int fd;
- struct passwd *pw;
+#if OPEN_DIRECTORY
+static int
+display(const char *tfn, CFDictionaryRef attrs)
+#else
+static int
+display(const char *tfn, struct passwd *pw)
+#endif
{
FILE *fp;
- char *bp, *p, *ttoa();
-#ifdef DIRECTORY_SERVICE
- ENTRY *ep;
- struct display d;
- int ndisplayed = 0;
-#endif /* DIRECTORY_SERVICE */
-
- if (!(fp = fdopen(fd, "w")))
- pw_error(tempname, 1, 1);
+#ifndef OPEN_DIRECTORY
+ char *bp, *gecos, *p;
+#endif
- (void)fprintf(fp,
- "# Changing user database information for %s.\n"
- "#\n"
- "# (use \"passwd\" to change the password)\n"
- "##\n",
- pw->pw_name);
-
-#ifdef DIRECTORY_SERVICE
- switch (dswhere) {
- case WHERE_FILES:
- (void)fprintf(fp,
- "# Flat file: /etc/master.passwd\n"
- "##\n");
- break;
- case WHERE_LOCALNI:
- (void)fprintf(fp,
- "# Local NetInfo Database\n"
- "##\n");
- break;
+ if ((fp = fopen(tfn, "w")) == NULL) {
+ warn("%s", tfn);
+ return (-1);
}
- d.pw = pw;
- bp = pw->pw_gecos;
- p = strsep(&bp, ",");
- d.fullname = (p ? p : "");
- p = strsep(&bp, ",");
- d.location = (p ? p : "");
- p = strsep(&bp, ",");
- d.officephone = (p ? p : "");
- p = strsep(&bp, ",");
- d.homephone = ( p ? p : "");
+#ifdef OPEN_DIRECTORY
+ CFArrayRef values = CFDictionaryGetValue(attrs, CFSTR(kDSNAttrRecordName));
+ CFStringRef username = (values && CFArrayGetCount(values)) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL;
+
+ (void)cfprintf(fp,
+ "# Changing user information for %@.\n"
+ "# Use \"passwd\" to change the password.\n"
+ "##\n"
+ "# Open Directory%s%@\n"
+ "##\n",
+ username,
+ DSPath ? ": " : "",
+ DSPath ? DSPath : CFSTR(""));
+
+ int ndisplayed = 0;
+ ENTRY* ep;
for (ep = list; ep->prompt; ep++)
if (!ep->restricted) {
- ep->display(&d, fp);
+ ep->display(attrs, ep->attrName, ep->prompt, fp);
ndisplayed++;
}
if(!ndisplayed) {
(void)fprintf(fp, "# No fields are available to change\n");
(void)fprintf(fp, "###################################\n");
}
-#else /* DIRECTORY_SERVICE */
- (void)fprintf(fp,
- "##\n"
- "# User Database\n"
- "# \n"
- "# Note: This program edits the /etc/master.passwd file which is only \n"
- "# consulted when the system is running in single-user mode. At other times \n"
- "# this information is handled by lookupd. By default, lookupd gets \n"
- "# information from NetInfo, so this file will not be consulted unless you \n"
- "# have changed lookupd's configuration.\n"
- "##\n");
-
- if (!uid) {
+#else OPEN_DIRECTORY
+ (void)fprintf(fp,
+ "#Changing user information for %s.\n", pw->pw_name);
+ if (master_mode) {
(void)fprintf(fp, "Login: %s\n", pw->pw_name);
(void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
- (void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid);
- (void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid);
+ (void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
+ (void)fprintf(fp, "Gid [# or name]: %lu\n",
+ (unsigned long)pw->pw_gid);
(void)fprintf(fp, "Change [month day year]: %s\n",
ttoa(pw->pw_change));
(void)fprintf(fp, "Expire [month day year]: %s\n",
*pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
}
/* Only admin can change "restricted" shells. */
+#if 0
else if (ok_shell(pw->pw_shell))
/*
* Make shell a restricted field. Ugly with a
* necklace, but there's not much else to do.
*/
+#else
+ else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) ||
+ master_mode)
+ /*
+ * If change not restrict (table.c) and standard shell
+ * OR if root, then allow editing of shell.
+ */
+#endif
(void)fprintf(fp, "Shell: %s\n",
*pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
else
list[E_SHELL].restricted = 1;
- bp = pw->pw_gecos;
+
+ if ((bp = gecos = strdup(pw->pw_gecos)) == NULL) {
+ warn(NULL);
+ fclose(fp);
+ return (-1);
+ }
+
p = strsep(&bp, ",");
- (void)fprintf(fp, "Full Name: %s\n", p ? p : "");
+ p = strdup(p ? p : "");
+ list[E_NAME].save = p;
+ if (!list[E_NAME].restricted || master_mode)
+ (void)fprintf(fp, "Full Name: %s\n", p);
+
p = strsep(&bp, ",");
- (void)fprintf(fp, "Location: %s\n", p ? p : "");
+ p = strdup(p ? p : "");
+ list[E_LOCATE].save = p;
+ if (!list[E_LOCATE].restricted || master_mode)
+ (void)fprintf(fp, "Office Location: %s\n", p);
+
p = strsep(&bp, ",");
- (void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
+ p = strdup(p ? p : "");
+ list[E_BPHONE].save = p;
+ if (!list[E_BPHONE].restricted || master_mode)
+ (void)fprintf(fp, "Office Phone: %s\n", p);
+
p = strsep(&bp, ",");
- (void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
-#endif /* DIRECTORY_SERVICE */
+ p = strdup(p ? p : "");
+ list[E_HPHONE].save = p;
+ if (!list[E_HPHONE].restricted || master_mode)
+ (void)fprintf(fp, "Home Phone: %s\n", p);
+
+ bp = strdup(bp ? bp : "");
+ list[E_OTHER].save = bp;
+ if (!list[E_OTHER].restricted || master_mode)
+ (void)fprintf(fp, "Other information: %s\n", bp);
+
+ free(gecos);
+#endif /* OPEN_DIRECTORY */
- (void)fchown(fd, getuid(), getgid());
+ (void)fchown(fileno(fp), getuid(), getgid());
(void)fclose(fp);
+ return (0);
}
-int
-verify(pw)
- struct passwd *pw;
+#ifdef OPEN_DIRECTORY
+static CFDictionaryRef
+verify(const char* tfn, CFDictionaryRef pw)
+#else
+static struct passwd *
+verify(const char *tfn, struct passwd *pw)
+#endif
{
+#ifdef OPEN_DIRECTORY
+ CFMutableDictionaryRef npw;
+#else
+ struct passwd *npw;
+#endif
ENTRY *ep;
- char *p;
+ char *buf, *p, *val;
struct stat sb;
FILE *fp;
- int len;
- static char buf[LINE_MAX];
+ int line;
+ size_t len;
- if (!(fp = fopen(tempname, "r")))
- pw_error(tempname, 1, 1);
- if (fstat(fileno(fp), &sb))
- pw_error(tempname, 1, 1);
+#ifdef OPEN_DIRECTORY
+ if ((npw = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == NULL)
+ return (NULL);
+#else
+ if ((pw = pw_dup(pw)) == NULL)
+ return (NULL);
+#endif
+ if ((fp = fopen(tfn, "r")) == NULL ||
+ fstat(fileno(fp), &sb) == -1) {
+ warn("%s", tfn);
+#ifndef OPEN_DIRECTORY
+ free(pw);
+#endif
+ return (NULL);
+ }
if (sb.st_size == 0) {
warnx("corrupted temporary file");
- goto bad;
+ fclose(fp);
+#ifndef OPEN_DIRECTORY
+ free(pw);
+#endif
+ return (NULL);
}
- while (fgets(buf, sizeof(buf), fp)) {
- if (!buf[0] || buf[0] == '#')
+ val = NULL;
+ for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
+ if (*buf == '\0' || *buf == '#')
continue;
- if (!(p = strchr(buf, '\n'))) {
- warnx("line too long");
- goto bad;
- }
- *p = '\0';
+ while (len > 0 && isspace(buf[len - 1]))
+ --len;
for (ep = list;; ++ep) {
if (!ep->prompt) {
- warnx("unrecognized field");
+ warnx("%s: unrecognized field on line %d",
+ tfn, line);
goto bad;
}
- if (!strncasecmp(buf, ep->prompt, ep->len)) {
- if (ep->restricted && uid) {
- warnx(
- "you may not change the %s field",
- ep->prompt);
- goto bad;
- }
- if (!(p = strchr(buf, ':'))) {
- warnx("line corrupted");
- goto bad;
- }
- while (isspace(*++p));
- if (ep->except && strpbrk(p, ep->except)) {
- warnx(
- "illegal character in the \"%s\" field",
- ep->prompt);
- goto bad;
- }
- if ((ep->func)(p, pw, ep)) {
-bad: (void)fclose(fp);
- return (0);
+ if (ep->len > len)
+ continue;
+ if (strncasecmp(buf, ep->prompt, ep->len) != 0)
+ continue;
+ if (ep->restricted && !master_mode) {
+ warnx("%s: you may not change the %s field",
+ tfn, ep->prompt);
+ goto bad;
+ }
+ for (p = buf; p < buf + len && *p != ':'; ++p)
+ /* nothing */ ;
+ if (*p != ':') {
+ warnx("%s: line %d corrupted", tfn, line);
+ goto bad;
+ }
+ while (++p < buf + len && isspace(*p))
+ /* nothing */ ;
+ free(val);
+ asprintf(&val, "%.*s", (int)(buf + len - p), p);
+ if (val == NULL)
+ goto bad;
+ if (ep->except && strpbrk(val, ep->except)) {
+ warnx("%s: invalid character in \"%s\" field '%s'",
+ tfn, ep->prompt, val);
+ goto bad;
+ }
+#ifdef OPEN_DIRECTORY
+ if ((ep->func)(val, NULL, NULL))
+ goto bad;
+ {
+ CFStringRef str = CFStringCreateWithCString(NULL, val, kCFStringEncodingUTF8);
+ if (str) {
+ CFDictionarySetValue(npw, ep->attrName, str);
+ CFRelease(str);
}
- break;
}
+#else
+ if ((ep->func)(val, pw, ep))
+ goto bad;
+#endif
+ break;
}
}
- (void)fclose(fp);
+ free(val);
+ fclose(fp);
+#ifndef OPEN_DIRECTORY
/* Build the gecos field. */
-#ifdef DIRECTORY_SERVICE
- if (list[E_NAME].save) {
- if (list[E_LOCATE].save) {
-#endif /* DIRECTORY_SERVICE */
- len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
- strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) + 4;
- if (!(p = malloc(len)))
- err(1, NULL);
- (void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s", list[E_NAME].save,
- list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save);
-#ifdef DIRECTORY_SERVICE
- } else
- pw->pw_gecos = list[E_NAME].save;
- } else
- pw->pw_gecos = "";
-#endif /* DIRECTORY_SERVICE */
-
- if (snprintf(buf, sizeof(buf),
- "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s",
- pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
- pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir,
- pw->pw_shell) >= sizeof(buf)) {
- warnx("entries too long");
- return (0);
+ len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save,
+ list[E_LOCATE].save, list[E_BPHONE].save,
+ list[E_HPHONE].save, list[E_OTHER].save);
+ if (p == NULL) {
+ warn("asprintf()");
+ free(pw);
+ return (NULL);
+ }
+ while (len > 0 && p[len - 1] == ',')
+ p[--len] = '\0';
+ pw->pw_gecos = p;
+ buf = pw_make(pw);
+ free(pw);
+ free(p);
+ if (buf == NULL) {
+ warn("pw_make()");
+ return (NULL);
}
- return (pw_scan(buf, pw, NULL));
+ npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER);
+#endif /* !OPEN_DIRECTORY */
+ free(buf);
+ return (npw);
+bad:
+#ifndef OPEN_DIRECTORY
+ free(pw);
+#endif
+ free(val);
+ fclose(fp);
+ return (NULL);
}
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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) 1988, 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 Technology, 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* documentation and/or other materials provided with 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.
* SUCH DAMAGE.
*/
+#if 0
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/chpass/field.c,v 1.9 2004/01/18 21:46:39 charnier Exp $");
+#endif
+
#include <sys/param.h>
+#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <grp.h>
+#include <paths.h>
#include <pwd.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "chpass.h"
-#include "pathnames.h"
/* ARGSUSED */
int
-p_login(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
{
if (!*p) {
warnx("empty login field");
- return (1);
+ return (-1);
}
if (*p == '-') {
warnx("login names may not begin with a hyphen");
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
if (!(pw->pw_name = strdup(p))) {
warnx("can't save entry");
- return (1);
+ return (-1);
}
+#endif
if (strchr(p, '.'))
warnx("\'.\' is dangerous in a login name");
for (; *p; ++p)
/* ARGSUSED */
int
-p_passwd(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
{
- if (!*p)
- pw->pw_passwd = ""; /* "NOLOGIN"; */
- else if (!(pw->pw_passwd = strdup(p))) {
+#ifndef OPEN_DIRECTORY
+ if (!(pw->pw_passwd = strdup(p))) {
warnx("can't save password entry");
- return (1);
+ return (-1);
}
-
+#endif
+
return (0);
}
/* ARGSUSED */
int
-p_uid(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
{
uid_t id;
char *np;
if (!*p) {
warnx("empty uid field");
- return (1);
+ return (-1);
}
if (!isdigit(*p)) {
warnx("illegal uid");
- return (1);
+ return (-1);
}
errno = 0;
id = strtoul(p, &np, 10);
- if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+ if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
warnx("illegal uid");
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
pw->pw_uid = id;
+#endif
return (0);
}
/* ARGSUSED */
int
-p_gid(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
{
struct group *gr;
gid_t id;
if (!*p) {
warnx("empty gid field");
- return (1);
+ return (-1);
}
if (!isdigit(*p)) {
if (!(gr = getgrnam(p))) {
warnx("unknown group %s", p);
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
pw->pw_gid = gr->gr_gid;
+#endif
return (0);
}
errno = 0;
id = strtoul(p, &np, 10);
- if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+ if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
warnx("illegal gid");
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
pw->pw_gid = id;
+#endif
return (0);
}
/* ARGSUSED */
int
-p_class(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
{
- if (!*p)
- pw->pw_class = "";
- else if (!(pw->pw_class = strdup(p))) {
+#ifndef OPEN_DIRECTORY
+ if (!(pw->pw_class = strdup(p))) {
warnx("can't save entry");
- return (1);
+ return (-1);
}
-
+#endif
+
return (0);
}
/* ARGSUSED */
int
-p_change(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
{
+#ifndef OPEN_DIRECTORY
if (!atot(p, &pw->pw_change))
return (0);
warnx("illegal date for change field");
- return (1);
+#endif
+ return (-1);
}
/* ARGSUSED */
int
-p_expire(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
{
+#ifndef OPEN_DIRECTORY
if (!atot(p, &pw->pw_expire))
return (0);
warnx("illegal date for expire field");
- return (1);
+#endif
+ return (-1);
}
/* ARGSUSED */
int
-p_gecos(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
{
- if (!*p)
- ep->save = "";
- else if (!(ep->save = strdup(p))) {
+#ifndef OPEN_DIRECTORY
+ if (!(ep->save = strdup(p))) {
warnx("can't save entry");
- return (1);
+ return (-1);
}
+#endif
return (0);
}
/* ARGSUSED */
int
-p_hdir(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
{
if (!*p) {
warnx("empty home directory field");
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
if (!(pw->pw_dir = strdup(p))) {
warnx("can't save entry");
- return (1);
+ return (-1);
}
+#endif
return (0);
}
+
/* ARGSUSED */
int
-p_shell(p, pw, ep)
- char *p;
- struct passwd *pw;
- ENTRY *ep;
+p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
{
- char *t, *ok_shell();
+ struct stat sbuf;
+#ifdef OPEN_DIRECTORY
+ struct passwd lpw;
+ pw = &lpw;
+ memset(pw, 0, sizeof(lpw));
+ pw->pw_shell = p;
+#endif
+#ifndef OPEN_DIRECTORY
if (!*p) {
- pw->pw_shell = _PATH_BSHELL;
+ pw->pw_shell = strdup(_PATH_BSHELL);
return (0);
}
/* only admin can change from or to "restricted" shells */
- if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
+ if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
warnx("%s: current shell non-standard", pw->pw_shell);
- return (1);
+ return (-1);
}
- if (!(t = ok_shell(p))) {
- if (uid) {
+#endif /* !OPEN_DIRECTORY */
+ if (!ok_shell(p)) {
+ if (!master_mode) {
warnx("%s: non-standard shell", p);
- return (1);
+ return (-1);
}
+#ifndef OPEN_DIRECTORY
+ pw->pw_shell = strdup(p);
+#endif
}
+#ifndef OPEN_DIRECTORY
else
- p = t;
- if (!(pw->pw_shell = strdup(p))) {
+ pw->pw_shell = dup_shell(p);
+ if (!pw->pw_shell) {
warnx("can't save entry");
- return (1);
+ return (-1);
+ }
+#endif
+ if (stat(pw->pw_shell, &sbuf) < 0) {
+ if (errno == ENOENT)
+ warnx("WARNING: shell '%s' does not exist",
+ pw->pw_shell);
+ else
+ warn("WARNING: can't stat shell '%s'", pw->pw_shell);
+ return (0);
+ }
+ if (!S_ISREG(sbuf.st_mode)) {
+ warnx("WARNING: shell '%s' is not a regular file",
+ pw->pw_shell);
+ return (0);
+ }
+ if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
+ warnx("WARNING: shell '%s' is not executable", pw->pw_shell);
+ return (0);
}
return (0);
}
-#ifdef DIRECTORY_SERVICE
-void
-d_change(struct display *d, FILE *fp)
-{
- fprintf(fp, "Change [month day year]: %s\n", ttoa(d->pw->pw_change));
-}
-
-void
-d_class(struct display *d, FILE *fp)
-{
- fprintf(fp, "Class: %s\n", d->pw->pw_class);
-}
-
-void
-d_expire(struct display *d, FILE *fp)
-{
- fprintf(fp, "Expire [month day year]: %s\n", ttoa(d->pw->pw_expire));
-}
-
-void
-d_fullname(struct display *d, FILE *fp)
-{
- fprintf(fp, "Full Name: %s\n", d->fullname);
-}
-
-void
-d_gid(struct display *d, FILE *fp)
-{
- fprintf(fp, "Gid [# or name]: %d\n", d->pw->pw_gid);
-}
-void
-d_hdir(struct display *d, FILE *fp)
-{
- fprintf(fp, "Home directory: %s\n", d->pw->pw_dir);
-}
-
-void
-d_homephone(struct display *d, FILE *fp)
-{
- fprintf(fp, "Home Phone: %s\n", d->homephone);
-}
-
-void
-d_login(struct display *d, FILE *fp)
-{
- fprintf(fp, "Login: %s\n", d->pw->pw_name);
-}
-
-void
-d_location(struct display *d, FILE *fp)
-{
- fprintf(fp, "Location: %s\n", d->location);
-}
-
-void
-d_officephone(struct display *d, FILE *fp)
-{
- fprintf(fp, "Office Phone: %s\n", d->officephone);
-}
-
-void
-d_passwd(struct display *d, FILE *fp)
-{
- fprintf(fp, "Password: %s\n", d->pw->pw_passwd);
-}
-
-void
-d_shell(struct display *d, FILE *fp)
+#ifdef OPEN_DIRECTORY
+#include <uuid/uuid.h>
+/* ARGSUSED */
+int
+p_uuid(char *p, struct passwd *pw __unused, ENTRY *ep)
{
- fprintf(fp, "Shell: %s\n", *d->pw->pw_shell ? d->pw->pw_shell
- : _PATH_BSHELL);
+ uuid_t uu;
+ if (uuid_parse(p, uu) != 0) {
+ warnx("invalid UUID");
+ return (-1);
+ }
+ return (0);
}
void
-d_uid(struct display *d, FILE *fp)
+display_string(CFDictionaryRef attrs, CFStringRef attrName, const char* prompt, FILE *fp)
{
- fprintf(fp, "Uid [#]: %d\n", d->pw->pw_uid);
+ CFTypeRef value = CFSTR("");
+ CFArrayRef values = CFDictionaryGetValue(attrs, attrName);
+ if (values) {
+ value = CFArrayGetCount(values) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL;
+ if (value && CFGetTypeID(value) != CFStringGetTypeID()) value = NULL;
+ }
+ cfprintf(fp, "%s: %@\n", prompt, value);
}
-#endif /* DIRECTORY_SERVICE */
+#endif /* OPEN_DIRECTORY */
--- /dev/null
+#ifdef OPEN_DIRECTORY
+#include "open_directory.h"
+#include "chpass.h"
+#include <err.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <OpenDirectory/OpenDirectoryPriv.h>
+#include <DirectoryService/DirServicesTypes.h>
+
+/*---------------------------------------------------------------------------
+ * PUBLIC setrestricted - sets the restricted flag
+ *---------------------------------------------------------------------------*/
+void
+setrestricted(CFDictionaryRef attrs)
+{
+ const char* user_allowed[] = { "shell", "full name", "office location", "office phone", "home phone", "picture", NULL };
+ const char* root_restricted[] = { "password", "change", "expire", "class", NULL };
+ ENTRY* ep;
+ const char** pp;
+ int restrict_by_default = !master_mode;
+
+ // for ordinary users, everything is restricted except for the values
+ // expressly permitted above
+ // for root, everything is permitted except for the values expressly
+ // restricted above
+
+ for (ep = list; ep->prompt; ep++) {
+ ep->restricted = restrict_by_default;
+ pp = restrict_by_default ? user_allowed : root_restricted;
+ for (; *pp; pp++) {
+ if (strncasecmp(ep->prompt, *pp, ep->len) == 0) {
+ ep->restricted = !restrict_by_default;
+ break;
+ }
+ }
+
+ // If not root, then it is only permitted to change the shell
+ // when the original value is one of the approved shells.
+ // Otherwise, the assumption is that root has given this user
+ // 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));
+ CFTypeRef value = values && CFArrayGetCount(values) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL;
+ if (value && CFGetTypeID(value) == CFStringGetTypeID()) {
+ size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8)+1;
+ char* shell = malloc(size);
+ if (CFStringGetCString(value, shell, size, kCFStringEncodingUTF8)) {
+ if (ok_shell(shell)) {
+ ep->restricted = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+static CFStringRef
+prompt_passwd(CFStringRef user)
+{
+ CFStringRef result = NULL;
+ CFStringRef prompt = CFStringCreateWithFormat(NULL, NULL, CFSTR("Password for %@: "), user);
+ char buf[128];
+ CFStringGetCString(prompt, buf, sizeof(buf), kCFStringEncodingUTF8);
+ char* pass = getpass(buf);
+ result = CFStringCreateWithCString(NULL, pass, kCFStringEncodingUTF8);
+ memset(pass, 0, strlen(pass));
+ CFRelease(prompt);
+ return result;
+}
+
+static void
+show_error(CFErrorRef error) {
+ if (error) {
+ CFStringRef desc = CFErrorCopyDescription(error);
+ if (desc) {
+ cfprintf(stderr, "%s: %@", progname, desc);
+ CFRelease(desc);
+ }
+ desc = CFErrorCopyFailureReason(error);
+ if (desc) cfprintf(stderr, " %@", desc);
+
+ desc = CFErrorCopyRecoverySuggestion(error);
+ if (desc) cfprintf(stderr, " %@", desc);
+
+ fprintf(stderr, "\n");
+ }
+}
+
+static int
+is_singleuser(void) {
+ uint32_t su = 0;
+ size_t susz = sizeof(su);
+ if (sysctlbyname("kern.singleuser", &su, &susz, NULL, 0) != 0) {
+ return 0;
+ } else {
+ return (int)su;
+ }
+}
+
+static int
+load_DirectoryServicesLocal() {
+ const char* launchctl = "/bin/launchctl";
+ const char* plist = "/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist";
+
+ pid_t pid = fork();
+ int status, res;
+ switch (pid) {
+ case -1: // ERROR
+ perror("launchctl");
+ return 0;
+ case 0: // CHILD
+ execl(launchctl, launchctl, "load", plist, NULL);
+ /* NOT REACHED */
+ perror("launchctl");
+ exit(1);
+ break;
+ default: // PARENT
+ do {
+ res = waitpid(pid, &status, 0);
+ } while (res == -1 && errno == EINTR);
+ if (res == -1) {
+ perror("launchctl");
+ return 0;
+ }
+ break;
+ }
+ return (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS));
+}
+
+ODRecordRef
+odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictionaryRef* attrs)
+{
+ ODSessionRef session = NULL;
+ ODNodeRef node = NULL;
+ ODRecordRef rec = NULL;
+ CFErrorRef error = NULL;
+
+ assert(attrs);
+
+ /*
+ * Connect to DS server
+ */
+ session = ODSessionCreate(NULL, NULL, &error);
+ if ( !session && error && CFErrorGetCode(error) == eServerNotRunning ) {
+ /*
+ * In single-user mode, attempt to load the local DS daemon.
+ */
+ if (is_singleuser() && load_DirectoryServicesLocal()) {
+ CFTypeRef keys[] = { kODSessionLocalPath };
+ CFTypeRef vals[] = { CFSTR("/var/db/dslocal") };
+ CFDictionaryRef opts = CFDictionaryCreate(NULL, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (opts) {
+ session = ODSessionCreate(NULL, opts, &error);
+ CFRelease(opts);
+ }
+
+ if (!location) {
+ location = CFRetain(CFSTR("/Local/Default"));
+ }
+ } else {
+ show_error(error);
+ return -1;
+ }
+ }
+
+ /*
+ * Open the specified node, or perform a search.
+ * Copy the record and put the record's location into DSPath.
+ */
+ if (location) {
+ node = ODNodeCreateWithName(NULL, session, location, &error);
+ } else {
+ node = ODNodeCreateWithNodeType(NULL, session, kODTypeAuthenticationSearchNode, &error);
+ }
+ if (session) CFRelease(session);
+ if (node) {
+ CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
+ CFArrayRef desiredAttrs = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
+ rec = ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), user, desiredAttrs, &error );
+ if (desiredAttrs) CFRelease(desiredAttrs);
+ CFRelease(node);
+ }
+ if (rec) {
+ *attrs = ODRecordCopyDetails(rec, NULL, &error);
+ if (*attrs) {
+ CFArrayRef values = CFDictionaryGetValue(*attrs, CFSTR(kDSNAttrMetaNodeLocation));
+ DSPath = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : NULL;
+ }
+
+ /*
+ * Prompt for a password if -u was specified,
+ * or if we are not root,
+ * or if we are updating something not on the
+ * local node.
+ */
+ if (authname || !master_mode ||
+ (DSPath && CFStringCompareWithOptions(DSPath, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo)) {
+
+ CFStringRef password = NULL;
+
+ if (!authname) authname = user;
+
+ password = prompt_passwd(authname);
+ if (!ODRecordSetNodeCredentials(rec, authname, password, &error)) {
+ CFRelease(rec);
+ rec = NULL;
+ }
+ }
+ }
+
+ if (error) show_error(error);
+ return rec;
+}
+
+void
+odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs)
+{
+ CFErrorRef error = NULL;
+ int updated = 0;
+ ENTRY* ep;
+
+ for (ep = list; ep->prompt; ep++) {
+
+ // Nothing to update
+ if (!rec || !attrs_orig || !attrs) break;
+
+ // No need to update if entry is restricted
+ if (ep->restricted) continue;
+
+ 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);
+
+ // No need to update if both values are the same
+ if (value == value_orig) continue;
+
+ // No need to update if strings are equal
+ if (value && value_orig) {
+ if (CFGetTypeID(value_orig) == CFStringGetTypeID() &&
+ CFStringCompare(value_orig, value, 0) == kCFCompareEqualTo) continue;
+ }
+
+ // No need to update if empty string replaces NULL
+ if (!value_orig && value) {
+ if (CFStringGetLength(value) == 0) continue;
+ }
+
+ // Needs update
+ if (value) {
+ // if new value is an empty string, send an empty dictionary which will delete the property.
+ 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)) {
+ updated = 1;
+ }
+ if (values) CFRelease(values);
+ if (error) show_error(error);
+ }
+ }
+
+ if (updated) {
+ updated = ODRecordSynchronize(rec, &error);
+ if (error) show_error(error);
+ }
+ if (!updated) {
+ fprintf(stderr, "%s: no changes made\n", progname);
+ }
+}
+#endif /* OPEN_DIRECTORY */
--- /dev/null
+#ifndef _OPEN_DIRECTORY_H_
+#define _OPEN_DIRECTORY_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenDirectory/OpenDirectory.h>
+
+extern void setrestricted(CFDictionaryRef attrs);
+
+ODRecordRef odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictionaryRef* attrs);
+
+void odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs);
+
+#endif /* _OPEN_DIRECTORY_H_ */
+++ /dev/null
-/*
- * 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) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
- */
-
-#include <paths.h>
-
-#undef _PATH_TMP
-#define _PATH_TMP "/tmp/chpass.XXXXXX"
*
* @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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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@
*/
*
* @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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*-
* Copyright (c) 1990, 1993, 1994
- * 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
* documentation and/or other materials provided with 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.
* SUCH DAMAGE.
*/
+#if 0
+#if 0
+#ifndef lint
+static const char sccsid[] = "@(#)table.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/chpass/table.c,v 1.10 2003/05/03 19:44:45 obrien Exp $");
+#endif
+
#include <sys/types.h>
#include <stddef.h>
#include "chpass.h"
char e1[] = ": ";
char e2[] = ":,";
-#ifdef DIRECTORY_SERVICE
+#ifdef OPEN_DIRECTORY
+#include "open_directory.h"
+
ENTRY list[] = {
- { "login", d_login, p_login, 0, 5, e1, },
- { "password", d_passwd, p_passwd, 0, 8, e1, },
- { "uid", d_uid, p_uid, 0, 3, e1, },
- { "gid", d_gid, p_gid, 0, 3, e1, },
- { "change", d_change, p_change, 0, 6, NULL, },
- { "expire", d_expire, p_expire, 0, 6, NULL, },
- { "class", d_class, p_class, 0, 5, e1, },
- { "home directory", d_hdir, p_hdir, 0, 14, e1, },
- { "shell", d_shell, p_shell, 0, 5, e1, },
- { "full name", d_fullname, p_gecos, 0, 9, e2, },
- { "location", d_location, p_gecos, 0, 8, e2, },
- { "office phone", d_officephone, p_gecos, 0, 12, e2, },
- { "home phone", d_homephone, p_gecos, 0, 10, e2, },
- { NULL },
+ { "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), },
+#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), },
+ { "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), },
+ { NULL, NULL, NULL, 0, 0, NULL, NULL,},
};
-#else /* DIRECTORY_SERVICE */
+#else /* OPEN_DIRECTORY */
ENTRY list[] = {
- { "login", p_login, 1, 5, e1, },
- { "password", p_passwd, 1, 8, e1, },
- { "uid", p_uid, 1, 3, e1, },
- { "gid", p_gid, 1, 3, e1, },
- { "class", p_class, 1, 5, e1, },
- { "change", p_change, 1, 6, NULL, },
- { "expire", p_expire, 1, 6, NULL, },
- { "full name", p_gecos, 0, 9, e2, },
- { "office phone", p_gecos, 0, 12, e2, },
- { "home phone", p_gecos, 0, 10, e2, },
- { "location", p_gecos, 0, 8, e2, },
- { "home directory", p_hdir, 1, 14, e1, },
- { "shell", p_shell, 0, 5, e1, },
- { NULL, 0, },
+ { "login", p_login, 1, 5, e1, NULL },
+ { "password", p_passwd, 1, 8, e1, NULL },
+ { "uid", p_uid, 1, 3, e1, NULL },
+ { "gid", p_gid, 1, 3, e1, NULL },
+ { "class", p_class, 1, 5, e1, NULL },
+ { "change", p_change, 1, 6, NULL, NULL },
+ { "expire", p_expire, 1, 6, NULL, NULL },
+#ifdef RESTRICT_FULLNAME_CHANGE /* do not allow fullname changes */
+ { "full name", p_gecos, 1, 9, e2, NULL },
+#else
+ { "full name", p_gecos, 0, 9, e2, NULL },
+#endif
+ { "office phone", p_gecos, 0, 12, e2, NULL },
+ { "home phone", p_gecos, 0, 10, e2, NULL },
+ { "office location", p_gecos, 0, 15, e2, NULL },
+ { "other information", p_gecos, 0, 11, e1, NULL },
+ { "home directory", p_hdir, 1, 14, e1, NULL },
+ { "shell", p_shell, 0, 5, e1, NULL },
+ { NULL, NULL, 0, 0, NULL, NULL },
};
-#endif /* DIRECTORY_SERVICE */
+#endif /* OPEN_DIRECTORY */
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* documentation and/or other materials provided with 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.
* SUCH DAMAGE.
*/
+#if 0
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)util.c 8.4 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/chpass/util.c,v 1.13 2004/01/18 21:46:39 charnier Exp $");
+#endif
+
#include <sys/types.h>
#include <ctype.h>
-#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "chpass.h"
-#include "pathnames.h"
-static int dmsize[] =
- { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-static char *months[] =
+#if OPEN_DIRECTORY
+#include <err.h>
+#include <paths.h>
+#include <sys/stat.h>
+#include "open_directory.h"
+
+char* tempname;
+#endif /* OPEN_DIRECTORY */
+
+static const char *months[] =
{ "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November",
"December", NULL };
char *
-ttoa(tval)
- time_t tval;
+ttoa(time_t tval)
{
struct tm *tp;
static char tbuf[50];
else
*tbuf = '\0';
return (tbuf);
-}
+}
int
-atot(p, store)
- char *p;
- time_t *store;
+atot(char *p, time_t *store)
{
static struct tm *lt;
- char *t, **mp;
+ char *t;
+ const char **mp;
time_t tval;
int day, month, year;
}
if (!(t = strtok(p, " \t")))
goto bad;
- for (mp = months;; ++mp) {
- if (!*mp)
- goto bad;
- if (!strncasecmp(*mp, t, 3)) {
- month = mp - months + 1;
- break;
+ if (isdigit(*t)) {
+ month = atoi(t);
+ } else {
+ for (mp = months;; ++mp) {
+ if (!*mp)
+ goto bad;
+ if (!strncasecmp(*mp, t, 3)) {
+ month = mp - months + 1;
+ break;
+ }
}
}
if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
goto bad;
year = atoi(t);
- if (day < 1 || day > 31 || month < 1 || month > 12 || !year)
+ if (day < 1 || day > 31 || month < 1 || month > 12)
goto bad;
- if (year < 100)
+ /* Allow two digit years 1969-2068 */
+ if (year < 69)
+ year += 2000;
+ else if (year < 100)
year += TM_YEAR_BASE;
- if (year <= EPOCH_YEAR)
+ if (year < EPOCH_YEAR)
bad: return (1);
- tval = isleap(year) && month > 2;
- for (--year; year >= EPOCH_YEAR; --year)
- tval += isleap(year) ?
- DAYSPERLYEAR : DAYSPERNYEAR;
- while (--month)
- tval += dmsize[month];
- tval += day;
- tval = tval * HOURSPERDAY * MINSPERHOUR * SECSPERMIN;
- tval -= lt->tm_gmtoff;
+ lt->tm_year = year - TM_YEAR_BASE;
+ lt->tm_mon = month - 1;
+ lt->tm_mday = day;
+ lt->tm_hour = 0;
+ lt->tm_min = 0;
+ lt->tm_sec = 0;
+ lt->tm_isdst = -1;
+ if ((tval = mktime(lt)) < 0)
+ return (1);
*store = tval;
return (0);
}
-char *
-ok_shell(name)
- char *name;
+int
+ok_shell(char *name)
{
+#ifdef __APPLE__
+ char *sh;
+#else
char *p, *sh;
+#endif
setusershell();
- while (sh = getusershell()) {
- if (!strcmp(name, sh))
- return (name);
+ while ((sh = getusershell())) {
+ if (!strcmp(name, sh)) {
+ endusershell();
+ return (1);
+ }
+#ifndef __APPLE__
/* allow just shell name, but use "real" path */
- if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0)
- return (sh);
+ if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+ endusershell();
+ return (1);
+ }
+#endif
}
+ endusershell();
+ return (0);
+}
+
+char *
+dup_shell(char *name)
+{
+ char *p, *sh, *ret;
+
+ setusershell();
+ while ((sh = getusershell())) {
+ if (!strcmp(name, sh)) {
+ endusershell();
+ return (strdup(name));
+ }
+ /* allow just shell name, but use "real" path */
+ if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+ ret = strdup(sh);
+ endusershell();
+ return (ret);
+ }
+ }
+ endusershell();
return (NULL);
}
+
+#if OPEN_DIRECTORY
+int
+cfprintf(FILE* file, const char* format, ...) {
+ char* cstr;
+ int result = 0;
+ va_list args;
+ va_start(args, format);
+ CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull);
+ if (formatStr) {
+ CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args);
+ if (str) {
+ size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1;
+ va_end(args);
+ cstr = malloc(size);
+ if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) {
+ result = fprintf(file, "%s", cstr);
+ free(cstr);
+ }
+ CFRelease(str);
+ }
+ CFRelease(formatStr);
+ }
+ return result;
+}
+
+/*
+ * Edit the temp file. Return -1 on error, >0 if the file was modified, 0
+ * if it was not.
+ */
+int
+editfile(const char* tfn)
+{
+ struct sigaction sa, sa_int, sa_quit;
+ sigset_t oldsigset, sigset;
+ struct stat st1, st2;
+ const char *p, *editor;
+ int pstat;
+ pid_t editpid;
+
+ if ((editor = getenv("EDITOR")) == NULL)
+ editor = _PATH_VI;
+ if (p = strrchr(editor, '/'))
+ ++p;
+ else
+ p = editor;
+
+ if (stat(tfn, &st1) == -1)
+ return (-1);
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(SIGINT, &sa, &sa_int);
+ sigaction(SIGQUIT, &sa, &sa_quit);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
+ switch ((editpid = fork())) {
+ case -1:
+ return (-1);
+ case 0:
+ sigaction(SIGINT, &sa_int, NULL);
+ sigaction(SIGQUIT, &sa_quit, NULL);
+ sigprocmask(SIG_SETMASK, &oldsigset, NULL);
+ errno = 0;
+ if (!master_mode) {
+ (void)setgid(getgid());
+ (void)setuid(getuid());
+ }
+ execlp(editor, p, tfn, (char *)NULL);
+ _exit(errno);
+ default:
+ /* parent */
+ break;
+ }
+ for (;;) {
+ if (waitpid(editpid, &pstat, WUNTRACED) == -1) {
+ if (errno == EINTR)
+ continue;
+ unlink(tfn);
+ editpid = -1;
+ break;
+ } else if (WIFSTOPPED(pstat)) {
+ raise(WSTOPSIG(pstat));
+ } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) {
+ editpid = -1;
+ break;
+ } else {
+ unlink(tfn);
+ editpid = -1;
+ break;
+ }
+ }
+ sigaction(SIGINT, &sa_int, NULL);
+ sigaction(SIGQUIT, &sa_quit, NULL);
+ sigprocmask(SIG_SETMASK, &oldsigset, NULL);
+ if (stat(tfn, &st2) == -1)
+ return (-1);
+ return (st1.st_mtime != st2.st_mtime);
+}
+
+void
+pw_error(char *name, int err, int eval)
+{
+ if (err)
+ warn("%s", name);
+ exit(eval);
+}
+
+#endif /* OPEN_DIRECTORY */
--- /dev/null
+
+ifeq "$(SRCROOT)" ""
+ SRCROOT=$(shell pwd)
+endif
+ifeq "$(OBJROOT)" ""
+ OBJROOT=$(shell pwd)
+endif
+ifeq "$(SYMROOT)" ""
+ SYMROOT=$(shell pwd)
+endif
+ifeq "$(DSTROOT)" ""
+ DSTROOT=
+endif
+
+ifneq "$(shell basename $(SRCROOT))" "dirhelper.tproj"
+SRCDIR=$(SRCROOT)/dirhelper.tproj
+else
+SRCDIR=$(SRCROOT)
+endif
+OBJDIR=$(OBJROOT)/dirhelper.obj
+
+CFLAGS = -g -mdynamic-no-pic -Os -Wall -Wextra -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror -D__MigTypeCheck=1 $(RC_CFLAGS) -I $(OBJDIR)
+
+LDFLAGS = -lbsm
+
+all: dirhelper
+
+dirhelper: mighdrs
+ cc -c $(CFLAGS) -o $(OBJDIR)/dirhelperServer.o $(OBJDIR)/dirhelperServer.c
+ cc -c $(CFLAGS) -o $(OBJDIR)/dirhelperUser.o $(OBJDIR)/dirhelperUser.c
+ cc -c $(CFLAGS) -o $(OBJDIR)/dirhelper.o $(SRCDIR)/dirhelper.c
+ cc $(CFLAGS) $(LDFLAGS) -o $(SYMROOT)/dirhelper $(OBJDIR)/dirhelperServer.o $(OBJDIR)/dirhelperUser.o $(OBJDIR)/dirhelper.o
+
+client: mighdrs
+ cc $(CFLAGS) $(LDFLAGS) -o $(SYMROOT)/client $(SRCDIR)/client.c $(OBJDIR)/dirhelperUser.c
+
+install: dirhelper
+ install -m 0644 -o root -g wheel -d $(DSTROOT)/System/Library/LaunchDaemons
+ install -m 0644 -o root -g wheel com.apple.bsd.dirhelper.plist $(DSTROOT)/System/Library/LaunchDaemons/
+ install -m 0755 -o root -g wheel -d $(DSTROOT)/usr/libexec
+ install -m 0755 -o root -g wheel $(SYMROOT)/dirhelper $(DSTROOT)/usr/libexec/
+ strip -S $(DSTROOT)/usr/libexec/dirhelper
+ mkdir -p "$(DSTROOT)/usr/share/man/man8"
+ gzip -c "$(SRCDIR)/dirhelper.8" > "$(DSTROOT)/usr/share/man/man8/dirhelper.8.gz"
+
+installsrc:
+ mkdir "$(SRCDIR)"
+ tar cf - . | tar xf - -C "$(SRCDIR)"
+
+mighdrs:
+ mkdir -p $(OBJDIR)
+ cd $(OBJDIR) && mig -sheader dirhelperServer.h /usr/local/include/dirhelper.defs
+
+installhdrs:
+ @echo nothing to install
+
+#installhdrs: mighdrs
+# install -m 0755 -o root -g wheel -d $(DSTROOT)/usr/local/include
+# install -m 0644 -o root -g wheel $(OBJDIR)/dirhelper.h $(DSTROOT)/usr/local/include/
+
+clean:
+ -rm -f *.o client dirhelper
+ -rm -rf dirhelper.obj
--- /dev/null
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "dirhelper.h"
+
+#define DIRHELPER_BOOTSTRAP_NAME "com.apple.bsd.dirhelper"
+
+int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
+{
+ kern_return_t kr;
+ mach_port_t mp;
+
+ kr = bootstrap_look_up(bootstrap_port, DIRHELPER_BOOTSTRAP_NAME, &mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "bootstrap_look_up(): %s\n", bootstrap_strerror(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ kr = __dirhelper_create_user_local(mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "dirhelper_create_user_local(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.bsd.dirhelper</string>
+ <key>MachServices</key>
+ <dict>
+ <key>com.apple.bsd.dirhelper</key>
+ <true/>
+ </dict>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/libexec/dirhelper</string>
+ </array>
+ <key>RunAtLoad</key>
+ <true/>
+ <key>TimeOut</key>
+ <integer>30</integer>
+ <key>StartCalendarInterval</key>
+ <dict>
+ <key>Hour</key>
+ <integer>3</integer>
+ <key>Minute</key>
+ <integer>35</integer>
+ </dict>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>CLEAN_FILES_OLDER_THAN_DAYS</key>
+ <string>3</string>
+ </dict>
+</dict>
+</plist>
--- /dev/null
+.\"
+.\" Copyright (c) 2006-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@
+.\"
+.Dd November 1, 2006
+.Dt dirhelper 8
+.Os "Mac OS X"
+.Sh NAME
+.Nm dirhelper
+.Nd helper for special directory creation
+.Sh SYNOPSIS
+.Nm dirhelper
+.Sh DESCRIPTION
+The
+.Nm dirhelper
+command is a launch-on-demand helper for special
+directory creation. It is launched in a privileged
+context via
+.Nm launchd
+in order to create special directories where the user
+would not otherwise have permission to do so.
+.Pp
+The
+.Nm dirhelper
+command should not be invoked directly. It will exit
+automatically after a period of inactivity.
+.Sh FILES
+.Bl -tag -width "/System/Library/LaunchDaemons/com.apple.bsd.dirhelper.plist" -compact
+.It Pa /System/Library/LaunchDaemons/com.apple.bsd.dirhelper.plist
+.El
+.Sh SEE ALSO
+.Xr launchd 8 ,
+.Xr launchd.plist 5
--- /dev/null
+/*
+ * Copyright (c) 2006-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 <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+
+#include <bsm/libbsm.h>
+
+#include <asl.h>
+#include <membership.h>
+#include <launch.h>
+#include <dirhelper_priv.h>
+
+#include "dirhelper.h"
+#include "dirhelperServer.h"
+
+// globals for idle exit
+struct idle_globals {
+ mach_port_t mp;
+ long timeout;
+ struct timeval lastmsg;
+};
+
+struct idle_globals idle_globals;
+
+void* idle_thread(void* param __attribute__((unused)));
+
+int file_check(const char* path, int mode, int uid, int gid);
+#define is_file(x) file_check((x), S_IFREG, -1, -1)
+#define is_directory(x) file_check((x), S_IFDIR, -1, -1)
+#define is_root_wheel_directory(x) file_check((x), S_IFDIR, 0, 0)
+
+int is_safeboot(void);
+
+void clean_files_older_than(const char* path, time_t when);
+void clean_directory(const char* name, int);
+
+kern_return_t
+do___dirhelper_create_user_local(
+ mach_port_t server_port __attribute__((unused)),
+ audit_token_t au_tok)
+{
+ int res = 0;
+ uid_t euid;
+ gid_t gid = 0;
+ struct passwd* pwd = NULL;
+
+ gettimeofday(&idle_globals.lastmsg, NULL);
+
+ audit_token_to_au32(au_tok,
+ NULL, // audit uid
+ &euid, // euid
+ NULL, // egid
+ NULL, // ruid
+ NULL, // rgid
+ NULL, // remote_pid
+ NULL, // asid
+ NULL); // aud_tid_t
+
+ // Look-up the primary gid of the user. We'll use this for chown(2)
+ // so that the created directory is owned by a group that the user
+ // belongs to, avoiding warnings if files are moved outside this dir.
+ pwd = getpwuid(euid);
+ if (pwd) gid = pwd->pw_gid;
+
+ do { // begin block
+ char path[PATH_MAX];
+ char *next;
+
+ if (__user_local_dirname(euid, DIRHELPER_USER_LOCAL, path, sizeof(path)) == NULL) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR,
+ "__user_local_dirname: %s", strerror(errno));
+ break;
+ }
+
+ //
+ // 1. Starting with VAR_FOLDERS_PATH, make each subdirectory
+ // in path, ignoring failure if it already exists.
+ // 2. Change ownership of directory to the user.
+ //
+ next = path + strlen(VAR_FOLDERS_PATH);
+ while ((next = strchr(next, '/')) != NULL) {
+ *next = 0; // temporarily truncate
+ res = mkdir(path, 0755);
+ if (res != 0 && errno != EEXIST) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR,
+ "mkdir(%s): %s", path, strerror(errno));
+ break;
+ }
+ *next++ = '/'; // restore the slash and increment
+ }
+ if(next || res) // an error occurred
+ break;
+ res = chown(path, euid, gid);
+ if (res != 0) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR,
+ "chown(%s): %s", path, strerror(errno));
+ }
+ } while(0); // end block
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do___dirhelper_idle_exit(
+ mach_port_t server_port __attribute__((unused)),
+ audit_token_t au_tok __attribute__((unused))) {
+
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ long delta = now.tv_sec - idle_globals.lastmsg.tv_sec;
+ if (delta >= idle_globals.timeout) {
+ asl_log(NULL, NULL, ASL_LEVEL_DEBUG,
+ "idle exit after %ld seconds", delta);
+ exit(EXIT_SUCCESS);
+ }
+
+ return KERN_SUCCESS;
+}
+
+void*
+idle_thread(void* param __attribute__((unused))) {
+ for(;;) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ long delta = (now.tv_sec - idle_globals.lastmsg.tv_sec);
+ if (delta < idle_globals.timeout) {
+ // sleep for remainder of timeout
+ sleep(idle_globals.timeout - delta);
+ } else {
+ // timeout has elapsed, attempt to idle exit
+ __dirhelper_idle_exit(idle_globals.mp);
+ }
+ }
+ return NULL;
+}
+
+// If when == 0, all files are removed. Otherwise, only regular files older than when.
+void
+clean_files_older_than(const char* path, time_t when) {
+ FTS* fts;
+
+ char* path_argv[] = { (char*)path, NULL };
+ fts = fts_open(path_argv, FTS_PHYSICAL | FTS_XDEV, NULL);
+ if (fts) {
+ FTSENT* ent;
+ asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s", path);
+ while ((ent = fts_read(fts))) {
+ switch(ent->fts_info) {
+ case FTS_F:
+ case FTS_DEFAULT:
+ // Unlink the file if it has not been accessed since
+ // the specified time. Obtain an exclusive lock so
+ // that we can avoid a race with other processes
+ // attempting to open the file.
+ if (when == 0) {
+ (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);
+ if (fd != -1) {
+ int res = flock(fd, LOCK_EX | LOCK_NB);
+ if (res == 0) {
+ struct stat sb;
+ res = fstat(fd, &sb);
+ if (res == 0 && sb.st_atime < when) {
+ (void)unlink(ent->fts_path);
+ }
+ (void)flock(fd, LOCK_UN);
+ }
+ close(fd);
+ }
+ }
+ break;
+
+ case FTS_SL:
+ case FTS_SLNONE:
+ if (when == 0) {
+ (void)unlink(ent->fts_path);
+ }
+ break;
+
+ case FTS_DP:
+ if (when == 0) {
+ (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));
+ break;
+
+ default:
+ break;
+ }
+ }
+ fts_close(fts);
+ } else {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno));
+ }
+}
+
+int
+file_check(const char* path, int mode, int uid, int gid) {
+ int check = 1;
+ struct stat sb;
+ if (lstat(path, &sb) == 0) {
+ check = check && ((sb.st_mode & S_IFMT) == mode);
+ check = check && ((sb.st_uid == (uid_t)uid) || uid == -1);
+ check = check && ((sb.st_gid == (gid_t)gid) || gid == -1);
+ } else {
+ if (errno != ENOENT) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno));
+ }
+ check = 0;
+ }
+ return check;
+}
+
+int
+is_safeboot(void) {
+ uint32_t sb = 0;
+ size_t sbsz = sizeof(sb);
+
+ if (sysctlbyname("kern.safeboot", &sb, &sbsz, NULL, 0) != 0) {
+ return 0;
+ } else {
+ return (int)sb;
+ }
+}
+
+void
+clean_directory(const char* name, int machineBoot) {
+ DIR* d;
+ time_t when = 0;
+
+ if (!machineBoot) {
+ struct timeval now;
+ long days = 3;
+ const char* str = getenv("CLEAN_FILES_OLDER_THAN_DAYS");
+ if (str) {
+ days = strtol(str, NULL, 0);
+ }
+ (void)gettimeofday(&now, NULL);
+
+ asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s older than %ld days", name, days);
+
+ when = now.tv_sec - (days * 60 * 60 * 24);
+ }
+
+ // Look up the boot time
+ struct timespec boottime;
+ size_t len = sizeof(boottime);
+ if (sysctlbyname("kern.boottime", &boottime, &len, NULL, 0) == -1) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", "sysctl kern.boottime", strerror(errno));
+ return;
+ }
+
+ if (!is_root_wheel_directory(VAR_FOLDERS_PATH)) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", VAR_FOLDERS_PATH, "invalid ownership");
+ return;
+ }
+
+ if ((d = opendir(VAR_FOLDERS_PATH))) {
+ struct dirent* e;
+ char path[PATH_MAX];
+
+ // /var/folders/*
+ 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);
+ if (is_root_wheel_directory(path)) {
+ DIR* d2 = opendir(path);
+ if (d2) {
+ struct dirent* e2;
+
+ // /var/folders/*/*
+ 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);
+ }
+ }
+
+ closedir(d2);
+ } else {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", path, strerror(errno));
+ }
+ }
+ }
+
+ closedir(d);
+ } else {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", VAR_FOLDERS_PATH, strerror(errno));
+ }
+}
+
+int
+main(int argc, char* argv[]) {
+ mach_msg_size_t mxmsgsz = MAX_TRAILER_SIZE;
+ kern_return_t kr;
+ long idle_timeout = 30; // default 30 second timeout
+
+ // 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);
+ exit(EXIT_SUCCESS);
+ } else if (argc > 1 && strcmp(argv[1], "-cleanTemporaryItems") == 0) {
+ clean_directory(DIRHELPER_TEMP_STR, 0);
+ clean_directory("TemporaryItems", 0);
+ exit(EXIT_SUCCESS);
+ } else if (argc > 1) {
+ exit(EXIT_FAILURE);
+ }
+
+ launch_data_t config = NULL, checkin = NULL;
+ checkin = launch_data_new_string(LAUNCH_KEY_CHECKIN);
+ config = launch_msg(checkin);
+ if (!config || launch_data_get_type(config) == LAUNCH_DATA_ERRNO) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "launchd checkin failed");
+ exit(EXIT_FAILURE);
+ }
+
+ launch_data_t tmv;
+ tmv = launch_data_dict_lookup(config, LAUNCH_JOBKEY_TIMEOUT);
+ if (tmv) {
+ idle_timeout = launch_data_get_integer(tmv);
+ asl_log(NULL, NULL, ASL_LEVEL_DEBUG,
+ "idle timeout set: %ld seconds", idle_timeout);
+ }
+
+ launch_data_t svc;
+ svc = launch_data_dict_lookup(config, LAUNCH_JOBKEY_MACHSERVICES);
+ if (!svc) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "no mach services");
+ exit(EXIT_FAILURE);
+ }
+
+ svc = launch_data_dict_lookup(svc, DIRHELPER_BOOTSTRAP_NAME);
+ if (!svc) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "no mach service: %s",
+ DIRHELPER_BOOTSTRAP_NAME);
+ exit(EXIT_FAILURE);
+ }
+
+ mach_port_t mp = launch_data_get_machport(svc);
+ if (mp == MACH_PORT_NULL) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "NULL mach service: %s",
+ DIRHELPER_BOOTSTRAP_NAME);
+ exit(EXIT_FAILURE);
+ }
+
+ // insert a send right so we can send our idle exit message
+ kr = mach_port_insert_right(mach_task_self(), mp, mp,
+ MACH_MSG_TYPE_MAKE_SEND);
+ if (kr != KERN_SUCCESS) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR, "send right failed: %s",
+ mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ // spawn a thread for our idle timeout
+ pthread_t thread;
+ idle_globals.mp = mp;
+ idle_globals.timeout = idle_timeout;
+ gettimeofday(&idle_globals.lastmsg, NULL);
+ pthread_create(&thread, NULL, &idle_thread, NULL);
+
+ // look to see if we have any messages queued. if not, assume
+ // we were launched because of the calendar interval, and attempt
+ // to clean the temporary items.
+ mach_msg_type_number_t status_count = MACH_PORT_RECEIVE_STATUS_COUNT;
+ mach_port_status_t status;
+ 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);
+ }
+
+ // main event loop
+
+ kr = mach_msg_server(dirhelper_server, mxmsgsz, mp,
+ MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) |
+ MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
+ if (kr != KERN_SUCCESS) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR,
+ "mach_msg_server(mp): %s", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
-OTHER_CFLAGS = -I/System/Library/Frameworks/System.framework/PrivateHeaders
+OTHER_CFLAGS = -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
OTHER_LIBS = -lproc
OTHER_GENERATED_OFILES = $(VERS_OFILE)
.Op Fl N Ar system
.Sh DESCRIPTION
.Nm Dmesg
-displays the contents of the system message buffer. This command needs to be run as root.
+displays the contents of the system message buffer.
+This command needs to be run as root.
.Pp
-.El
.Sh SEE ALSO
.Xr syslogd 8
.Sh HISTORY
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#include <sys/msgbuf.h>
-
-#include <fcntl.h>
-#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
#include <vis.h>
#include <libproc.h>
-
-void usage __P((void));
+void
+usage() {
+ (void)fprintf(stderr, "usage: sudo dmesg\n");
+ exit(1);
+}
int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- register int ch, newl, skip;
- register char *p, *ep;
- struct msgbuf cur;
- char buf[5];
+main(int argc, char **argv) {
+ char msgbuf[16*1024], *visbuf;
+ long data_size;
if (argc > 1)
usage();
- if (proc_kmsgbuf(&cur, sizeof(struct msgbuf)) == 0){
+ if ((data_size = proc_kmsgbuf(msgbuf, sizeof(msgbuf))) == 0){
perror("Unable to obtain kernel buffer");
usage();
- exit(1);
}
- if (cur.msg_magic != MSG_MAGIC) {
- perror("magic number incorrect");
- exit(1);
- }
- if (cur.msg_bufx >= MSG_BSIZE)
- cur.msg_bufx = 0;
-
- /*
- * The message buffer is circular; start at the read pointer, and
- * go to the write pointer - 1.
- */
- p = cur.msg_bufc + cur.msg_bufx;
- ep = cur.msg_bufc + cur.msg_bufx - 1;
- for (newl = skip = 0; p != ep; ++p) {
- if (p == cur.msg_bufc + MSG_BSIZE)
- p = cur.msg_bufc;
- ch = *p;
- /* Skip "\n<.*>" syslog sequences. */
- if (skip) {
- if (ch == '>')
- newl = skip = 0;
- continue;
- }
- if (newl && ch == '<') {
- skip = 1;
- continue;
- }
- if (ch == '\0')
- continue;
- newl = ch == '\n';
- (void)vis(buf, ch, 0, 0);
- if (buf[1] == 0)
- (void)putchar(buf[0]);
- else
- (void)printf("%s", buf);
- }
- if (!newl)
- (void)putchar('\n');
+ visbuf = malloc(data_size*4);
+ strvis(visbuf, msgbuf, 0);
+ printf("%s", visbuf);
+ free(visbuf);
exit(0);
}
-void
-usage()
-{
- (void)fprintf(stderr, "usage: sudo dmesg\n");
- exit(1);
-}
backing_store_alerts 1000;
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
backing_store_triggers 1200;
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
default_pager_alerts.defs backing_store_alerts.defs\
- backing_store_triggers.defs dynamic_pager.8
+ backing_store_triggers.defs dynamic_pager.8\
+ com.apple.dynamic_pager.plist
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
#
MIGFLAGS = -no-cpp-precomp -R -untyped -DNO_DIRECT_RPC
MIG = $(NEXT_ROOT)/usr/bin/mig
+
+Embedded=$(shell tconf --test TARGET_OS_EMBEDDED)
default_pager_alerts_server.c : backing_store_alerts.c \
backing_store_triggers_server.c \
install-man-page:
install -d $(DSTROOT)/usr/share/man/man8
install -c -m 444 dynamic_pager.8 $(DSTROOT)/usr/share/man/man8/dynamic_pager.8
+
+LAUNCHD_PLIST_DIR = $(DSTROOT)/System/Library/LaunchDaemons
+LAUNCHD_PLIST = com.apple.dynamic_pager.plist
+
+install-launchd-plist:
+ install -d $(LAUNCHD_PLIST_DIR)
+ install -c -m 644 $(LAUNCHD_PLIST) $(LAUNCHD_PLIST_DIR)/$(LAUNCHD_PLIST)
+ifeq "$(Embedded)" "YES"
+ /usr/libexec/PlistBuddy -x \
+ -c "Add :Disabled bool true" \
+ "$(LAUNCHD_PLIST_DIR)/$(LAUNCHD_PLIST)"
+endif
#OTHER_PUBLIC_HEADERS = default_pager_alerts_server.h
#OTHER_GENERATED_OFILES = $(VERS_OFILE)
-include ../Makefile.include
-OTHER_CFLAGS =
+OTHER_CFLAGS = -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
+OTHER_LDFLAGS = -framework CoreFoundation -framework IOKit
BEFORE_BUILD = default_pager_alerts_server.o
-AFTER_INSTALL += install-man-page
+AFTER_INSTALL += install-man-page install-launchd-plist
default_pager_alerts.defs,
backing_store_alerts.defs,
backing_store_triggers.defs,
- dynamic_pager.8
+ dynamic_pager.8,
+ com.apple.dynamic_pager.plist
);
};
LANGUAGE = English;
backing_store_alerts 1000;
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
backing_store_triggers 1200;
+#ifndef __MigTypeCheck
+#define __MigTypeCheck 1
+#endif
+
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.dynamic_pager</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/sbin/dynamic_pager</string>
+ <string>-F</string>
+ <string>/private/var/vm/swapfile</string>
+ </array>
+ <key>OnDemand</key>
+ <false/>
+</dict>
+</plist>
.Os "Mac OS X"
.Sh NAME
.Nm dynamic_pager
-.Nd dynamic pager external storage manager
+.Nd external storage manager for dynamic pager
.Sh SYNOPSIS
.Nm dynamic_pager
.Op Fl E
.Sh DESCRIPTION
The
.Nm dynamic_pager
-daemon manages a pool of external swap files which the kernel uses to
-support demand paging. This pool is expanded with new swap files as load on
-the system increases, and contracted when the swapping resources are no
-longer needed. The
+daemon manages a pool of external swap files
+which the kernel uses to support demand paging.
+This pool is expanded with new swap files
+as load on the system increases.
+It is contracted when the swapping resources are no longer needed. The
.Nm dynamic_pager
-daemon also provides a notification service for those applications which
-wish to receive notices when the external paging pool expands or contracts.
+daemon also provides a notification service
+for those applications which wish to receive notices
+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
to use for the external paging files. By default this is
.Pa /private/var/vm/swapfile .
-.It Fl S
-The fixed
-.Ar filesize
-[in bytes] to use for the paging files. By default
-.Nm dynamic_pager
-uses variable sized paging files, using larger sized files as paging demands
-increase. The
-.Fl S ,
-.Fl H
-and
-.Fl L
-options disable that default and cause
-.Nm dynamic_pager
-to use a series of fixed sized external paging files.
+.\" ==========
.It Fl H
If there are less than
.Ar high-water-trigger
bytes free in the external paging files, the kernel will signal
.Nm dynamic_pager
to add a new external paging file.
+.\" ==========
.It Fl L
If there are more than
.Ar low-water-trigger
.Ar high-water-trigger
+
.Ar filesize .
+.\" ==========
.It Fl P
This option is currently unimplemented.
+.\" ==========
+.It Fl S
+The fixed
+.Ar filesize
+[in bytes] to use for the paging files. By default
+.Nm dynamic_pager
+uses variable sized paging files, using larger sized files as paging demands
+increase. The
+.Fl S ,
+.Fl H
+and
+.Fl L
+options disable that default and cause
+.Nm dynamic_pager
+to use a series of fixed sized external paging files.
.El
.Sh FILES
.Bl -tag -width /private/var/vp/swapfile* -compact
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/gmon.h>
+#include <sys/types.h>
#include <errno.h>
-#include <kvm.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <paths.h>
+#include <dirent.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPowerSourcesPrivate.h>
#include <default_pager/default_pager_types.h>
#include <default_pager_alerts_server.h>
if(hi_water) {
mach_msg_type_name_t poly;
- daemon(0,0);
-
if (mach_port_allocate(mach_task_self(),
MACH_PORT_RIGHT_RECEIVE,
&trigger_port) != KERN_SUCCESS) {
}
exit(EXIT_SUCCESS);
}
+
+static void
+clean_swap_directory(const char *path)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char buf[1024];
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ fprintf(stderr,"dynamic_pager: cannot open swap directory %s\n", path);
+ exit(EXIT_FAILURE);
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_namlen>= 4 && strncmp(entry->d_name, "swap", 4) == 0) {
+ snprintf(buf, sizeof buf, "%s/%s", path, entry->d_name);
+ unlink(buf);
+ }
+ }
+
+ closedir(dir);
+}
+
+#define VM_PREFS_PLIST "/Library/Preferences/com.apple.virtualMemory.plist"
+#define VM_PREFS_ENCRYPT_SWAP_KEY "UseEncryptedSwap"
+
+static boolean_t
+should_encrypt_swap(void)
+{
+ CFPropertyListRef propertyList;
+ CFTypeID propertyListType;
+ CFStringRef errorString;
+ CFDataRef resourceData;
+ SInt32 errorCode;
+ CFURLRef fileURL;
+ CFTypeRef value;
+ boolean_t should_encrypt;
+ boolean_t explicit_value;
+ CFTypeRef snap;
+
+ explicit_value = false;
+
+ fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)VM_PREFS_PLIST, strlen(VM_PREFS_PLIST), false);
+ if (fileURL == NULL) {
+ /*fprintf(stderr, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", getprogname(), VM_PREFS_PLIST);*/
+ goto done;
+ }
+
+ if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode)) {
+ /*fprintf(stderr, "%s: CFURLCreateDataAndPropertiesFromResource(%s) failed: %d\n", getprogname(), VM_PREFS_PLIST, (int)errorCode);*/
+ CFRelease(fileURL);
+ goto done;
+ }
+
+ CFRelease(fileURL);
+ propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resourceData, kCFPropertyListMutableContainers, &errorString);
+ if (propertyList == NULL) {
+ /*fprintf(stderr, "%s: cannot get XML propertyList %s\n", getprogname(), VM_PREFS_PLIST);*/
+ CFRelease(resourceData);
+ goto done;
+ }
+
+ propertyListType = CFGetTypeID(propertyList);
+
+ if (propertyListType == CFDictionaryGetTypeID()) {
+ value = (CFTypeRef) CFDictionaryGetValue((CFDictionaryRef) propertyList, CFSTR(VM_PREFS_ENCRYPT_SWAP_KEY));
+ if (value == NULL) {
+ /* no value: use the default value */
+ } else if (CFGetTypeID(value) != CFBooleanGetTypeID()) {
+ fprintf(stderr, "%s: wrong type for key \"%s\"\n",
+ getprogname(), VM_PREFS_ENCRYPT_SWAP_KEY);
+ /* bogus value, assume it's "true" for safety's sake */
+ should_encrypt = true;
+ explicit_value = true;
+ } else {
+ should_encrypt = CFBooleanGetValue((CFBooleanRef)value);
+ explicit_value = true;
+ }
+ }
+ else {
+ /*fprintf(stderr, "%s: invalid propertyList type %d (not a dictionary)\n", getprogname(), propertyListType);*/
+ }
+ CFRelease(resourceData);
+ CFRelease(propertyList);
+
+done:
+ if (! explicit_value) {
+ /* 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);*/
+ }
+ }
+
+ return should_encrypt;
+}
+
int
main(int argc, char **argv)
{
char default_filename[] = "/private/var/vm/swapfile";
int ch;
int variable_sized = 1;
- boolean_t encrypted_swap = FALSE;
+ boolean_t encrypted_swap;
+
+/*
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+*/
seteuid(getuid());
strcpy(fileroot, default_filename);
hi_water = 0;
local_hi_water = 0;
+ encrypted_swap = should_encrypt_swap();
- while ((ch = getopt(argc, argv, "EF:L:H:S:P:O:")) != EOF) {
+ while ((ch = getopt(argc, argv, "EF:L:H:S:P:QO:")) != EOF) {
switch((char)ch) {
case 'E':
priority = atoi(optarg);
break;
+ case 'Q':
+ /* just query for "encrypted swap" default value */
+ fprintf(stdout,
+ "dynamic_pager: encrypted swap will be %s\n",
+ encrypted_swap ? "ON": "OFF");
+ exit(0);
+
default:
(void)fprintf(stderr,
"usage: dynamic_pager [-F filename] [-L low water alert trigger] [-H high water alert trigger] [-S file size] [-P priority]\n");
size_t len;
unsigned int size;
u_int64_t memsize;
- u_int64_t fs_limit;
+ u_int64_t fs_limit = 0;
/*
* if we get here, then none of the following options were specified... -L, H, or -S
if (q = strrchr(tmp, '/'))
*q = 0;
- if (statfs(tmp, &sfs) != -1) {
- /*
+ if (statfs(tmp, &sfs) == -1) {
+ /*
+ * Setup the swap directory.
+ */
+ if (mkdir(tmp, 0755) == -1) {
+ (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp);
+ exit(EXIT_FAILURE);
+ }
+ chown(tmp, 0, 0);
+
+ if (statfs(tmp, &sfs) == -1) {
+ /*
+ * We really can't get filesystem status,
+ * so let's not limit the swap files...
+ */
+ fs_limit = (u_int64_t) -1;
+ }
+ }
+
+ /*
+ * 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
* space available on the filesystem where the swap files
* are to reside. This will allow us to allocate and
* free space.
*/
fs_limit = ((u_int64_t)sfs.f_bfree * (u_int64_t)sfs.f_bsize) / 8;
-
- } else {
- (void)fprintf(stderr, "dynamic_pager: swap directory must exist\n");
- exit(EXIT_FAILURE);
}
+
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
len = sizeof(u_int64_t);
is formatted according to the size of your window.
A narrow window will display fewer columns of data.
Use a wide window for maximum data display.
-You may override the window formatting restrictions by forcing a wide display
-with the
+You may override the window formatting restrictions
+by forcing a wide display with the
.Fl w
option.
-In this case, the data displayed will wrap when the window is not wide enough.
+In this case, the data displayed will wrap
+when the window is not wide enough.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.\" ==========
.It Fl e
Specifying the
.Fl e
option generates output that excludes sampling
of the running fs_usage tool.
-If a list of process ids or commands is also given, then those processes are
-also excluded from the sampled output.
-.It Fl w
-Specifying the
-.Fl w
-option forces a wider, more detailed output, regardless of the window size.
+If a list of process ids or commands is also given,
+then those processes are also excluded from the sampled output.
+.\" ==========
.It Fl f
Specifying the
.Fl f
.Pp
.Pa cachehit
In addition, display CACHE_HIT output.
+.\" ==========
+.It Fl w
+Specifying the
+.Fl w
+option forces a wider, more detailed output,
+regardless of the window size.
+.\" ==========
.It pid | cmd
The sampled data can be limited to a list of process ids or commands.
When a command name is given, all processes with that name will be sampled.
Using the
.Fl e
-option has the opposite effect, excluding sampled data relating to the given
-list of process ids or commands.
+option has the opposite effect,
+excluding sampled data relating to the given list
+of process ids or commands.
.El
.Pp
If you set the DYLD_IMAGE_SUFFIX environment variable to
.Dq Li _debug ,
-then an application will use the debug version of all libraries including the
-Carbon FileManager.
+then an application will use the debug version of all libraries,
+including the Carbon FileManager.
See
.Xr dyld 1 .
When
.Nm fs_usage
-is run against a Carbon Application launched in this environment, then the
-high level Carbon FileManager calls will be displayed bracketing the system
-calls that they are built on.
+is run against a Carbon Application launched in this environment,
+then the high-level Carbon FileManager calls
+will be displayed bracketing the system calls that they are built on.
.Pp
The data columns displayed are as follows:
.Bl -tag -width Ds
TOD when call occurred.
Wide mode will have millisecond granularity.
.It CALL
-The name of the network or filesystem related call, page-in, page-out or physical disk access.
+The name of the network or filesystem related call, page-in, page-out,
+or physical disk access.
.It FILE DESCRIPTOR
Of the form F=x, x is a file descriptor.
-Depending on the type of system call, this will be either an input value or a
-return value.
+Depending on the type of system call,
+this will be either an input value or a return value.
.It BYTE COUNT
Of the form B=x, x is the number of bytes requested by the call.
.It [ERRNO]
.It PATHNAME
Pathname of the file accessed (up to the last 28 bytes).
.It FAULT ADDRESS
-Of the form A=0xnnnnnnnn, where 0xnnnnnnnn is the address being faulted.
+Of the form A=0xnnnnnnnn,
+where 0xnnnnnnnn is the address being faulted.
.It DISK BLOCK NUMBER
-Of the form D=0xnnnnnnnn, where 0xnnnnnnnn is the block number of the physical
-disk block being read or written.
+Of the form D=0xnnnnnnnn,
+where 0xnnnnnnnn is the block number
+of the physical disk block being read or written.
.It OFFSET
Of the form O=0xnnnnnnnn, where 0xnnnnnnnn is a file offset.
.It SELECT RETURN
-Of the form S=x, x is the number of ready descriptors returned by the select()
-system call.
+Of the form S=x, x is the number of ready descriptors returned
+by the select() system call.
If S=0, the time limit expired.
.It TIME INTERVAL(W)
The elapsed time spent in the system call.
A
.Sq Li W
-after the elapsed time indicates the process was scheduled out during this file
-activity.
+after the elapsed time indicates the process was scheduled out
+during this file activity.
In this case, the elapsed time includes the wait time.
.It PROCESS NAME
The process that made the system call.
fs_usage -w -f filesys Mail
.Pp
.Nm fs_usage
-will display file system related data for all instances of processes named Mail.
+will display file system related data
+for all instances of processes named Mail.
Maximum data output will be displayed in the window.
.Sh SEE ALSO
-.Xr top 1 ,
-.Xr sc_usage 1 ,
+.Xr dyld 1 ,
.Xr latency 1 ,
-.Xr dyld 1
+.Xr sc_usage 1 ,
+.Xr top 1
#include <strings.h>
#include <nlist.h>
#include <fcntl.h>
+#include <aio.h>
#include <string.h>
#include <dirent.h>
#include <libc.h>
#include <termios.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
#ifndef KERNEL_PRIVATE
#define KERNEL_PRIVATE
#define MAXINDEX 2048
+typedef struct LibraryRange {
+ uint64_t b_address;
+ uint64_t e_address;
+} LibraryRange;
+
+LibraryRange framework32;
+LibraryRange framework64;
+
+
typedef struct LibraryInfo {
- unsigned long address;
+ uint64_t b_address;
+ uint64_t e_address;
char *name;
} LibraryInfo;
LibraryInfo frameworkInfo[MAXINDEX];
int numFrameworks = 0;
-char seg_addr_table[256]="/AppleInternal/Developer/seg_addr_table";
-
-char *lookup_name();
+char *lookup_name(uint64_t user_addr);
/*
*/
#define NUMPARMS 23
#define PATHLENGTH (NUMPARMS*sizeof(long))
-#define MAXCOLS 131
+#define MAXCOLS 132
#define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
#define MAXWIDTH MAX_WIDE_MODE_COLS + 64
-
struct th_info {
+ int my_index;
int in_filemgr;
int thread;
int pid;
int arg2;
int arg3;
int arg4;
+ int arg5;
+ int arg6;
+ int arg7;
+ int arg8;
int child_thread;
int waited;
double stime;
#define MAX_THREADS 512
struct th_info th_state[MAX_THREADS];
+kd_threadmap *last_map = NULL;
+int last_thread = 0;
+int map_is_the_same = 0;
+int filemgr_in_progress = 0;
+int execs_in_progress = 0;
+int cur_start = 0;
int cur_max = 0;
int need_new_map = 1;
-int bias_secs;
+int bias_secs = 0;
+long last_time;
int wideflag = 0;
int columns = 0;
int select_pid_mode = 0; /* Flag set indicates that output is restricted
char *arguments = 0;
int argmax = 0;
+
+#define USLEEP_MIN 1
+#define USLEEP_BEHIND 2
+#define USLEEP_MAX 32
+int usleep_ms = USLEEP_MIN;
+
/*
* Network only or filesystem only output filter
* Default of zero means report all activity - no filtering
#define NETWORK_FILTER 0x02
#define CACHEHIT_FILTER 0x04
#define EXEC_FILTER 0x08
+#define PATHNAME_FILTER 0x10
#define DEFAULT_DO_NOT_FILTER 0x00
int filter_mode = CACHEHIT_FILTER;
struct diskio *free_diskios = NULL;
struct diskio *busy_diskios = NULL;
+
+
struct diskio *insert_diskio();
struct diskio *complete_diskio();
void free_diskio();
void print_diskio();
-void format_print();
+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);
char *find_disk_name();
void cache_disk_names();
-int ReadSegAddrTable();
+int ReadSharedCacheMap(const char *, LibraryRange *);
+void SortFrameworkAddresses();
void mark_thread_waited(int);
int check_filter_mode(struct th_info *, int, int, int, char *);
void fs_usage_fd_set(unsigned int, unsigned int);
void create_map_entry(int, int, char *);
void enter_syscall();
-void exit_syscall();
void extend_syscall();
void kill_thread_map();
+#define CLASS_MASK 0xff000000
+#define CSC_MASK 0xffff0000
+#define BSC_INDEX(type) ((type >> 2) & 0x3fff)
+
+
#define TRACE_DATA_NEWTHREAD 0x07000004
#define TRACE_DATA_EXEC 0x07000008
#define TRACE_STRING_NEWTHREAD 0x07010004
#define TRACE_STRING_EXEC 0x07010008
-#define MACH_vmfault 0x01300000
+#define MACH_vmfault 0x01300008
#define MACH_pageout 0x01300004
#define MACH_sched 0x01400000
#define MACH_stkhandoff 0x01400008
#define VFS_LOOKUP 0x03010090
#define BSC_exit 0x040C0004
+#define P_DISKIO 0x03020000
+#define P_DISKIO_DONE 0x03020004
+#define P_DISKIO_MASK (CSC_MASK | 0x4)
+
#define P_WrData 0x03020000
#define P_RdData 0x03020008
#define P_WrMeta 0x03020020
#define P_PgOutAsync 0x03020050
#define P_PgInAsync 0x03020058
-#define P_WrDataDone 0x03020004
-#define P_RdDataDone 0x0302000C
-#define P_WrMetaDone 0x03020024
-#define P_RdMetaDone 0x0302002C
-#define P_PgOutDone 0x03020044
-#define P_PgInDone 0x0302004C
+#define P_WrDataDone 0x03020004
+#define P_RdDataDone 0x0302000C
+#define P_WrMetaDone 0x03020024
+#define P_RdMetaDone 0x0302002C
+#define P_PgOutDone 0x03020044
+#define P_PgInDone 0x0302004C
#define P_WrDataAsyncDone 0x03020014
#define P_RdDataAsyncDone 0x0302001C
#define P_WrMetaAsyncDone 0x03020034
#define MSC_map_fd 0x010c00ac
+#define BSC_BASE 0x040C0000
+#define MSC_BASE 0x010C0000
+
// Network related codes
-#define BSC_recvmsg 0x040C006C
-#define BSC_sendmsg 0x040C0070
-#define BSC_recvfrom 0x040C0074
-#define BSC_accept 0x040C0078
-#define BSC_select 0x040C0174
-#define BSC_socket 0x040C0184
-#define BSC_connect 0x040C0188
-#define BSC_bind 0x040C01A0
-#define BSC_listen 0x040C01A8
-#define BSC_sendto 0x040C0214
-#define BSC_socketpair 0x040C021C
-
-#define BSC_read 0x040C000C
-#define BSC_write 0x040C0010
-#define BSC_open 0x040C0014
-#define BSC_close 0x040C0018
-#define BSC_link 0x040C0024
-#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_fchflags 0x040C008C
-#define BSC_sync 0x040C0090
-#define BSC_dup 0x040C00A4
-#define BSC_revoke 0x040C00E0
-#define BSC_symlink 0x040C00E4
-#define BSC_readlink 0x040C00E8
-#define BSC_execve 0x040C00EC
-#define BSC_chroot 0x040C00F4
-#define BSC_dup2 0x040C0168
-#define BSC_fsync 0x040C017C
-#define BSC_readv 0x040C01E0
-#define BSC_writev 0x040C01E4
-#define BSC_fchown 0x040C01EC
-#define BSC_fchmod 0x040C01F0
-#define BSC_rename 0x040C0200
-#define BSC_mkfifo 0x040c0210
-#define BSC_mkdir 0x040C0220
-#define BSC_rmdir 0x040C0224
-#define BSC_utimes 0x040C0228
-#define BSC_futimes 0x040C022C
-#define BSC_pread 0x040C0264
-#define BSC_pread_extended 0x040E0264
-#define BSC_pwrite 0x040C0268
-#define BSC_pwrite_extended 0x040E0268
-#define BSC_statfs 0x040C0274
-#define BSC_fstatfs 0x040C0278
-#define BSC_stat 0x040C02F0
-#define BSC_fstat 0x040C02F4
-#define BSC_lstat 0x040C02F8
-#define BSC_pathconf 0x040C02FC
-#define BSC_fpathconf 0x040C0300
-#define BSC_getdirentries 0x040C0310
-#define BSC_mmap 0x040c0314
-#define BSC_lseek 0x040c031c
-#define BSC_truncate 0x040C0320
-#define BSC_ftruncate 0x040C0324
-#define BSC_undelete 0x040C0334
-#define BSC_statv 0x040C0364
-#define BSC_lstatv 0x040C0368
-#define BSC_fstatv 0x040C036C
-#define BSC_mkcomplex 0x040C0360
-#define BSC_getattrlist 0x040C0370
-#define BSC_setattrlist 0x040C0374
-#define BSC_getdirentriesattr 0x040C0378
-#define BSC_exchangedata 0x040C037C
-#define BSC_checkuseraccess 0x040C0380
-#define BSC_searchfs 0x040C0384
-#define BSC_delete 0x040C0388
-#define BSC_copyfile 0x040C038C
-#define BSC_getxattr 0x040C03A8
-#define BSC_fgetxattr 0x040C03AC
-#define BSC_setxattr 0x040C03B0
-#define BSC_fsetxattr 0x040C03B4
-#define BSC_removexattr 0x040C03B8
-#define BSC_fremovexattr 0x040C03BC
-#define BSC_listxattr 0x040C03C0
-#define BSC_flistxattr 0x040C03C4
-#define BSC_fsctl 0x040C03C8
-#define BSC_open_extended 0x040C0454
-#define BSC_stat_extended 0x040C045C
-#define BSC_lstat_extended 0x040C0460
-#define BSC_fstat_extended 0x040C0464
-#define BSC_chmod_extended 0x040C0468
-#define BSC_fchmod_extended 0x040C046C
-#define BSC_access_extended 0x040C0470
-#define BSC_mkfifo_extended 0x040C048C
-#define BSC_mkdir_extended 0x040C0490
-#define BSC_load_shared_file 0x040C04A0
-#define BSC_lchown 0x040C05B0
+#define BSC_recvmsg 0x040C006C
+#define BSC_sendmsg 0x040C0070
+#define BSC_recvfrom 0x040C0074
+#define BSC_accept 0x040C0078
+#define BSC_select 0x040C0174
+#define BSC_socket 0x040C0184
+#define BSC_connect 0x040C0188
+#define BSC_bind 0x040C01A0
+#define BSC_listen 0x040C01A8
+#define BSC_sendto 0x040C0214
+#define BSC_socketpair 0x040C021C
+
+#define BSC_read 0x040C000C
+#define BSC_write 0x040C0010
+#define BSC_open 0x040C0014
+#define BSC_close 0x040C0018
+#define BSC_link 0x040C0024
+#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_fchflags 0x040C008C
+#define BSC_sync 0x040C0090
+#define BSC_dup 0x040C00A4
+#define BSC_ioctl 0x040C00D8
+#define BSC_revoke 0x040C00E0
+#define BSC_symlink 0x040C00E4
+#define BSC_readlink 0x040C00E8
+#define BSC_execve 0x040C00EC
+#define BSC_chroot 0x040C00F4
+#define BSC_msync 0x040C0104
+#define BSC_dup2 0x040C0168
+#define BSC_fcntl 0x040C0170
+#define BSC_fsync 0x040C017C
+#define BSC_readv 0x040C01E0
+#define BSC_writev 0x040C01E4
+#define BSC_fchown 0x040C01EC
+#define BSC_fchmod 0x040C01F0
+#define BSC_rename 0x040C0200
+#define BSC_mkfifo 0x040c0210
+#define BSC_mkdir 0x040C0220
+#define BSC_rmdir 0x040C0224
+#define BSC_utimes 0x040C0228
+#define BSC_futimes 0x040C022C
+#define BSC_pread 0x040C0264
+#define BSC_pwrite 0x040C0268
+#define BSC_statfs 0x040C0274
+#define BSC_fstatfs 0x040C0278
+#define BSC_stat 0x040C02F0
+#define BSC_fstat 0x040C02F4
+#define BSC_lstat 0x040C02F8
+#define BSC_pathconf 0x040C02FC
+#define BSC_fpathconf 0x040C0300
+#define BSC_getdirentries 0x040C0310
+#define BSC_mmap 0x040c0314
+#define BSC_lseek 0x040c031c
+#define BSC_truncate 0x040C0320
+#define BSC_ftruncate 0x040C0324
+#define BSC_undelete 0x040C0334
+#define BSC_statv 0x040C0364
+#define BSC_lstatv 0x040C0368
+#define BSC_fstatv 0x040C036C
+#define BSC_mkcomplex 0x040C0360
+#define BSC_getattrlist 0x040C0370
+#define BSC_setattrlist 0x040C0374
+#define BSC_getdirentriesattr 0x040C0378
+#define BSC_exchangedata 0x040C037C
+#define BSC_checkuseraccess 0x040C0380
+#define BSC_searchfs 0x040C0384
+#define BSC_delete 0x040C0388
+#define BSC_copyfile 0x040C038C
+#define BSC_getxattr 0x040C03A8
+#define BSC_fgetxattr 0x040C03AC
+#define BSC_setxattr 0x040C03B0
+#define BSC_fsetxattr 0x040C03B4
+#define BSC_removexattr 0x040C03B8
+#define BSC_fremovexattr 0x040C03BC
+#define BSC_listxattr 0x040C03C0
+#define BSC_flistxattr 0x040C03C4
+#define BSC_fsctl 0x040C03C8
+#define BSC_open_extended 0x040C0454
+#define BSC_stat_extended 0x040C045C
+#define BSC_lstat_extended 0x040C0460
+#define BSC_fstat_extended 0x040C0464
+#define BSC_chmod_extended 0x040C0468
+#define BSC_fchmod_extended 0x040C046C
+#define BSC_access_extended 0x040C0470
+#define BSC_mkfifo_extended 0x040C048C
+#define BSC_mkdir_extended 0x040C0490
+#define BSC_load_shared_file 0x040C04A0
+#define BSC_aio_fsync 0x040C04E4
+#define BSC_aio_return 0x040C04E8
+#define BSC_aio_suspend 0x040C04EC
+#define BSC_aio_cancel 0x040C04F0
+#define BSC_aio_error 0x040C04F4
+#define BSC_aio_read 0x040C04F8
+#define BSC_aio_write 0x040C04FC
+#define BSC_lio_listio 0x040C0500
+#define BSC_lchown 0x040C05B0
+
+#define BSC_read_nocancel 0x040c0630
+#define BSC_write_nocancel 0x040c0634
+#define BSC_open_nocancel 0x040c0638
+#define BSC_close_nocancel 0x040c063c
+#define BSC_recvmsg_nocancel 0x040c0644
+#define BSC_sendmsg_nocancel 0x040c0648
+#define BSC_recvfrom_nocancel 0x040c064c
+#define BSC_accept_nocancel 0x040c0650
+#define BSC_msync_nocancel 0x040c0654
+#define BSC_fcntl_nocancel 0x040c0658
+#define BSC_select_nocancel 0x040c065c
+#define BSC_fsync_nocancel 0x040c0660
+#define BSC_connect_nocancel 0x040c0664
+#define BSC_readv_nocancel 0x040c066c
+#define BSC_writev_nocancel 0x040c0670
+#define BSC_sendto_nocancel 0x040c0674
+#define BSC_pread_nocancel 0x040c0678
+#define BSC_pwrite_nocancel 0x040c067c
+#define BSC_aio_suspend_nocancel 0x40c0694
+
+#define BSC_msync_extended 0x040e0104
+#define BSC_pread_extended 0x040e0264
+#define BSC_pwrite_extended 0x040e0268
+#define BSC_mmap_extended 0x040e0314
+#define BSC_mmap_extended2 0x040f0314
// Carbon File Manager support
-#define FILEMGR_PBGETCATALOGINFO 0x1e000020
-#define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
-#define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
-#define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
-#define FILEMGR_PBCREATEFORK 0x1e000030
-#define FILEMGR_PBDELETEFORK 0x1e000034
-#define FILEMGR_PBITERATEFORK 0x1e000038
-#define FILEMGR_PBOPENFORK 0x1e00003c
-#define FILEMGR_PBREADFORK 0x1e000040
-#define FILEMGR_PBWRITEFORK 0x1e000044
-#define FILEMGR_PBALLOCATEFORK 0x1e000048
-#define FILEMGR_PBDELETEOBJECT 0x1e00004c
-#define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
-#define FILEMGR_PBGETFORKCBINFO 0x1e000054
-#define FILEMGR_PBGETVOLUMEINFO 0x1e000058
-#define FILEMGR_PBMAKEFSREF 0x1e00005c
-#define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
-#define FILEMGR_PBMOVEOBJECT 0x1e000064
-#define FILEMGR_PBOPENITERATOR 0x1e000068
-#define FILEMGR_PBRENAMEUNICODE 0x1e00006c
-#define FILEMGR_PBSETCATALOGINFO 0x1e000070
-#define FILEMGR_PBSETVOLUMEINFO 0x1e000074
-#define FILEMGR_FSREFMAKEPATH 0x1e000078
-#define FILEMGR_FSPATHMAKEREF 0x1e00007c
-
-#define FILEMGR_PBGETCATINFO 0x1e010000
-#define FILEMGR_PBGETCATINFOLITE 0x1e010004
-#define FILEMGR_PBHGETFINFO 0x1e010008
-#define FILEMGR_PBXGETVOLINFO 0x1e01000c
-#define FILEMGR_PBHCREATE 0x1e010010
-#define FILEMGR_PBHOPENDF 0x1e010014
-#define FILEMGR_PBHOPENRF 0x1e010018
-#define FILEMGR_PBHGETDIRACCESS 0x1e01001c
-#define FILEMGR_PBHSETDIRACCESS 0x1e010020
-#define FILEMGR_PBHMAPID 0x1e010024
-#define FILEMGR_PBHMAPNAME 0x1e010028
-#define FILEMGR_PBCLOSE 0x1e01002c
-#define FILEMGR_PBFLUSHFILE 0x1e010030
-#define FILEMGR_PBGETEOF 0x1e010034
-#define FILEMGR_PBSETEOF 0x1e010038
-#define FILEMGR_PBGETFPOS 0x1e01003c
-#define FILEMGR_PBREAD 0x1e010040
-#define FILEMGR_PBWRITE 0x1e010044
-#define FILEMGR_PBGETFCBINFO 0x1e010048
-#define FILEMGR_PBSETFINFO 0x1e01004c
-#define FILEMGR_PBALLOCATE 0x1e010050
-#define FILEMGR_PBALLOCCONTIG 0x1e010054
-#define FILEMGR_PBSETFPOS 0x1e010058
-#define FILEMGR_PBSETCATINFO 0x1e01005c
-#define FILEMGR_PBGETVOLPARMS 0x1e010060
-#define FILEMGR_PBSETVINFO 0x1e010064
-#define FILEMGR_PBMAKEFSSPEC 0x1e010068
-#define FILEMGR_PBHGETVINFO 0x1e01006c
-#define FILEMGR_PBCREATEFILEIDREF 0x1e010070
-#define FILEMGR_PBDELETEFILEIDREF 0x1e010074
-#define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
-#define FILEMGR_PBFLUSHVOL 0x1e01007c
-#define FILEMGR_PBHRENAME 0x1e010080
-#define FILEMGR_PBCATMOVE 0x1e010084
-#define FILEMGR_PBEXCHANGEFILES 0x1e010088
-#define FILEMGR_PBHDELETE 0x1e01008c
-#define FILEMGR_PBDIRCREATE 0x1e010090
-#define FILEMGR_PBCATSEARCH 0x1e010094
-#define FILEMGR_PBHSETFLOCK 0x1e010098
-#define FILEMGR_PBHRSTFLOCK 0x1e01009c
-#define FILEMGR_PBLOCKRANGE 0x1e0100a0
-#define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
+#define FILEMGR_PBGETCATALOGINFO 0x1e000020
+#define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
+#define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
+#define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
+#define FILEMGR_PBCREATEFORK 0x1e000030
+#define FILEMGR_PBDELETEFORK 0x1e000034
+#define FILEMGR_PBITERATEFORK 0x1e000038
+#define FILEMGR_PBOPENFORK 0x1e00003c
+#define FILEMGR_PBREADFORK 0x1e000040
+#define FILEMGR_PBWRITEFORK 0x1e000044
+#define FILEMGR_PBALLOCATEFORK 0x1e000048
+#define FILEMGR_PBDELETEOBJECT 0x1e00004c
+#define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
+#define FILEMGR_PBGETFORKCBINFO 0x1e000054
+#define FILEMGR_PBGETVOLUMEINFO 0x1e000058
+#define FILEMGR_PBMAKEFSREF 0x1e00005c
+#define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
+#define FILEMGR_PBMOVEOBJECT 0x1e000064
+#define FILEMGR_PBOPENITERATOR 0x1e000068
+#define FILEMGR_PBRENAMEUNICODE 0x1e00006c
+#define FILEMGR_PBSETCATALOGINFO 0x1e000070
+#define FILEMGR_PBSETVOLUMEINFO 0x1e000074
+#define FILEMGR_FSREFMAKEPATH 0x1e000078
+#define FILEMGR_FSPATHMAKEREF 0x1e00007c
+
+#define FILEMGR_PBGETCATINFO 0x1e010000
+#define FILEMGR_PBGETCATINFOLITE 0x1e010004
+#define FILEMGR_PBHGETFINFO 0x1e010008
+#define FILEMGR_PBXGETVOLINFO 0x1e01000c
+#define FILEMGR_PBHCREATE 0x1e010010
+#define FILEMGR_PBHOPENDF 0x1e010014
+#define FILEMGR_PBHOPENRF 0x1e010018
+#define FILEMGR_PBHGETDIRACCESS 0x1e01001c
+#define FILEMGR_PBHSETDIRACCESS 0x1e010020
+#define FILEMGR_PBHMAPID 0x1e010024
+#define FILEMGR_PBHMAPNAME 0x1e010028
+#define FILEMGR_PBCLOSE 0x1e01002c
+#define FILEMGR_PBFLUSHFILE 0x1e010030
+#define FILEMGR_PBGETEOF 0x1e010034
+#define FILEMGR_PBSETEOF 0x1e010038
+#define FILEMGR_PBGETFPOS 0x1e01003c
+#define FILEMGR_PBREAD 0x1e010040
+#define FILEMGR_PBWRITE 0x1e010044
+#define FILEMGR_PBGETFCBINFO 0x1e010048
+#define FILEMGR_PBSETFINFO 0x1e01004c
+#define FILEMGR_PBALLOCATE 0x1e010050
+#define FILEMGR_PBALLOCCONTIG 0x1e010054
+#define FILEMGR_PBSETFPOS 0x1e010058
+#define FILEMGR_PBSETCATINFO 0x1e01005c
+#define FILEMGR_PBGETVOLPARMS 0x1e010060
+#define FILEMGR_PBSETVINFO 0x1e010064
+#define FILEMGR_PBMAKEFSSPEC 0x1e010068
+#define FILEMGR_PBHGETVINFO 0x1e01006c
+#define FILEMGR_PBCREATEFILEIDREF 0x1e010070
+#define FILEMGR_PBDELETEFILEIDREF 0x1e010074
+#define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
+#define FILEMGR_PBFLUSHVOL 0x1e01007c
+#define FILEMGR_PBHRENAME 0x1e010080
+#define FILEMGR_PBCATMOVE 0x1e010084
+#define FILEMGR_PBEXCHANGEFILES 0x1e010088
+#define FILEMGR_PBHDELETE 0x1e01008c
+#define FILEMGR_PBDIRCREATE 0x1e010090
+#define FILEMGR_PBCATSEARCH 0x1e010094
+#define FILEMGR_PBHSETFLOCK 0x1e010098
+#define FILEMGR_PBHRSTFLOCK 0x1e01009c
+#define FILEMGR_PBLOCKRANGE 0x1e0100a0
+#define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
#define FILEMGR_CLASS 0x1e
+#define FILEMGR_BASE 0x1e000000
+
+#define FMT_DEFAULT 0
+#define FMT_FD 1
+#define FMT_FD_IO 2
+#define FMT_FD_2 3
+#define FMT_SOCKET 4
+#define FMT_PGIN 5
+#define FMT_PGOUT 6
+#define FMT_CACHEHIT 7
+#define FMT_DISKIO 8
+#define FMT_LSEEK 9
+#define FMT_PREAD 10
+#define FMT_FTRUNC 11
+#define FMT_TRUNC 12
+#define FMT_SELECT 13
+#define FMT_OPEN 14
+#define FMT_AIO_FSYNC 15
+#define FMT_AIO_RETURN 16
+#define FMT_AIO_SUSPEND 17
+#define FMT_AIO_CANCEL 18
+#define FMT_AIO 19
+#define FMT_LIO_LISTIO 20
+#define FMT_MSYNC 21
+#define FMT_FCNTL 22
+#define FMT_ACCESS 23
+#define FMT_CHMOD 24
+#define FMT_FCHMOD 25
+#define FMT_CHMOD_EXT 26
+#define FMT_FCHMOD_EXT 27
+#define FMT_CHFLAGS 28
+#define FMT_FCHFLAGS 29
+#define FMT_IOCTL 30
+#define FMT_MMAP 31
+
+#define MAX_BSD_SYSCALL 512
+
+struct bsd_syscall {
+ char *sc_name;
+ int sc_format;
+} bsd_syscalls[MAX_BSD_SYSCALL];
+
+
+int bsd_syscall_types[] = {
+ BSC_recvmsg,
+ BSC_recvmsg_nocancel,
+ BSC_sendmsg,
+ BSC_sendmsg_nocancel,
+ BSC_recvfrom,
+ BSC_recvfrom_nocancel,
+ BSC_accept,
+ BSC_accept_nocancel,
+ BSC_select,
+ BSC_select_nocancel,
+ BSC_socket,
+ BSC_connect,
+ BSC_connect_nocancel,
+ BSC_bind,
+ BSC_listen,
+ BSC_sendto,
+ BSC_sendto_nocancel,
+ BSC_socketpair,
+ BSC_read,
+ BSC_read_nocancel,
+ BSC_write,
+ BSC_write_nocancel,
+ BSC_open,
+ BSC_open_nocancel,
+ BSC_close,
+ BSC_close_nocancel,
+ BSC_link,
+ BSC_unlink,
+ BSC_chdir,
+ BSC_fchdir,
+ BSC_mknod,
+ BSC_chmod,
+ BSC_chown,
+ BSC_access,
+ BSC_chflags,
+ BSC_fchflags,
+ BSC_sync,
+ BSC_dup,
+ BSC_revoke,
+ BSC_symlink,
+ BSC_readlink,
+ BSC_execve,
+ BSC_chroot,
+ BSC_dup2,
+ BSC_fsync,
+ BSC_fsync_nocancel,
+ BSC_readv,
+ BSC_readv_nocancel,
+ BSC_writev,
+ BSC_writev_nocancel,
+ BSC_fchown,
+ BSC_fchmod,
+ BSC_rename,
+ BSC_mkfifo,
+ BSC_mkdir,
+ BSC_rmdir,
+ BSC_utimes,
+ BSC_futimes,
+ BSC_pread,
+ BSC_pread_nocancel,
+ BSC_pwrite,
+ BSC_pwrite_nocancel,
+ BSC_statfs,
+ BSC_fstatfs,
+ BSC_stat,
+ BSC_fstat,
+ BSC_lstat,
+ BSC_pathconf,
+ BSC_fpathconf,
+ BSC_getdirentries,
+ BSC_mmap,
+ BSC_lseek,
+ BSC_truncate,
+ BSC_ftruncate,
+ BSC_undelete,
+ BSC_statv,
+ BSC_lstatv,
+ BSC_fstatv,
+ BSC_mkcomplex,
+ BSC_getattrlist,
+ BSC_setattrlist,
+ BSC_getdirentriesattr,
+ BSC_exchangedata,
+ BSC_checkuseraccess,
+ BSC_searchfs,
+ BSC_delete,
+ BSC_copyfile,
+ BSC_getxattr,
+ BSC_fgetxattr,
+ BSC_setxattr,
+ BSC_fsetxattr,
+ BSC_removexattr,
+ BSC_fremovexattr,
+ BSC_listxattr,
+ BSC_flistxattr,
+ BSC_fsctl,
+ BSC_open_extended,
+ BSC_stat_extended,
+ BSC_lstat_extended,
+ BSC_fstat_extended,
+ BSC_chmod_extended,
+ BSC_fchmod_extended,
+ BSC_access_extended,
+ BSC_mkfifo_extended,
+ BSC_mkdir_extended,
+ BSC_load_shared_file,
+ BSC_aio_fsync,
+ BSC_aio_return,
+ BSC_aio_suspend,
+ BSC_aio_suspend_nocancel,
+ BSC_aio_cancel,
+ BSC_aio_error,
+ BSC_aio_read,
+ BSC_aio_write,
+ BSC_lio_listio,
+ BSC_lchown,
+ BSC_msync,
+ BSC_msync_nocancel,
+ BSC_fcntl,
+ BSC_fcntl_nocancel,
+ BSC_ioctl,
+ 0
+};
+
+
+#define MAX_FILEMGR 512
+
+struct filemgr_call {
+ char *fm_name;
+} filemgr_calls[MAX_FILEMGR];
+
+
+int filemgr_call_types[] = {
+ FILEMGR_PBGETCATALOGINFO,
+ FILEMGR_PBGETCATALOGINFOBULK,
+ FILEMGR_PBCREATEFILEUNICODE,
+ FILEMGR_PBCREATEDIRECTORYUNICODE,
+ FILEMGR_PBCREATEFORK,
+ FILEMGR_PBDELETEFORK,
+ FILEMGR_PBITERATEFORK,
+ FILEMGR_PBOPENFORK,
+ FILEMGR_PBREADFORK,
+ FILEMGR_PBWRITEFORK,
+ FILEMGR_PBALLOCATEFORK,
+ FILEMGR_PBDELETEOBJECT,
+ FILEMGR_PBEXCHANGEOBJECT,
+ FILEMGR_PBGETFORKCBINFO,
+ FILEMGR_PBGETVOLUMEINFO,
+ FILEMGR_PBMAKEFSREF,
+ FILEMGR_PBMAKEFSREFUNICODE,
+ FILEMGR_PBMOVEOBJECT,
+ FILEMGR_PBOPENITERATOR,
+ FILEMGR_PBRENAMEUNICODE,
+ FILEMGR_PBSETCATALOGINFO,
+ FILEMGR_PBSETVOLUMEINFO,
+ FILEMGR_FSREFMAKEPATH,
+ FILEMGR_FSPATHMAKEREF,
+
+ FILEMGR_PBGETCATINFO,
+ FILEMGR_PBGETCATINFOLITE,
+ FILEMGR_PBHGETFINFO,
+ FILEMGR_PBXGETVOLINFO,
+ FILEMGR_PBHCREATE,
+ FILEMGR_PBHOPENDF,
+ FILEMGR_PBHOPENRF,
+ FILEMGR_PBHGETDIRACCESS,
+ FILEMGR_PBHSETDIRACCESS,
+ FILEMGR_PBHMAPID,
+ FILEMGR_PBHMAPNAME,
+ FILEMGR_PBCLOSE,
+ FILEMGR_PBFLUSHFILE,
+ FILEMGR_PBGETEOF,
+ FILEMGR_PBSETEOF,
+ FILEMGR_PBGETFPOS,
+ FILEMGR_PBREAD,
+ FILEMGR_PBWRITE,
+ FILEMGR_PBGETFCBINFO,
+ FILEMGR_PBSETFINFO,
+ FILEMGR_PBALLOCATE,
+ FILEMGR_PBALLOCCONTIG,
+ FILEMGR_PBSETFPOS,
+ FILEMGR_PBSETCATINFO,
+ FILEMGR_PBGETVOLPARMS,
+ FILEMGR_PBSETVINFO,
+ FILEMGR_PBMAKEFSSPEC,
+ FILEMGR_PBHGETVINFO,
+ FILEMGR_PBCREATEFILEIDREF,
+ FILEMGR_PBDELETEFILEIDREF,
+ FILEMGR_PBRESOLVEFILEIDREF,
+ FILEMGR_PBFLUSHVOL,
+ FILEMGR_PBHRENAME,
+ FILEMGR_PBCATMOVE,
+ FILEMGR_PBEXCHANGEFILES,
+ FILEMGR_PBHDELETE,
+ FILEMGR_PBDIRCREATE,
+ FILEMGR_PBCATSEARCH,
+ FILEMGR_PBHSETFLOCK,
+ FILEMGR_PBHRSTFLOCK,
+ FILEMGR_PBLOCKRANGE,
+ FILEMGR_PBUNLOCKRANGE,
+ 0
+};
+
-#define MAX_PIDS 32
+
+#define MAX_PIDS 256
int pids[MAX_PIDS];
int num_of_pids = 0;
int exclude_pids = 0;
int exclude_default_pids = 1;
+
struct kinfo_proc *kp_buffer = 0;
int kp_nentries = 0;
-#define SAMPLE_SIZE 60000
+#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
void set_pidexclude();
void set_remove();
+ fflush(0);
+
set_enable(0);
if (exclude_pids == 0) {
columns = size.ws_col;
if (columns > MAXWIDTH)
- columns = MAXWIDTH;
+ columns = MAXWIDTH;
}
}
}
fprintf(stderr, " -f Output is based on the mode provided\n");
fprintf(stderr, " mode = \"network\" Show only network related output\n");
fprintf(stderr, " mode = \"filesys\" Show only file system related output\n");
+ fprintf(stderr, " mode = \"pathname\" Show only pathname related output\n");
fprintf(stderr, " mode = \"exec\" Show only execs\n");
fprintf(stderr, " mode = \"cachehit\" In addition, show cachehits\n");
fprintf(stderr, " pid selects process(s) to sample\n");
exit(1);
}
+
+int filemgr_index(type) {
+
+ if (type & 0x10000)
+ return (((type >> 2) & 0x3fff) + 256);
+
+ return (((type >> 2) & 0x3fff));
+}
+
+
+void init_tables(void)
+{ int i;
+ int type;
+ int code;
+
+ for (i = 0; i < MAX_THREADS; i++)
+ th_state[i].my_index = i;
+
+ for (i = 0; i < MAX_BSD_SYSCALL; i++) {
+ bsd_syscalls[i].sc_name = NULL;
+ bsd_syscalls[i].sc_format = FMT_DEFAULT;
+ }
+
+ for (i = 0; i < MAX_FILEMGR; i++) {
+ filemgr_calls[i].fm_name = NULL;
+ }
+
+ for (i = 0; (type = bsd_syscall_types[i]); i++) {
+
+ code = BSC_INDEX(type);
+
+ if (code >= MAX_BSD_SYSCALL) {
+ printf("BSD syscall init (%x): type exceeds table size\n", type);
+ continue;
+ }
+ switch (type) {
+
+ case BSC_recvmsg:
+ case BSC_recvmsg_nocancel:
+ bsd_syscalls[code].sc_name = "recvmsg";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_sendmsg:
+ case BSC_sendmsg_nocancel:
+ bsd_syscalls[code].sc_name = "sendmsg";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_recvfrom:
+ case BSC_recvfrom_nocancel:
+ bsd_syscalls[code].sc_name = "recvfrom";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_sendto:
+ case BSC_sendto_nocancel:
+ bsd_syscalls[code].sc_name = "sendto";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_select:
+ case BSC_select_nocancel:
+ bsd_syscalls[code].sc_name = "select";
+ bsd_syscalls[code].sc_format = FMT_SELECT;
+ break;
+
+ case BSC_accept:
+ case BSC_accept_nocancel:
+ bsd_syscalls[code].sc_name = "accept";
+ bsd_syscalls[code].sc_format = FMT_FD_2;
+ break;
+
+ case BSC_socket:
+ bsd_syscalls[code].sc_name = "socket";
+ bsd_syscalls[code].sc_format = FMT_SOCKET;
+ break;
+
+ case BSC_connect:
+ case BSC_connect_nocancel:
+ bsd_syscalls[code].sc_name = "connect";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_bind:
+ bsd_syscalls[code].sc_name = "bind";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_listen:
+ bsd_syscalls[code].sc_name = "listen";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_mmap:
+ bsd_syscalls[code].sc_name = "mmap";
+ bsd_syscalls[code].sc_format = FMT_MMAP;
+ break;
+
+ case BSC_socketpair:
+ bsd_syscalls[code].sc_name = "socketpair";
+ break;
+
+ case BSC_getxattr:
+ bsd_syscalls[code].sc_name = "getxattr";
+ break;
+
+ case BSC_setxattr:
+ bsd_syscalls[code].sc_name = "setxattr";
+ break;
+
+ case BSC_removexattr:
+ bsd_syscalls[code].sc_name = "removexattr";
+ break;
+
+ case BSC_listxattr:
+ bsd_syscalls[code].sc_name = "listxattr";
+ break;
+
+ case BSC_stat:
+ bsd_syscalls[code].sc_name = "stat";
+ break;
+
+ case BSC_stat_extended:
+ bsd_syscalls[code].sc_name = "stat_extended";
+ break;
+
+ case BSC_execve:
+ bsd_syscalls[code].sc_name = "execve";
+ break;
+
+ case BSC_load_shared_file:
+ bsd_syscalls[code].sc_name = "load_sf";
+ break;
+
+ case BSC_open:
+ case BSC_open_nocancel:
+ bsd_syscalls[code].sc_name = "open";
+ bsd_syscalls[code].sc_format = FMT_OPEN;
+ break;
+
+ case BSC_open_extended:
+ bsd_syscalls[code].sc_name = "open_extended";
+ bsd_syscalls[code].sc_format = FMT_OPEN;
+ break;
+
+ case BSC_dup:
+ bsd_syscalls[code].sc_name = "dup";
+ bsd_syscalls[code].sc_format = FMT_FD_2;
+ break;
+
+ case BSC_dup2:
+ bsd_syscalls[code].sc_name = "dup2";
+ bsd_syscalls[code].sc_format = FMT_FD_2;
+ break;
+
+ case BSC_close:
+ case BSC_close_nocancel:
+ bsd_syscalls[code].sc_name = "close";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_read:
+ case BSC_read_nocancel:
+ bsd_syscalls[code].sc_name = "read";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_write:
+ case BSC_write_nocancel:
+ bsd_syscalls[code].sc_name = "write";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_fgetxattr:
+ bsd_syscalls[code].sc_name = "fgetxattr";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_fsetxattr:
+ bsd_syscalls[code].sc_name = "fsetxattr";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_fremovexattr:
+ bsd_syscalls[code].sc_name = "fremovexattr";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_flistxattr:
+ bsd_syscalls[code].sc_name = "flistxattr";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_fstat:
+ bsd_syscalls[code].sc_name = "fstat";
+ 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_lstat:
+ bsd_syscalls[code].sc_name = "lstat";
+ break;
+
+ case BSC_lstat_extended:
+ bsd_syscalls[code].sc_name = "lstat_extended";
+ break;
+
+ case BSC_lstatv:
+ bsd_syscalls[code].sc_name = "lstatv";
+ break;
+
+ case BSC_link:
+ bsd_syscalls[code].sc_name = "link";
+ break;
+
+ case BSC_unlink:
+ bsd_syscalls[code].sc_name = "unlink";
+ break;
+
+ case BSC_mknod:
+ bsd_syscalls[code].sc_name = "mknod";
+ break;
+
+ case BSC_chmod:
+ bsd_syscalls[code].sc_name = "chmod";
+ bsd_syscalls[code].sc_format = FMT_CHMOD;
+ break;
+
+ case BSC_chmod_extended:
+ bsd_syscalls[code].sc_name = "chmod_extended";
+ bsd_syscalls[code].sc_format = FMT_CHMOD_EXT;
+ break;
+
+ case BSC_fchmod:
+ bsd_syscalls[code].sc_name = "fchmod";
+ bsd_syscalls[code].sc_format = FMT_FCHMOD;
+ break;
+
+ case BSC_fchmod_extended:
+ bsd_syscalls[code].sc_name = "fchmod_extended";
+ bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT;
+ break;
+
+ case BSC_chown:
+ bsd_syscalls[code].sc_name = "chown";
+ break;
+
+ case BSC_lchown:
+ bsd_syscalls[code].sc_name = "lchown";
+ break;
+
+ case BSC_fchown:
+ bsd_syscalls[code].sc_name = "fchown";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_access:
+ bsd_syscalls[code].sc_name = "access";
+ bsd_syscalls[code].sc_format = FMT_ACCESS;
+ break;
+
+ case BSC_access_extended:
+ bsd_syscalls[code].sc_name = "access_extended";
+ break;
+
+ case BSC_chdir:
+ bsd_syscalls[code].sc_name = "chdir";
+ break;
+
+ case BSC_chroot:
+ bsd_syscalls[code].sc_name = "chroot";
+ break;
+
+ case BSC_utimes:
+ bsd_syscalls[code].sc_name = "utimes";
+ break;
+
+ case BSC_delete:
+ bsd_syscalls[code].sc_name = "delete";
+ break;
+
+ case BSC_undelete:
+ bsd_syscalls[code].sc_name = "undelete";
+ break;
+
+ case BSC_revoke:
+ bsd_syscalls[code].sc_name = "revoke";
+ break;
+
+ case BSC_fsctl:
+ bsd_syscalls[code].sc_name = "fsctl";
+ break;
+
+ case BSC_chflags:
+ bsd_syscalls[code].sc_name = "chflags";
+ bsd_syscalls[code].sc_format = FMT_CHFLAGS;
+ break;
+
+ case BSC_fchflags:
+ bsd_syscalls[code].sc_name = "fchflags";
+ bsd_syscalls[code].sc_format = FMT_FCHFLAGS;
+ break;
+
+ case BSC_fchdir:
+ bsd_syscalls[code].sc_name = "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;
+ break;
+
+ case BSC_sync:
+ bsd_syscalls[code].sc_name = "sync";
+ break;
+
+ case BSC_symlink:
+ bsd_syscalls[code].sc_name = "symlink";
+ break;
+
+ case BSC_readlink:
+ bsd_syscalls[code].sc_name = "readlink";
+ break;
+
+ case BSC_fsync:
+ case BSC_fsync_nocancel:
+ bsd_syscalls[code].sc_name = "fsync";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_readv:
+ case BSC_readv_nocancel:
+ bsd_syscalls[code].sc_name = "readv";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_writev:
+ case BSC_writev_nocancel:
+ bsd_syscalls[code].sc_name = "writev";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
+ case BSC_pread:
+ case BSC_pread_nocancel:
+ bsd_syscalls[code].sc_name = "pread";
+ bsd_syscalls[code].sc_format = FMT_PREAD;
+ break;
+
+ case BSC_pwrite:
+ case BSC_pwrite_nocancel:
+ bsd_syscalls[code].sc_name = "pwrite";
+ bsd_syscalls[code].sc_format = FMT_PREAD;
+ break;
+
+ case BSC_mkdir:
+ bsd_syscalls[code].sc_name = "mkdir";
+ break;
+
+ case BSC_mkdir_extended:
+ bsd_syscalls[code].sc_name = "mkdir_extended";
+ break;
+
+ case BSC_mkfifo:
+ bsd_syscalls[code].sc_name = "mkfifo";
+ break;
+
+ case BSC_mkfifo_extended:
+ bsd_syscalls[code].sc_name = "mkfifo_extended";
+ break;
+
+ case BSC_rmdir:
+ bsd_syscalls[code].sc_name = "rmdir";
+ break;
+
+ case BSC_statfs:
+ bsd_syscalls[code].sc_name = "statfs";
+ break;
+
+ case BSC_fstatfs:
+ bsd_syscalls[code].sc_name = "fstatfs";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_pathconf:
+ bsd_syscalls[code].sc_name = "pathconf";
+ break;
+
+ case BSC_fpathconf:
+ bsd_syscalls[code].sc_name = "fpathconf";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_getdirentries:
+ bsd_syscalls[code].sc_name = "getdirentries";
+ 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;
+ break;
+
+ case BSC_truncate:
+ bsd_syscalls[code].sc_name = "truncate";
+ bsd_syscalls[code].sc_format = FMT_TRUNC;
+ break;
+
+ case BSC_ftruncate:
+ bsd_syscalls[code].sc_name = "ftruncate";
+ bsd_syscalls[code].sc_format = FMT_FTRUNC;
+ break;
+
+ case BSC_statv:
+ bsd_syscalls[code].sc_name = "statv";
+ break;
+
+ case BSC_fstatv:
+ bsd_syscalls[code].sc_name = "fstatv";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_mkcomplex:
+ bsd_syscalls[code].sc_name = "mkcomplex";
+ break;
+
+ case BSC_getattrlist:
+ bsd_syscalls[code].sc_name = "getattrlist";
+ break;
+
+ case BSC_setattrlist:
+ bsd_syscalls[code].sc_name = "setattrlist";
+ break;
+
+ case BSC_getdirentriesattr:
+ bsd_syscalls[code].sc_name = "getdirentriesattr";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_exchangedata:
+ bsd_syscalls[code].sc_name = "exchangedata";
+ break;
+
+ case BSC_rename:
+ bsd_syscalls[code].sc_name = "rename";
+ break;
+
+ case BSC_copyfile:
+ bsd_syscalls[code].sc_name = "copyfile";
+ break;
+
+ case BSC_checkuseraccess:
+ bsd_syscalls[code].sc_name = "checkuseraccess";
+ break;
+
+ case BSC_searchfs:
+ bsd_syscalls[code].sc_name = "searchfs";
+ break;
+
+ case BSC_aio_fsync:
+ bsd_syscalls[code].sc_name = "aio_fsync";
+ bsd_syscalls[code].sc_format = FMT_AIO_FSYNC;
+ break;
+
+ case BSC_aio_return:
+ bsd_syscalls[code].sc_name = "aio_return";
+ bsd_syscalls[code].sc_format = FMT_AIO_RETURN;
+ break;
+
+ case BSC_aio_suspend:
+ case BSC_aio_suspend_nocancel:
+ bsd_syscalls[code].sc_name = "aio_suspend";
+ bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND;
+ break;
+
+ case BSC_aio_cancel:
+ bsd_syscalls[code].sc_name = "aio_cancel";
+ bsd_syscalls[code].sc_format = FMT_AIO_CANCEL;
+ break;
+
+ case BSC_aio_error:
+ bsd_syscalls[code].sc_name = "aio_error";
+ bsd_syscalls[code].sc_format = FMT_AIO;
+ break;
+
+ case BSC_aio_read:
+ bsd_syscalls[code].sc_name = "aio_read";
+ bsd_syscalls[code].sc_format = FMT_AIO;
+ break;
+
+ case BSC_aio_write:
+ bsd_syscalls[code].sc_name = "aio_write";
+ bsd_syscalls[code].sc_format = FMT_AIO;
+ break;
+
+ case BSC_lio_listio:
+ bsd_syscalls[code].sc_name = "lio_listio";
+ bsd_syscalls[code].sc_format = FMT_LIO_LISTIO;
+ break;
+
+ case BSC_msync:
+ case BSC_msync_nocancel:
+ bsd_syscalls[code].sc_name = "msync";
+ bsd_syscalls[code].sc_format = FMT_MSYNC;
+ break;
+
+ case BSC_fcntl:
+ case BSC_fcntl_nocancel:
+ bsd_syscalls[code].sc_name = "fcntl";
+ bsd_syscalls[code].sc_format = FMT_FCNTL;
+ break;
+
+ case BSC_ioctl:
+ bsd_syscalls[code].sc_name = "ioctl";
+ bsd_syscalls[code].sc_format = FMT_IOCTL;
+ break;
+ }
+ }
+
+ for (i = 0; (type = filemgr_call_types[i]); i++) {
+ char * p;
+
+ code = filemgr_index(type);
+
+ if (code >= MAX_FILEMGR) {
+ printf("FILEMGR call init (%x): type exceeds table size\n", type);
+ continue;
+ }
+ switch (type) {
+
+ case FILEMGR_PBGETCATALOGINFO:
+ p = "GetCatalogInfo";
+ break;
+
+ case FILEMGR_PBGETCATALOGINFOBULK:
+ p = "GetCatalogInfoBulk";
+ break;
+
+ case FILEMGR_PBCREATEFILEUNICODE:
+ p = "CreateFileUnicode";
+ break;
+
+ case FILEMGR_PBCREATEDIRECTORYUNICODE:
+ p = "CreateDirectoryUnicode";
+ break;
+
+ case FILEMGR_PBCREATEFORK:
+ p = "PBCreateFork";
+ break;
+
+ case FILEMGR_PBDELETEFORK:
+ p = "PBDeleteFork";
+ break;
+
+ case FILEMGR_PBITERATEFORK:
+ p = "PBIterateFork";
+ break;
+
+ case FILEMGR_PBOPENFORK:
+ p = "PBOpenFork";
+ break;
+
+ case FILEMGR_PBREADFORK:
+ p = "PBReadFork";
+ break;
+
+ case FILEMGR_PBWRITEFORK:
+ p = "PBWriteFork";
+ break;
+
+ case FILEMGR_PBALLOCATEFORK:
+ p = "PBAllocateFork";
+ break;
+
+ case FILEMGR_PBDELETEOBJECT:
+ p = "PBDeleteObject";
+ break;
+
+ case FILEMGR_PBEXCHANGEOBJECT:
+ p = "PBExchangeObject";
+ break;
+
+ case FILEMGR_PBGETFORKCBINFO:
+ p = "PBGetForkCBInfo";
+ break;
+
+ case FILEMGR_PBGETVOLUMEINFO:
+ p = "PBGetVolumeInfo";
+ break;
+
+ case FILEMGR_PBMAKEFSREF:
+ p = "PBMakeFSRef";
+ break;
+
+ case FILEMGR_PBMAKEFSREFUNICODE:
+ p = "PBMakeFSRefUnicode";
+ break;
+
+ case FILEMGR_PBMOVEOBJECT:
+ p = "PBMoveObject";
+ break;
+
+ case FILEMGR_PBOPENITERATOR:
+ p = "PBOpenIterator";
+ break;
+
+ case FILEMGR_PBRENAMEUNICODE:
+ p = "PBRenameUnicode";
+ break;
+
+ case FILEMGR_PBSETCATALOGINFO:
+ p = "SetCatalogInfo";
+ break;
+
+ case FILEMGR_PBSETVOLUMEINFO:
+ p = "SetVolumeInfo";
+ break;
+
+ case FILEMGR_FSREFMAKEPATH:
+ p = "FSRefMakePath";
+ break;
+
+ case FILEMGR_FSPATHMAKEREF:
+ p = "FSPathMakeRef";
+ break;
+
+ case FILEMGR_PBGETCATINFO:
+ p = "GetCatInfo";
+ break;
+
+ case FILEMGR_PBGETCATINFOLITE:
+ p = "GetCatInfoLite";
+ break;
+
+ case FILEMGR_PBHGETFINFO:
+ p = "PBHGetFInfo";
+ break;
+
+ case FILEMGR_PBXGETVOLINFO:
+ p = "PBXGetVolInfo";
+ break;
+
+ case FILEMGR_PBHCREATE:
+ p = "PBHCreate";
+ break;
+
+ case FILEMGR_PBHOPENDF:
+ p = "PBHOpenDF";
+ break;
+
+ case FILEMGR_PBHOPENRF:
+ p = "PBHOpenRF";
+ break;
+
+ case FILEMGR_PBHGETDIRACCESS:
+ p = "PBHGetDirAccess";
+ break;
+
+ case FILEMGR_PBHSETDIRACCESS:
+ p = "PBHSetDirAccess";
+ break;
+
+ case FILEMGR_PBHMAPID:
+ p = "PBHMapID";
+ break;
+
+ case FILEMGR_PBHMAPNAME:
+ p = "PBHMapName";
+ break;
+
+ case FILEMGR_PBCLOSE:
+ p = "PBClose";
+ break;
+
+ case FILEMGR_PBFLUSHFILE:
+ p = "PBFlushFile";
+ break;
+
+ case FILEMGR_PBGETEOF:
+ p = "PBGetEOF";
+ break;
+
+ case FILEMGR_PBSETEOF:
+ p = "PBSetEOF";
+ break;
+
+ case FILEMGR_PBGETFPOS:
+ p = "PBGetFPos";
+ break;
+
+ case FILEMGR_PBREAD:
+ p = "PBRead";
+ break;
+
+ case FILEMGR_PBWRITE:
+ p = "PBWrite";
+ break;
+
+ case FILEMGR_PBGETFCBINFO:
+ p = "PBGetFCBInfo";
+ break;
+
+ case FILEMGR_PBSETFINFO:
+ p = "PBSetFInfo";
+ break;
+
+ case FILEMGR_PBALLOCATE:
+ p = "PBAllocate";
+ break;
+
+ case FILEMGR_PBALLOCCONTIG:
+ p = "PBAllocContig";
+ break;
+
+ case FILEMGR_PBSETFPOS:
+ p = "PBSetFPos";
+ break;
+
+ case FILEMGR_PBSETCATINFO:
+ p = "PBSetCatInfo";
+ break;
+
+ case FILEMGR_PBGETVOLPARMS:
+ p = "PBGetVolParms";
+ break;
+
+ case FILEMGR_PBSETVINFO:
+ p = "PBSetVInfo";
+ break;
+
+ case FILEMGR_PBMAKEFSSPEC:
+ p = "PBMakeFSSpec";
+ break;
+
+ case FILEMGR_PBHGETVINFO:
+ p = "PBHGetVInfo";
+ break;
+
+ case FILEMGR_PBCREATEFILEIDREF:
+ p = "PBCreateFileIDRef";
+ break;
+
+ case FILEMGR_PBDELETEFILEIDREF:
+ p = "PBDeleteFileIDRef";
+ break;
+
+ case FILEMGR_PBRESOLVEFILEIDREF:
+ p = "PBResolveFileIDRef";
+ break;
+
+ case FILEMGR_PBFLUSHVOL:
+ p = "PBFlushVol";
+ break;
+
+ case FILEMGR_PBHRENAME:
+ p = "PBHRename";
+ break;
+
+ case FILEMGR_PBCATMOVE:
+ p = "PBCatMove";
+ break;
+
+ case FILEMGR_PBEXCHANGEFILES:
+ p = "PBExchangeFiles";
+ break;
+
+ case FILEMGR_PBHDELETE:
+ p = "PBHDelete";
+ break;
+
+ case FILEMGR_PBDIRCREATE:
+ p = "PBDirCreate";
+ break;
+
+ case FILEMGR_PBCATSEARCH:
+ p = "PBCatSearch";
+ break;
+
+ case FILEMGR_PBHSETFLOCK:
+ p = "PBHSetFlock";
+ break;
+
+ case FILEMGR_PBHRSTFLOCK:
+ p = "PBHRstFLock";
+ break;
+
+ case FILEMGR_PBLOCKRANGE:
+ p = "PBLockRange";
+ break;
+
+ case FILEMGR_PBUNLOCKRANGE:
+ p = "PBUnlockRange";
+ break;
+
+ default:
+ p = NULL;
+ break;
+ }
+ filemgr_calls[code].fm_name = p;
+ }
+}
+
+
+
int
main(argc, argv)
int argc;
char *myname = "fs_usage";
int i;
char ch;
+ struct sigaction osa;
void getdivisor();
void argtopid();
void set_remove();
myname++;
}
}
-
while ((ch = getopt(argc, argv, "ewf:")) != EOF) {
switch(ch) {
filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */
else if (!strcmp(optarg, "exec"))
filter_mode |= EXEC_FILTER;
+ else if (!strcmp(optarg, "pathname"))
+ filter_mode |= PATHNAME_FILTER;
break;
default:
argc -= optind;
argv += optind;
+ /*
+ * when excluding, fs_usage should be the first in line for pids[]
+ *
+ * the !exclude_pids && argc == 0 catches the exclude_default_pids
+ * case below where exclude_pids is later set and the fs_usage PID
+ * needs to make it into pids[]
+ */
+ if (exclude_pids || (!exclude_pids && argc == 0))
+ {
+ if (num_of_pids < (MAX_PIDS - 1))
+ pids[num_of_pids++] = getpid();
+ }
+
/* If we process any list of pids/cmds, then turn off the defaults */
if (argc > 0)
exclude_default_pids = 0;
exclude_pids = 1;
}
- if (exclude_pids)
- {
- if (num_of_pids < (MAX_PIDS - 1))
- pids[num_of_pids++] = getpid();
- else
- exit_usage(myname);
- }
-
#if 0
for (i = 0; i < num_of_pids; i++)
{
/* set up signal handlers */
signal(SIGINT, leave);
signal(SIGQUIT, leave);
- signal(SIGHUP, leave);
+
+ sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
+
+ if (osa.sa_handler == SIG_DFL)
+ signal(SIGHUP, leave);
signal(SIGTERM, leave);
signal(SIGWINCH, sigwinch);
- if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
+ /* 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");
- ReadSegAddrTable();
+ 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);
+ }
+ SortFrameworkAddresses();
+
cache_disk_names();
set_remove();
- set_numbufs(SAMPLE_SIZE);
+ set_numbufs(num_events);
set_init();
if (exclude_pids == 0) {
getdivisor();
init_arguments_buffer();
+ init_tables();
/* main loop */
while (1) {
- usleep(1000 * 20);
+ usleep(1000 * usleep_ms);
sample_sc();
+
+ last_time = time((long *)0);
}
}
}
-struct th_info *find_thread(int thread, int type) {
- struct th_info *ti;
+void destroy_thread(struct th_info *ti) {
- for (ti = th_state; ti < &th_state[cur_max]; ti++) {
- if (ti->thread == thread) {
- if (type == ti->type)
- return(ti);
- if (ti->in_filemgr) {
- if (type == -1)
- return(ti);
- continue;
- }
- if (type == 0)
- return(ti);
- }
- }
- return ((struct th_info *)0);
+ ti->child_thread = 0;
+ ti->thread = 0;
+ ti->pid = 0;
+
+ if (ti->my_index < cur_start)
+ cur_start = ti->my_index;
+
+ if (ti->my_index == cur_max) {
+ while (ti >= &th_state[0]) {
+ if (ti->thread)
+ break;
+ ti--;
+ }
+ cur_max = ti->my_index;
+ }
+}
+
+
+struct th_info *find_empty(void) {
+ struct th_info *ti;
+
+ for (ti = &th_state[cur_start]; ti < &th_state[MAX_THREADS]; ti++, cur_start++) {
+ if (ti->thread == 0) {
+ if (cur_start > cur_max)
+ cur_max = cur_start;
+ cur_start++;
+
+ return (ti);
+ }
+ }
+ return ((struct th_info *)0);
+
+}
+
+
+struct th_info *find_thread(int thread, int type) {
+ struct th_info *ti;
+
+ for (ti = &th_state[0]; ti <= &th_state[cur_max]; ti++) {
+ if (ti->thread == thread) {
+ if (type == ti->type)
+ return(ti);
+ if (ti->in_filemgr) {
+ if (type == -1)
+ return(ti);
+ continue;
+ }
+ if (type == 0)
+ return(ti);
+ }
+ }
+ return ((struct th_info *)0);
}
mark_thread_waited(int thread) {
struct th_info *ti;
- for (ti = th_state; ti < &th_state[cur_max]; ti++) {
+ for (ti = th_state; ti <= &th_state[cur_max]; ti++) {
if (ti->thread == thread) {
- ti->waited = 1;
+ ti->waited = 1;
}
}
}
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 (bufinfo.flags & KDBG_WRAPPED) {
- fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly\n");
+ fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
- for (i = 0; i < cur_max; i++) {
+ 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;
set_enable(0);
set_enable(1);
#endif
for (i = 0; i < count; i++) {
int debugid, thread;
- int type, n;
+ int type;
+ int index;
long *sargptr;
uint64_t now;
long long l_usecs;
if (i == 0)
{
+ curr_time = time((long *)0);
/*
* Compute bias seconds after each trace buffer read.
* This helps resync timestamps with the system clock
* in the event of a system sleep.
*/
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = time((long *)0);
- bias_secs = curr_time - secs;
+ if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
+ l_usecs = (long long)(now / divisor);
+ secs = l_usecs / 1000000;
+ bias_secs = curr_time - secs;
+ }
+ }
+
+ 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);
+ continue;
+ }
+ if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
+ if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
+ print_diskio(dio);
+ free_diskio(dio);
+ }
+ continue;
}
-
switch (type) {
- case P_RdMeta:
- case P_WrMeta:
- case P_RdData:
- case P_WrData:
- case P_PgIn:
- case P_PgOut:
- case P_RdMetaAsync:
- case P_WrMetaAsync:
- case P_RdDataAsync:
- case P_WrDataAsync:
- case P_PgInAsync:
- case P_PgOutAsync:
- insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
- continue;
-
- case P_RdMetaDone:
- case P_WrMetaDone:
- case P_RdDataDone:
- case P_WrDataDone:
- case P_PgInDone:
- case P_PgOutDone:
- case P_RdMetaAsyncDone:
- case P_WrMetaAsyncDone:
- case P_RdDataAsyncDone:
- case P_WrDataAsyncDone:
- case P_PgInAsyncDone:
- case P_PgOutAsyncDone:
- if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
- print_diskio(dio);
- free_diskio(dio);
- }
- continue;
-
-
case TRACE_DATA_NEWTHREAD:
- for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
- if (ti->thread == 0)
- break;
- }
- if (ti == &th_state[MAX_THREADS])
- continue;
- if (n >= cur_max)
- cur_max = n + 1;
+ if ((ti = find_empty()) == NULL)
+ continue;
ti->thread = thread;
ti->child_thread = kd[i].arg1;
continue;
create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
- if (ti == &th_state[cur_max - 1])
- cur_max--;
- ti->child_thread = 0;
- ti->thread = 0;
- ti->pid = 0;
+ destroy_thread(ti);
+
continue;
case TRACE_DATA_EXEC:
- for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
- if (ti->thread == 0)
- break;
- }
- if (ti == &th_state[MAX_THREADS])
- continue;
- if (n >= cur_max)
- cur_max = n + 1;
+ if ((ti = find_empty()) == NULL)
+ continue;
ti->thread = thread;
ti->pid = kd[i].arg1;
{
create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
- if (ti == &th_state[cur_max - 1])
- cur_max--;
- ti->thread = 0;
- ti->pid = 0;
+ destroy_thread(ti);
}
continue;
kill_thread_map(thread);
continue;
+ case BSC_mmap:
+ if (kd[i].arg4 & MAP_ANON)
+ continue;
+ break;
+
case MACH_sched:
case MACH_stkhandoff:
mark_thread_waited(thread);
if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
continue;
- if (!ti->pathptr) {
+ if (ti->pathptr == NULL) {
sargptr = ti->pathname;
*sargptr++ = kd[i].arg2;
*sargptr++ = kd[i].arg3;
* NULL terminate the 'string'
*/
*sargptr = 0;
-
ti->pathptr = sargptr;
} else {
sargptr = ti->pathptr;
/*
- We don't want to overrun our pathname buffer if the
- kernel sends us more VFS_LOOKUP entries than we can
- handle.
- */
+ * We don't want to overrun our pathname buffer if the
+ * kernel sends us more VFS_LOOKUP entries than we can
+ * handle.
+ */
if (sargptr >= &ti->pathname[NUMPARMS]) {
continue;
}
- /*
- We need to detect consecutive vfslookup entries.
- So, if we get here and find a START entry,
- fake the pathptr so we can bypass all further
- vfslookup entries.
- */
+ /*
+ * We need to detect consecutive vfslookup entries.
+ * So, if we get here and find a START entry,
+ * fake the pathptr so we can bypass all further
+ * vfslookup entries.
+ */
if (debugid & DBG_FUNC_START) {
ti->pathptr = &ti->pathname[NUMPARMS];
continue;
* NULL terminate the 'string'
*/
*sargptr = 0;
-
ti->pathptr = sargptr;
}
continue;
}
if (debugid & DBG_FUNC_START) {
- char *p;
-
- switch (type) {
- case FILEMGR_PBGETCATALOGINFO:
- p = "GetCatalogInfo";
- break;
- case FILEMGR_PBGETCATALOGINFOBULK:
- p = "GetCatalogInfoBulk";
- break;
- case FILEMGR_PBCREATEFILEUNICODE:
- p = "CreateFileUnicode";
- break;
- case FILEMGR_PBCREATEDIRECTORYUNICODE:
- p = "CreateDirectoryUnicode";
- break;
- case FILEMGR_PBCREATEFORK:
- p = "PBCreateFork";
- break;
- case FILEMGR_PBDELETEFORK:
- p = "PBDeleteFork";
- break;
- case FILEMGR_PBITERATEFORK:
- p = "PBIterateFork";
- break;
- case FILEMGR_PBOPENFORK:
- p = "PBOpenFork";
- break;
- case FILEMGR_PBREADFORK:
- p = "PBReadFork";
- break;
- case FILEMGR_PBWRITEFORK:
- p = "PBWriteFork";
- break;
- case FILEMGR_PBALLOCATEFORK:
- p = "PBAllocateFork";
- break;
- case FILEMGR_PBDELETEOBJECT:
- p = "PBDeleteObject";
- break;
- case FILEMGR_PBEXCHANGEOBJECT:
- p = "PBExchangeObject";
- break;
- case FILEMGR_PBGETFORKCBINFO:
- p = "PBGetForkCBInfo";
- break;
- case FILEMGR_PBGETVOLUMEINFO:
- p = "PBGetVolumeInfo";
- break;
- case FILEMGR_PBMAKEFSREF:
- p = "PBMakeFSRef";
- break;
- case FILEMGR_PBMAKEFSREFUNICODE:
- p = "PBMakeFSRefUnicode";
- break;
- case FILEMGR_PBMOVEOBJECT:
- p = "PBMoveObject";
- break;
- case FILEMGR_PBOPENITERATOR:
- p = "PBOpenIterator";
- break;
- case FILEMGR_PBRENAMEUNICODE:
- p = "PBRenameUnicode";
- break;
- case FILEMGR_PBSETCATALOGINFO:
- p = "SetCatalogInfo";
- break;
- case FILEMGR_PBSETVOLUMEINFO:
- p = "SetVolumeInfo";
- break;
- case FILEMGR_FSREFMAKEPATH:
- p = "FSRefMakePath";
- break;
- case FILEMGR_FSPATHMAKEREF:
- p = "FSPathMakeRef";
- break;
- // SPEC based calls
- case FILEMGR_PBGETCATINFO:
- p = "GetCatInfo";
- break;
- case FILEMGR_PBGETCATINFOLITE:
- p = "GetCatInfoLite";
- break;
- case FILEMGR_PBHGETFINFO:
- p = "PBHGetFInfo";
- break;
- case FILEMGR_PBXGETVOLINFO:
- p = "PBXGetVolInfo";
- break;
- case FILEMGR_PBHCREATE:
- p = "PBHCreate";
- break;
- case FILEMGR_PBHOPENDF:
- p = "PBHOpenDF";
- break;
- case FILEMGR_PBHOPENRF:
- p = "PBHOpenRF";
- break;
- case FILEMGR_PBHGETDIRACCESS:
- p = "PBHGetDirAccess";
- break;
- case FILEMGR_PBHSETDIRACCESS:
- p = "PBHSetDirAccess";
- break;
- case FILEMGR_PBHMAPID:
- p = "PBHMapID";
- break;
- case FILEMGR_PBHMAPNAME:
- p = "PBHMapName";
- break;
- case FILEMGR_PBCLOSE:
- p = "PBClose";
- break;
- case FILEMGR_PBFLUSHFILE:
- p = "PBFlushFile";
- break;
- case FILEMGR_PBGETEOF:
- p = "PBGetEOF";
- break;
- case FILEMGR_PBSETEOF:
- p = "PBSetEOF";
- break;
- case FILEMGR_PBGETFPOS:
- p = "PBGetFPos";
- break;
- case FILEMGR_PBREAD:
- p = "PBRead";
- break;
- case FILEMGR_PBWRITE:
- p = "PBWrite";
- break;
- case FILEMGR_PBGETFCBINFO:
- p = "PBGetFCBInfo";
- break;
- case FILEMGR_PBSETFINFO:
- p = "PBSetFInfo";
- break;
- case FILEMGR_PBALLOCATE:
- p = "PBAllocate";
- break;
- case FILEMGR_PBALLOCCONTIG:
- p = "PBAllocContig";
- break;
- case FILEMGR_PBSETFPOS:
- p = "PBSetFPos";
- break;
- case FILEMGR_PBSETCATINFO:
- p = "PBSetCatInfo";
- break;
- case FILEMGR_PBGETVOLPARMS:
- p = "PBGetVolParms";
- break;
- case FILEMGR_PBSETVINFO:
- p = "PBSetVInfo";
- break;
- case FILEMGR_PBMAKEFSSPEC:
- p = "PBMakeFSSpec";
- break;
- case FILEMGR_PBHGETVINFO:
- p = "PBHGetVInfo";
- break;
- case FILEMGR_PBCREATEFILEIDREF:
- p = "PBCreateFileIDRef";
- break;
- case FILEMGR_PBDELETEFILEIDREF:
- p = "PBDeleteFileIDRef";
- break;
- case FILEMGR_PBRESOLVEFILEIDREF:
- p = "PBResolveFileIDRef";
- break;
- case FILEMGR_PBFLUSHVOL:
- p = "PBFlushVol";
- break;
- case FILEMGR_PBHRENAME:
- p = "PBHRename";
- break;
- case FILEMGR_PBCATMOVE:
- p = "PBCatMove";
- break;
- case FILEMGR_PBEXCHANGEFILES:
- p = "PBExchangeFiles";
- break;
- case FILEMGR_PBHDELETE:
- p = "PBHDelete";
- break;
- case FILEMGR_PBDIRCREATE:
- p = "PBDirCreate";
- break;
- case FILEMGR_PBCATSEARCH:
- p = "PBCatSearch";
- break;
- case FILEMGR_PBHSETFLOCK:
- p = "PBHSetFlock";
- break;
- case FILEMGR_PBHRSTFLOCK:
- p = "PBHRstFLock";
- break;
- case FILEMGR_PBLOCKRANGE:
- p = "PBLockRange";
- break;
- case FILEMGR_PBUNLOCKRANGE:
- p = "PBUnlockRange";
- break;
- default:
- p = (char *)0;
- break;
- }
- enter_syscall(thread, type, &kd[i], p, (double)now);
+ char * p;
+
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
+
+ index = filemgr_index(type);
+
+ if (index >= MAX_FILEMGR)
+ continue;
+
+ if ((p = filemgr_calls[index].fm_name) == NULL)
+ continue;
+ } else
+ p = NULL;
+
+ enter_syscall(thread, type, &kd[i], p, (double)now);
continue;
}
-
+
switch (type) {
-
- case BSC_pread_extended:
- case BSC_pwrite_extended:
- extend_syscall(thread, type, &kd[i], (double)now);
- case MACH_pageout:
- if (kd[i].arg2)
- exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
- else
- exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
- break;
+ case MACH_pageout:
+ if (kd[i].arg2)
+ exit_syscall("PAGE_OUT_D", 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);
+ 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_CACHE_HIT_FAULT)
+ exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
+ else {
+ if ((ti = find_thread(thread, type))) {
+ destroy_thread(ti);
+ }
+ }
+ continue;
+
+ case MSC_map_fd:
+ exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
+ continue;
+
+ case BSC_mmap_extended:
+ case BSC_mmap_extended2:
+ case BSC_msync_extended:
+ case BSC_pread_extended:
+ case BSC_pwrite_extended:
+ extend_syscall(thread, type, &kd[i]);
+ continue;
+ }
- case MACH_vmfault:
- if (kd[i].arg2 == DBG_PAGEIN_FAULT)
- exit_syscall("PAGE_IN", thread, type, kd[i].arg4, kd[i].arg1, 0, 6, (double)now);
- else if (kd[i].arg2 == DBG_CACHE_HIT_FAULT)
- exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
- else {
- if ((ti = find_thread(thread, type))) {
- if (ti == &th_state[cur_max - 1])
- cur_max--;
- ti->thread = 0;
- }
- }
- break;
+ if ((type & CSC_MASK) == BSC_BASE) {
- case MSC_map_fd:
- exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
+ index = BSC_INDEX(type);
- case BSC_mmap:
- exit_syscall("mmap", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_recvmsg:
- exit_syscall("recvmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
+ if (index >= MAX_BSD_SYSCALL)
+ continue;
- case BSC_sendmsg:
- exit_syscall("sendmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
+ if (bsd_syscalls[index].sc_name == NULL)
+ continue;
- case BSC_recvfrom:
- exit_syscall("recvfrom", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
+ if (type == BSC_execve)
+ execs_in_progress--;
- case BSC_accept:
- exit_syscall("accept", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
-
- case BSC_select:
- exit_syscall("select", thread, type, kd[i].arg1, kd[i].arg2, 0, 8, (double)now);
- break;
-
- case BSC_socket:
- exit_syscall("socket", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
+ exit_syscall(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
+ bsd_syscalls[index].sc_format, (double)now);
- case BSC_connect:
- exit_syscall("connect", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_bind:
- exit_syscall("bind", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_listen:
- exit_syscall("listen", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_sendto:
- exit_syscall("sendto", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_socketpair:
- exit_syscall("socketpair", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_getxattr:
- exit_syscall("getxattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_setxattr:
- exit_syscall("setxattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_removexattr:
- exit_syscall("removexattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_listxattr:
- exit_syscall("listxattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_stat:
- exit_syscall("stat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_stat_extended:
- exit_syscall("stat_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_execve:
- exit_syscall("execve", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_load_shared_file:
- exit_syscall("load_sf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_open:
- exit_syscall("open", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
-
- case BSC_open_extended:
- exit_syscall("open_extended", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
-
- case BSC_dup:
- exit_syscall("dup", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
-
- case BSC_dup2:
- exit_syscall("dup2", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
- break;
-
- case BSC_close:
- exit_syscall("close", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_read:
- exit_syscall("read", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_write:
- exit_syscall("write", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_fgetxattr:
- exit_syscall("fgetxattr", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fsetxattr:
- exit_syscall("fsetxattr", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fremovexattr:
- exit_syscall("fremovexattr", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_flistxattr:
- exit_syscall("flistxattr", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fstat:
- exit_syscall("fstat", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fstat_extended:
- exit_syscall("fstat_extended", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_lstat:
- exit_syscall("lstat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_lstat_extended:
- exit_syscall("lstat_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_link:
- exit_syscall("link", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_unlink:
- exit_syscall("unlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_mknod:
- exit_syscall("mknod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chmod:
- exit_syscall("chmod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chmod_extended:
- exit_syscall("chmod_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chown:
- exit_syscall("chown", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_lchown:
- exit_syscall("lchown", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_access:
- exit_syscall("access", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_access_extended:
- exit_syscall("access_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chdir:
- exit_syscall("chdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chroot:
- exit_syscall("chroot", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_utimes:
- exit_syscall("utimes", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_delete:
- exit_syscall("delete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_undelete:
- exit_syscall("undelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_revoke:
- exit_syscall("revoke", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fsctl:
- exit_syscall("fsctl", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_chflags:
- exit_syscall("chflags", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fchflags:
- exit_syscall("fchflags", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fchdir:
- exit_syscall("fchdir", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_futimes:
- exit_syscall("futimes", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_sync:
- exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_symlink:
- exit_syscall("symlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_readlink:
- exit_syscall("readlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fsync:
- exit_syscall("fsync", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_readv:
- exit_syscall("readv", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_writev:
- exit_syscall("writev", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_pread:
- exit_syscall("pread", thread, type, kd[i].arg1, kd[i].arg2, 1, 9, (double)now);
- break;
-
- case BSC_pwrite:
- exit_syscall("pwrite", thread, type, kd[i].arg1, kd[i].arg2, 1, 9, (double)now);
- break;
-
- case BSC_fchown:
- exit_syscall("fchown", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fchmod:
- exit_syscall("fchmod", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_fchmod_extended:
- exit_syscall("fchmod_extended", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_mkdir:
- exit_syscall("mkdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_mkdir_extended:
- exit_syscall("mkdir_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_mkfifo:
- exit_syscall("mkfifo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_mkfifo_extended:
- exit_syscall("mkfifo_extended", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_rmdir:
- exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_statfs:
- exit_syscall("statfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fstatfs:
- exit_syscall("fstatfs", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_pathconf:
- exit_syscall("pathconf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fpathconf:
- exit_syscall("fpathconf", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_getdirentries:
- exit_syscall("getdirentries", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
- break;
-
- case BSC_lseek:
- exit_syscall("lseek", thread, type, kd[i].arg1, kd[i].arg3, 1, 5, (double)now);
- break;
-
- case BSC_truncate:
- exit_syscall("truncate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_ftruncate:
- exit_syscall("ftruncate", thread, type, kd[i].arg1, kd[i].arg2, 1, 3, (double)now);
- break;
-
- case BSC_statv:
- exit_syscall("statv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_lstatv:
- exit_syscall("lstatv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_fstatv:
- exit_syscall("fstatv", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
- break;
-
- case BSC_mkcomplex:
- exit_syscall("mkcomplex", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_getattrlist:
- exit_syscall("getattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_setattrlist:
- exit_syscall("setattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_getdirentriesattr:
- exit_syscall("getdirentriesattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 1, (double)now);
- break;
-
-
- case BSC_exchangedata:
- exit_syscall("exchangedata", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_rename:
- exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
-
- case BSC_copyfile:
- exit_syscall("copyfile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
+ continue;
+ }
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
+
+ index = filemgr_index(type);
- case BSC_checkuseraccess:
- exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
+ if (index >= MAX_FILEMGR)
+ continue;
- case BSC_searchfs:
- exit_syscall("searchfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
+ if (filemgr_calls[index].fm_name == NULL)
+ continue;
- case FILEMGR_PBGETCATALOGINFO:
- exit_syscall("GetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETCATALOGINFOBULK:
- exit_syscall("GetCatalogInfoBulk", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCREATEFILEUNICODE:
- exit_syscall("CreateFileUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCREATEDIRECTORYUNICODE:
- exit_syscall("CreateDirectoryUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCREATEFORK:
- exit_syscall("PBCreateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBDELETEFORK:
- exit_syscall("PBDeleteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBITERATEFORK:
- exit_syscall("PBIterateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBOPENFORK:
- exit_syscall("PBOpenFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBREADFORK:
- exit_syscall("PBReadFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBWRITEFORK:
- exit_syscall("PBWriteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBALLOCATEFORK:
- exit_syscall("PBAllocateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBDELETEOBJECT:
- exit_syscall("PBDeleteObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBEXCHANGEOBJECT:
- exit_syscall("PBExchangeObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETFORKCBINFO:
- exit_syscall("PBGetForkCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETVOLUMEINFO:
- exit_syscall("PBGetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBMAKEFSREF:
- exit_syscall("PBMakeFSRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBMAKEFSREFUNICODE:
- exit_syscall("PBMakeFSRefUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBMOVEOBJECT:
- exit_syscall("PBMoveObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBOPENITERATOR:
- exit_syscall("PBOpenIterator", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBRENAMEUNICODE:
- exit_syscall("PBRenameUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETCATALOGINFO:
- exit_syscall("PBSetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETVOLUMEINFO:
- exit_syscall("PBSetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_FSREFMAKEPATH:
- exit_syscall("FSRefMakePath", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_FSPATHMAKEREF:
- exit_syscall("FSPathMakeRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETCATINFO:
- exit_syscall("GetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETCATINFOLITE:
- exit_syscall("GetCatInfoLite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHGETFINFO:
- exit_syscall("PBHGetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBXGETVOLINFO:
- exit_syscall("PBXGetVolInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHCREATE:
- exit_syscall("PBHCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHOPENDF:
- exit_syscall("PBHOpenDF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHOPENRF:
- exit_syscall("PBHOpenRF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHGETDIRACCESS:
- exit_syscall("PBHGetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHSETDIRACCESS:
- exit_syscall("PBHSetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHMAPID:
- exit_syscall("PBHMapID", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHMAPNAME:
- exit_syscall("PBHMapName", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCLOSE:
- exit_syscall("PBClose", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBFLUSHFILE:
- exit_syscall("PBFlushFile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETEOF:
- exit_syscall("PBGetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETEOF:
- exit_syscall("PBSetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETFPOS:
- exit_syscall("PBGetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBREAD:
- exit_syscall("PBRead", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBWRITE:
- exit_syscall("PBWrite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETFCBINFO:
- exit_syscall("PBGetFCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETFINFO:
- exit_syscall("PBSetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBALLOCATE:
- exit_syscall("PBAllocate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBALLOCCONTIG:
- exit_syscall("PBAllocContig", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETFPOS:
- exit_syscall("PBSetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETCATINFO:
- exit_syscall("PBSetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBGETVOLPARMS:
- exit_syscall("PBGetVolParms", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBSETVINFO:
- exit_syscall("PBSetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBMAKEFSSPEC:
- exit_syscall("PBMakeFSSpec", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHGETVINFO:
- exit_syscall("PBHGetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCREATEFILEIDREF:
- exit_syscall("PBCreateFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBDELETEFILEIDREF:
- exit_syscall("PBDeleteFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBRESOLVEFILEIDREF:
- exit_syscall("PBResolveFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBFLUSHVOL:
- exit_syscall("PBFlushVol", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHRENAME:
- exit_syscall("PBHRename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCATMOVE:
- exit_syscall("PBCatMove", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBEXCHANGEFILES:
- exit_syscall("PBExchangeFiles", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHDELETE:
- exit_syscall("PBHDelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBDIRCREATE:
- exit_syscall("PBDirCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBCATSEARCH:
- exit_syscall("PBCatSearch", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHSETFLOCK:
- exit_syscall("PBHSetFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBHRSTFLOCK:
- exit_syscall("PBHRstFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBLOCKRANGE:
- exit_syscall("PBLockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- case FILEMGR_PBUNLOCKRANGE:
- exit_syscall("PBUnlockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
- break;
- default:
- break;
+ exit_syscall(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
+ FMT_DEFAULT, (double)now);
}
}
fflush(0);
}
+
+
+
void
-enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now)
{
struct th_info *ti;
- int i;
int secs;
int usecs;
long long l_usecs;
int argsclen = 0;
char buf[MAXWIDTH];
- switch (type) {
-
- case MACH_pageout:
- case MACH_vmfault:
- case MSC_map_fd:
- case BSC_mmap:
- case BSC_recvmsg:
- case BSC_sendmsg:
- case BSC_recvfrom:
- case BSC_accept:
- case BSC_select:
- case BSC_socket:
- case BSC_connect:
- case BSC_bind:
- case BSC_listen:
- case BSC_sendto:
- case BSC_socketpair:
- case BSC_execve:
- case BSC_getxattr:
- case BSC_fgetxattr:
- case BSC_setxattr:
- case BSC_fsetxattr:
- case BSC_removexattr:
- case BSC_fremovexattr:
- case BSC_listxattr:
- case BSC_flistxattr:
- case BSC_open_extended:
- case BSC_stat_extended:
- case BSC_lstat_extended:
- case BSC_fstat_extended:
- case BSC_chmod_extended:
- case BSC_fchmod_extended:
- case BSC_access_extended:
- case BSC_mkfifo_extended:
- case BSC_mkdir_extended:
- case BSC_stat:
- case BSC_load_shared_file:
- case BSC_open:
- case BSC_dup:
- case BSC_dup2:
- case BSC_close:
- case BSC_read:
- case BSC_write:
- case BSC_fstat:
- case BSC_lstat:
- case BSC_link:
- case BSC_unlink:
- case BSC_mknod:
- case BSC_chmod:
- case BSC_chown:
- case BSC_lchown:
- case BSC_access:
- case BSC_chflags:
- case BSC_fchflags:
- case BSC_fchdir:
- case BSC_futimes:
- case BSC_chdir:
- case BSC_utimes:
- case BSC_chroot:
- case BSC_undelete:
- case BSC_delete:
- case BSC_revoke:
- case BSC_fsctl:
- case BSC_copyfile:
- case BSC_sync:
- case BSC_symlink:
- case BSC_readlink:
- case BSC_fsync:
- case BSC_readv:
- case BSC_writev:
- case BSC_pread:
- case BSC_pwrite:
- case BSC_fchown:
- case BSC_fchmod:
- case BSC_rename:
- case BSC_mkdir:
- case BSC_mkfifo:
- case BSC_rmdir:
- case BSC_statfs:
- case BSC_fstatfs:
- case BSC_pathconf:
- case BSC_fpathconf:
- case BSC_getdirentries:
- case BSC_lseek:
- case BSC_truncate:
- case BSC_ftruncate:
- case BSC_statv:
- case BSC_lstatv:
- case BSC_fstatv:
- case BSC_mkcomplex:
- case BSC_getattrlist:
- case BSC_setattrlist:
- case BSC_getdirentriesattr:
- case BSC_exchangedata:
- case BSC_checkuseraccess:
- case BSC_searchfs:
- case FILEMGR_PBGETCATALOGINFO:
- case FILEMGR_PBGETCATALOGINFOBULK:
- case FILEMGR_PBCREATEFILEUNICODE:
- case FILEMGR_PBCREATEDIRECTORYUNICODE:
- case FILEMGR_PBCREATEFORK:
- case FILEMGR_PBDELETEFORK:
- case FILEMGR_PBITERATEFORK:
- case FILEMGR_PBOPENFORK:
- case FILEMGR_PBREADFORK:
- case FILEMGR_PBWRITEFORK:
- case FILEMGR_PBALLOCATEFORK:
- case FILEMGR_PBDELETEOBJECT:
- case FILEMGR_PBEXCHANGEOBJECT:
- case FILEMGR_PBGETFORKCBINFO:
- case FILEMGR_PBGETVOLUMEINFO:
- case FILEMGR_PBMAKEFSREF:
- case FILEMGR_PBMAKEFSREFUNICODE:
- case FILEMGR_PBMOVEOBJECT:
- case FILEMGR_PBOPENITERATOR:
- case FILEMGR_PBRENAMEUNICODE:
- case FILEMGR_PBSETCATALOGINFO:
- case FILEMGR_PBSETVOLUMEINFO:
- case FILEMGR_FSREFMAKEPATH:
- case FILEMGR_FSPATHMAKEREF:
-
- case FILEMGR_PBGETCATINFO:
- case FILEMGR_PBGETCATINFOLITE:
- case FILEMGR_PBHGETFINFO:
- case FILEMGR_PBXGETVOLINFO:
- case FILEMGR_PBHCREATE:
- case FILEMGR_PBHOPENDF:
- case FILEMGR_PBHOPENRF:
- case FILEMGR_PBHGETDIRACCESS:
- case FILEMGR_PBHSETDIRACCESS:
- case FILEMGR_PBHMAPID:
- case FILEMGR_PBHMAPNAME:
- case FILEMGR_PBCLOSE:
- case FILEMGR_PBFLUSHFILE:
- case FILEMGR_PBGETEOF:
- case FILEMGR_PBSETEOF:
- case FILEMGR_PBGETFPOS:
- case FILEMGR_PBREAD:
- case FILEMGR_PBWRITE:
- case FILEMGR_PBGETFCBINFO:
- case FILEMGR_PBSETFINFO:
- case FILEMGR_PBALLOCATE:
- case FILEMGR_PBALLOCCONTIG:
- case FILEMGR_PBSETFPOS:
- case FILEMGR_PBSETCATINFO:
- case FILEMGR_PBGETVOLPARMS:
- case FILEMGR_PBSETVINFO:
- case FILEMGR_PBMAKEFSSPEC:
- case FILEMGR_PBHGETVINFO:
- case FILEMGR_PBCREATEFILEIDREF:
- case FILEMGR_PBDELETEFILEIDREF:
- case FILEMGR_PBRESOLVEFILEIDREF:
- case FILEMGR_PBFLUSHVOL:
- case FILEMGR_PBHRENAME:
- case FILEMGR_PBCATMOVE:
- case FILEMGR_PBEXCHANGEFILES:
- case FILEMGR_PBHDELETE:
- case FILEMGR_PBDIRCREATE:
- case FILEMGR_PBCATSEARCH:
- case FILEMGR_PBHSETFLOCK:
- case FILEMGR_PBHRSTFLOCK:
- case FILEMGR_PBLOCKRANGE:
- case FILEMGR_PBUNLOCKRANGE:
-
- if ((ti = find_thread(thread, BSC_execve))) {
- if (ti->pathptr) {
- exit_syscall("execve", thread, BSC_execve, 0, 0, 0, 0, (double)now);
- }
- }
- for (i = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, i++) {
- if (ti->thread == 0)
- break;
- }
- if (ti == &th_state[MAX_THREADS])
- return;
- if (i >= cur_max)
- cur_max = i + 1;
+ if (execs_in_progress) {
+ if ((ti = find_thread(thread, BSC_execve))) {
+ if (ti->pathptr) {
+ exit_syscall("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
+ execs_in_progress--;
+ }
+ }
+ }
+ if ((ti = find_empty()) == NULL)
+ return;
- if ((type >> 24) == FILEMGR_CLASS) {
- ti->in_filemgr = 1;
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
+
+ filemgr_in_progress++;
+ ti->in_filemgr = 1;
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = bias_secs + secs;
+ l_usecs = (long long)(now / divisor);
+ secs = l_usecs / 1000000;
+ curr_time = bias_secs + secs;
- sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
- tsclen = strlen(buf);
+ sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
+ tsclen = strlen(buf);
- if (columns > MAXCOLS || wideflag) {
- usecs = l_usecs - (long long)((long long)secs * 1000000);
- sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
- tsclen = strlen(buf);
- }
+ if (columns > MAXCOLS || wideflag) {
+ usecs = l_usecs - (long long)((long long)secs * 1000000);
+ sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
+ tsclen = strlen(buf);
+ }
- /* Print timestamp column */
- printf("%s", buf);
+ /*
+ * Print timestamp column
+ */
+ printf("%s", buf);
- map = find_thread_map(thread);
- if (map) {
+ map = find_thread_map(thread);
+ if (map) {
sprintf(buf, " %-25.25s ", name);
nmclen = strlen(buf);
printf("%s", buf);
argsclen = strlen(buf);
/*
- Calculate white space out to command
- */
+ * Calculate white space out to command
+ */
+ if (columns > MAXCOLS || wideflag) {
+ clen = columns - (tsclen + nmclen + argsclen + 20);
+ } else
+ clen = columns - (tsclen + nmclen + argsclen + 12);
+
+ if (clen > 0) {
+ printf("%s", buf); /* print the kdargs */
+ memset(buf, ' ', clen);
+ buf[clen] = '\0';
+ printf("%s", buf);
+ }
+ else if ((argsclen + clen) > 0) {
+ /*
+ * no room so wipe out the kdargs
+ */
+ memset(buf, ' ', (argsclen + clen));
+ buf[argsclen + clen] = '\0';
+ printf("%s", buf);
+ }
if (columns > MAXCOLS || wideflag)
- {
- clen = columns - (tsclen + nmclen + argsclen + 20);
- }
+ printf("%-20.20s\n", map->command);
else
- clen = columns - (tsclen + nmclen + argsclen + 12);
-
- if(clen > 0)
- {
- printf("%s", buf); /* print the kdargs */
- memset(buf, ' ', clen);
- buf[clen] = '\0';
- printf("%s", buf);
- }
- else if ((argsclen + clen) > 0)
- {
- /* no room so wipe out the kdargs */
- memset(buf, ' ', (argsclen + clen));
- buf[argsclen + clen] = '\0';
- printf("%s", buf);
- }
+ 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);
+ }
+ ti->thread = thread;
+ ti->waited = 0;
+ ti->type = type;
+ ti->stime = now;
+ ti->arg1 = kd->arg1;
+ ti->arg2 = kd->arg2;
+ ti->arg3 = kd->arg3;
+ ti->arg4 = kd->arg4;
+ ti->pathptr = (long *)NULL;
+ ti->pathname[0] = 0;
+}
- if (columns > MAXCOLS || wideflag)
- printf("%-20.20s\n", map->command);
- 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);
- } else {
- ti->in_filemgr = 0;
- }
- ti->thread = thread;
- ti->waited = 0;
- ti->type = type;
- ti->stime = now;
- ti->arg1 = kd->arg1;
- ti->arg2 = kd->arg2;
- ti->arg3 = kd->arg3;
- ti->arg4 = kd->arg4;
- ti->pathptr = (long *)NULL;
- ti->pathname[0] = 0;
- break;
- default:
- break;
+void
+enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+{
+ int index;
+
+ if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd) {
+ enter_syscall_now(thread, type, kd, name, now);
+ return;
+ }
+ if ((type & CSC_MASK) == BSC_BASE) {
+
+ index = BSC_INDEX(type);
+
+ if (index >= MAX_BSD_SYSCALL)
+ return;
+
+ if (type == BSC_execve)
+ execs_in_progress++;
+
+ if (bsd_syscalls[index].sc_name)
+ enter_syscall_now(thread, type, kd, name, now);
+
+ return;
+ }
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
+
+ index = filemgr_index(type);
+
+ if (index >= MAX_FILEMGR)
+ return;
+
+ if (filemgr_calls[index].fm_name)
+ enter_syscall_now(thread, type, kd, name, now);
}
- fflush (0);
}
/*
*/
void
-extend_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+extend_syscall(int thread, int type, kd_buf *kd)
{
struct th_info *ti;
switch (type) {
+ case BSC_mmap_extended:
+ if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
+ return;
+ ti->arg8 = ti->arg3; /* save protection */
+ ti->arg1 = kd->arg1; /* the fd */
+ ti->arg3 = kd->arg2; /* bottom half address */
+ ti->arg5 = kd->arg3; /* bottom half size */
+ break;
+ case BSC_mmap_extended2:
+ if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
+ return;
+ ti->arg2 = kd->arg1; /* top half address */
+ ti->arg4 = kd->arg2; /* top half size */
+ ti->arg6 = kd->arg3; /* top half file offset */
+ ti->arg7 = kd->arg4; /* bottom half file offset */
+ break;
+ case BSC_msync_extended:
+ if ((ti = find_thread(thread, BSC_msync)) == (struct th_info *)0) {
+ if ((ti = find_thread(thread, BSC_msync_nocancel)) == (struct th_info *)0)
+ return;
+ }
+ ti->arg4 = kd->arg1; /* top half address */
+ ti->arg5 = kd->arg2; /* top half size */
+ break;
case BSC_pread_extended:
- if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0)
- return;
+ if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0) {
+ if ((ti = find_thread(thread, BSC_pread_nocancel)) == (struct th_info *)0)
+ return;
+ }
ti->arg1 = kd->arg1; /* the fd */
ti->arg2 = kd->arg2; /* nbytes */
ti->arg3 = kd->arg3; /* top half offset */
ti->arg4 = kd->arg4; /* bottom half offset */
break;
case BSC_pwrite_extended:
- if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0)
- return;
+ if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0) {
+ if ((ti = find_thread(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
+ return;
+ }
ti->arg1 = kd->arg1; /* the fd */
ti->arg2 = kd->arg2; /* nbytes */
ti->arg3 = kd->arg3; /* top half offset */
}
}
+
void
-exit_syscall(char *sc_name, int thread, int type, int error, int retval,
- int has_fd, int has_ret, double now)
+exit_syscall(char *sc_name, int thread, int type, int arg1, int arg2, int arg3, int arg4,
+ int format, double now)
{
- struct th_info *ti;
+ struct th_info *ti;
- if ((ti = find_thread(thread, type)) == (struct th_info *)0)
- return;
+ if ((ti = find_thread(thread, type)) == (struct th_info *)0)
+ return;
+
+ if (check_filter_mode(ti, type, arg1, arg2, sc_name))
+ format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)ti->pathname, NULL);
- if (check_filter_mode(ti, type, error, retval, sc_name))
- format_print(ti, sc_name, thread, type, error, retval, has_fd, has_ret, now, ti->stime, ti->waited, (char *)ti->pathname, NULL);
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
+ ti->in_filemgr = 0;
- if (ti == &th_state[cur_max - 1])
- cur_max--;
- ti->thread = 0;
+ if (filemgr_in_progress > 0)
+ filemgr_in_progress--;
+ }
+ destroy_thread(ti);
}
+void
+get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off)
+{
+ if (smode & 04)
+ buf[0] = 'r';
+ if (smode & 02)
+ buf[1] = 'w';
+ if (smode & 01) {
+ if (special)
+ buf[2] = x_on;
+ else
+ buf[2] = 'x';
+ } else {
+ if (special)
+ buf[2] = x_off;
+ }
+}
+
void
-format_print(struct th_info *ti, char *sc_name, int thread, int type, int error, int retval,
- int has_fd, int has_ret, double now, double stime, int waited, char *pathname, struct diskio *dio)
+get_mode_string(int mode, char *buf)
{
- int secs;
- int usecs;
- int nopadding;
- long long l_usecs;
- long curr_time;
- char *command_name;
- kd_threadmap *map;
- kd_threadmap *find_thread_map();
- int len = 0;
- int clen = 0;
- char *framework_name;
- char buf[MAXWIDTH];
-
- command_name = "";
-
- if (dio)
- command_name = dio->issuing_command;
- else {
- if ((map = find_thread_map(thread)))
- command_name = map->command;
- }
-
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = bias_secs + secs;
- sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
- clen = strlen(buf);
-
- if (columns > MAXCOLS || wideflag) {
- nopadding = 0;
- usecs = l_usecs - (long long)((long long)secs * 1000000);
- sprintf(&buf[clen], ".%03ld", (long)usecs / 1000);
- clen = strlen(buf);
-
- if ((type >> 24) != FILEMGR_CLASS) {
- if (find_thread(thread, -1)) {
- sprintf(&buf[clen], " ");
- clen = strlen(buf);
- nopadding = 1;
- }
- }
- } else
- nopadding = 1;
+ memset(buf, '-', 9);
+ buf[9] = '\0';
+
+ get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T');
+ get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S');
+ get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S');
+}
+
+
+int clip_64bit(char *s, uint64_t value)
+{
+ int clen = 0;
+
+ if ( (value & 0xff00000000000000LL) )
+ clen = printf("%s0x%16.16qx", s, value);
+ else if ( (value & 0x00ff000000000000LL) )
+ clen = printf("%s0x%14.14qx ", s, value);
+ else if ( (value & 0x0000ff0000000000LL) )
+ clen = printf("%s0x%12.12qx ", s, value);
+ else if ( (value & 0x000000ff00000000LL) )
+ clen = printf("%s0x%10.10qx ", s, value);
+ else
+ clen = printf("%s0x%8.8qx ", s, value);
+
+ return (clen);
+}
+
+
+void
+format_print(struct th_info *ti, char *sc_name, int 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;
+ int usecs;
+ int nopadding = 0;
+ long long l_usecs;
+ long curr_time;
+ char *command_name;
+ kd_threadmap *map;
+ kd_threadmap *find_thread_map();
+ int in_filemgr = 0;
+ int len = 0;
+ int clen = 0;
+ int tlen = 0;
+ int class;
+ uint64_t user_addr;
+ uint64_t user_size;
+ char *framework_name;
+ 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 timestamp_len = 0;
+ static int last_msec = 0;
+
+
+ class = type >> 24;
+
+ if (dio)
+ command_name = dio->issuing_command;
+ else {
+ if (map_is_the_same && thread == last_thread)
+ map = last_map;
+ else {
+ if ((map = find_thread_map(thread))) {
+ last_map = map;
+ last_thread = thread;
+ map_is_the_same = 1;
+ }
+ }
+ 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;
+ need_msec_update = 1;
+ }
+ if (columns > MAXCOLS || wideflag) {
+ int msec;
- if (((type >> 24) == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
- sprintf(&buf[clen], " %-18.18s", sc_name);
- else
- sprintf(&buf[clen], " %-15.15s", sc_name);
+ tlen = timestamp_len;
+ nopadding = 0;
+ msec = (l_usecs - (long long)((long long)secs * 1000000)) / 1000;
- clen = strlen(buf);
+ if (msec != last_msec || need_msec_update) {
+ sprintf(×tamp[tlen], ".%03ld", (long)msec);
+ last_msec = msec;
+ }
+ tlen += 4;
+
+ timestamp[tlen] = '\0';
+
+ if (filemgr_in_progress) {
+ if (class != FILEMGR_CLASS) {
+ if (find_thread(thread, -1)) {
+ in_filemgr = 1;
+ }
+ }
+ }
+ } else
+ nopadding = 1;
+
+ if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
+ clen = printf("%s %-20.20s", timestamp, sc_name);
+ else if (in_filemgr)
+ clen = printf("%s %-15.15s", timestamp, sc_name);
+ else
+ clen = printf("%s %-17.17s", timestamp, sc_name);
- framework_name = (char *)0;
-
- if (columns > MAXCOLS || wideflag) {
- if (has_ret == 7) {
- sprintf(&buf[clen], " D=0x%8.8x", dio->blkno);
-
- clen = strlen(buf);
-
- if (dio->io_errno)
- sprintf(&buf[clen], " [%3d] ", dio->io_errno);
- else
- sprintf(&buf[clen], " B=0x%-6x /dev/%s", dio->iosize, find_disk_name(dio->dev));
- } else {
+ framework_name = (char *)0;
+
+ if (columns > MAXCOLS || wideflag) {
- off_t offset_reassembled = 0LL;
+ off_t offset_reassembled = 0LL;
- if (has_fd == 2 && error == 0)
- sprintf(&buf[clen], " F=%-3d", retval);
- else if (has_fd == 1)
- sprintf(&buf[clen], " F=%-3d", ti->arg1);
- else if (has_ret != 2 && has_ret != 6)
- sprintf(&buf[clen], " ");
-
- clen = strlen(buf);
-
- if (has_ret == 2 || has_ret == 6)
- framework_name = lookup_name(retval);
-
- if (error && has_ret != 6)
- sprintf(&buf[clen], "[%3d] ", error);
- else if (has_ret == 3)
- sprintf(&buf[clen], "O=0x%8.8x", ti->arg3);
- else if (has_ret == 5)
- sprintf(&buf[clen], "O=0x%8.8x", retval);
- else if (has_ret == 2)
- sprintf(&buf[clen], " A=0x%8.8x ", retval);
- else if (has_ret == 6)
- sprintf(&buf[clen], " A=0x%8.8x B=0x%-8x", retval, error);
- else if (has_ret == 1)
- sprintf(&buf[clen], " B=0x%-6x", retval);
- else if (has_ret == 4)
- sprintf(&buf[clen], "B=0x%-8x", retval);
- else if (has_ret == 8) /* BSC_select */
- sprintf(&buf[clen], " S=%-3d ", retval);
- else if (has_ret == 9) /* BSC_pread, BSC_pwrite */
- {
- sprintf(&buf[clen], "B=0x%-8x", retval);
- clen = strlen(buf);
- offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
- if ((offset_reassembled >> 32) != 0)
- sprintf(&buf[clen], "O=0x%16.16qx", (off_t)offset_reassembled);
- else
- sprintf(&buf[clen], "O=0x%8.8qx", (off_t)offset_reassembled);
- }
- else
- sprintf(&buf[clen], " ");
- }
- clen = strlen(buf);
- }
- printf("%s", buf);
-
- /*
- Calculate space available to print pathname
- */
- if (columns > MAXCOLS || wideflag)
- clen = columns - (clen + 13 + 20);
- else
- clen = columns - (clen + 13 + 12);
-
- if ((type >> 24) != FILEMGR_CLASS && !nopadding)
- clen -= 3;
-
- if (framework_name)
- sprintf(&buf[0], " %s ", framework_name);
- else
- sprintf(&buf[0], " %s ", pathname);
- len = strlen(buf);
-
- if (clen > len)
- {
- /*
- Add null padding if column length
- is wider than the pathname length.
- */
- memset(&buf[len], ' ', clen - len);
- buf[clen] = '\0';
- printf("%s", buf);
- }
- else if (clen == len)
- {
- printf("%s", buf);
- }
- else if ((clen > 0) && (clen < len))
- {
- /* This prints the tail end of the pathname */
- buf[len-clen] = ' ';
- printf("%s", &buf[len - clen]);
- }
-
- usecs = (unsigned long)((now - stime) / divisor);
- secs = usecs / 1000000;
- usecs -= secs * 1000000;
-
- if ((type >> 24) != FILEMGR_CLASS && !nopadding)
- printf(" ");
+ switch (format) {
+
+ case FMT_DEFAULT:
+ /*
+ * pathname based system calls or
+ * calls with no fd or pathname (i.e. sync)
+ */
+ if (arg1)
+ clen += printf(" [%3d] ", arg1);
+ else
+ clen += printf(" ");
+ break;
+
+ case FMT_FD:
+ /*
+ * fd based system call... no I/O
+ */
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d", ti->arg1);
+ break;
+
+ case FMT_FD_2:
+ /*
+ * accept, dup, dup2
+ */
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d F=%-3d", ti->arg1, arg2);
+ break;
+
+ case FMT_FD_IO:
+ /*
+ * system calls with fd's that return an I/O completion count
+ */
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d B=0x%-6x", ti->arg1, arg2);
+ break;
+
+ case FMT_PGIN:
+ /*
+ * pagein
+ */
+ user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
+ framework_name = lookup_name(user_addr);
+ clen += clip_64bit(" A=", user_addr);
+ break;
+
+ case FMT_CACHEHIT:
+ /*
+ * cache hit
+ */
+ user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
+
+ framework_name = lookup_name(user_addr);
+ clen += clip_64bit(" A=", user_addr);
+ break;
+
+ case FMT_PGOUT:
+ /*
+ * pageout
+ */
+ clen += printf(" B=0x%-8x", arg2);
+ break;
+
+ case FMT_DISKIO:
+ /*
+ * physical disk I/O
+ */
+ if (dio->io_errno)
+ clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
+ else
+ clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, find_disk_name(dio->dev));
+ break;
+
+ case FMT_MSYNC:
+ {
+ /*
+ * msync
+ */
+ int mlen = 0;
+
+ buf[0] = '\0';
+
+ if (ti->arg3 & MS_ASYNC)
+ mlen += sprintf(&buf[mlen], "MS_ASYNC | ");
+ else
+ mlen += sprintf(&buf[mlen], "MS_SYNC | ");
+
+ if (ti->arg3 & MS_INVALIDATE)
+ mlen += sprintf(&buf[mlen], "MS_INVALIDATE | ");
+ if (ti->arg3 & MS_KILLPAGES)
+ mlen += sprintf(&buf[mlen], "MS_KILLPAGES | ");
+ if (ti->arg3 & MS_DEACTIVATE)
+ mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | ");
+
+ if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE))
+ mlen += sprintf(&buf[mlen], "UNKNOWN | ");
+
+ if (mlen)
+ buf[mlen - 3] = '\0';
+
+ if (arg1)
+ clen += printf(" [%3d]", arg1);
+
+ user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1);
+ clen += clip_64bit(" A=", user_addr);
+
+ user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2);
+
+ clen += printf(" B=0x%-16qx <%s>", user_size, buf);
+
+ break;
+ }
+
+ case FMT_FCNTL:
+ {
+ /*
+ * fcntl
+ */
+ char *p = NULL;
+
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d", ti->arg1);
+
+ switch(ti->arg2) {
+
+ case F_DUPFD:
+ p = "DUPFD";
+ break;
+
+ case F_GETFD:
+ p = "GETFD";
+ break;
+
+ case F_SETFD:
+ p = "SETFD";
+ break;
+
+ case F_GETFL:
+ p = "GETFL";
+ break;
+
+ case F_SETFL:
+ p = "SETFL";
+ break;
+
+ case F_GETOWN:
+ p = "GETOWN";
+ break;
+
+ case F_SETOWN:
+ p = "SETOWN";
+ break;
+
+ case F_GETLK:
+ p = "GETLK";
+ break;
+
+ case F_SETLK:
+ p = "SETLK";
+ break;
+
+ case F_SETLKW:
+ p = "SETLKW";
+ break;
+
+ case F_PREALLOCATE:
+ p = "PREALLOCATE";
+ break;
+
+ case F_SETSIZE:
+ p = "SETSIZE";
+ break;
+
+ case F_RDADVISE:
+ p = "RDADVISE";
+ break;
+
+ case F_GETPATH:
+ p = "GETPATH";
+ break;
+
+ case F_FULLFSYNC:
+ p = "FULLFSYNC";
+ break;
+
+ case F_PATHPKG_CHECK:
+ p = "PATHPKG_CHECK";
+ break;
+
+ case F_NOCACHE:
+ if (ti->arg3)
+ p = "CACHING OFF";
+ else
+ p = "CACHING ON";
+ break;
+
+ }
+ if (p)
+ clen += printf(" <%s>", p);
+ else
+ clen += printf(" <CMD=%d>", ti->arg2);
+
+ break;
+ }
+
+ case FMT_IOCTL:
+ {
+ /*
+ * fcntl
+ */
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d", ti->arg1);
+
+ clen += printf(" <CMD=0x%x>", ti->arg2);
+
+ break;
+ }
+
+ case FMT_SELECT:
+ /*
+ * select
+ */
+ if (arg1)
+ clen += printf(" [%3d]", arg1);
+ else
+ clen += printf(" S=%-3d", arg2);
+
+ break;
+
+ case FMT_LSEEK:
+ case FMT_PREAD:
+ /*
+ * pread, pwrite, lseek
+ */
+ clen += printf(" F=%-3d", ti->arg1);
+
+ if (arg1)
+ clen += printf("[%3d] ", arg1);
+ else {
+ if (format == FMT_PREAD)
+ clen += printf(" B=0x%-8x ", arg2);
+ else
+ clen += printf(" ");
+ }
+ if (format == FMT_PREAD)
+ offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
+ else
+#ifdef __ppc__
+ offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3);
+#else
+ offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2);
+#endif
+ clen += clip_64bit("O=", offset_reassembled);
+
+ if (format == FMT_LSEEK) {
+ char *mode;
+
+ if (ti->arg4 == SEEK_SET)
+ mode = "SEEK_SET";
+ else if (ti->arg4 == SEEK_CUR)
+ mode = "SEEK_CUR";
+ else if (ti->arg4 == SEEK_END)
+ mode = "SEEK_END";
+ else
+ mode = "UNKNOWN";
+
+ clen += printf(" <%s>", mode);
+ }
+ break;
+
+ case FMT_MMAP:
+ /*
+ * mmap
+ */
+ clen += printf(" F=%-3d ", ti->arg1);
+
+ if (arg1)
+ clen += printf("[%3d] ", arg1);
+ else {
+
+ user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
+
+ clen += clip_64bit("A=", user_addr);
+
+ offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7);
+
+ clen += clip_64bit("O=", offset_reassembled);
+
+ user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5);
+
+ clen += printf("B=0x%-16qx", user_size);
+
+ clen += printf(" <");
+
+ if (ti->arg8 & PROT_READ)
+ clen += printf("READ");
+
+ if (ti->arg8 & PROT_WRITE)
+ clen += printf("|WRITE");
+
+ if (ti->arg8 & PROT_EXEC)
+ clen += printf("|EXEC");
+
+ clen += printf(">");
+ }
+ break;
+
+ case FMT_TRUNC:
+ case FMT_FTRUNC:
+ /*
+ * ftruncate, truncate
+ */
+ if (format == FMT_FTRUNC)
+ clen += printf(" F=%-3d", ti->arg1);
+ else
+ clen += printf(" ");
+
+ if (arg1)
+ clen += printf("[%3d]", arg1);
+
+#ifdef __ppc__
+ offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
+#else
+ offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2);
+#endif
+ clen += clip_64bit(" O=", offset_reassembled);
+
+ nopadding = 1;
+ break;
+
+ case FMT_FCHFLAGS:
+ case FMT_CHFLAGS:
+ {
+ /*
+ * fchflags, chflags
+ */
+ int mlen = 0;
+
+ if (format == FMT_FCHFLAGS) {
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d", ti->arg1);
+ } else {
+ if (arg1)
+ clen += printf(" [%3d] ", arg1);
+ }
+ buf[mlen++] = ' ';
+ buf[mlen++] = '<';
+
+ if (ti->arg2 & UF_NODUMP)
+ mlen += sprintf(&buf[mlen], "UF_NODUMP | ");
+ if (ti->arg2 & UF_IMMUTABLE)
+ mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | ");
+ if (ti->arg2 & UF_APPEND)
+ mlen += sprintf(&buf[mlen], "UF_APPEND | ");
+ if (ti->arg2 & UF_OPAQUE)
+ mlen += sprintf(&buf[mlen], "UF_OPAQUE | ");
+ if (ti->arg2 & SF_ARCHIVED)
+ mlen += sprintf(&buf[mlen], "SF_ARCHIVED | ");
+ if (ti->arg2 & SF_IMMUTABLE)
+ mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | ");
+ if (ti->arg2 & SF_APPEND)
+ mlen += sprintf(&buf[mlen], "SF_APPEND | ");
+
+ if (ti->arg2 == 0)
+ mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | ");
+ else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND))
+ mlen += sprintf(&buf[mlen], "UNKNOWN | ");
+
+ if (mlen >= 3)
+ mlen -= 3;
+
+ buf[mlen++] = '>';
+ buf[mlen] = '\0';
+
+ if (mlen < 21) {
+ memset(&buf[mlen], ' ', 21 - mlen);
+ mlen = 21;
+ }
+ clen += printf("%s", buf);
+
+ nopadding = 1;
+ break;
+ }
+
+ case FMT_FCHMOD:
+ case FMT_FCHMOD_EXT:
+ case FMT_CHMOD:
+ case FMT_CHMOD_EXT:
+ {
+ /*
+ * fchmod, fchmod_extended, chmod, chmod_extended
+ */
+ int mode;
+
+ if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) {
+ if (arg1)
+ clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d ", ti->arg1);
+ } else {
+ if (arg1)
+ clen += printf(" [%3d] ", arg1);
+ else
+ clen += printf(" ");
+ }
+ if (format == FMT_FCHMOD || format == FMT_CHMOD)
+ mode = ti->arg2;
+ else
+ mode = ti->arg4;
+
+ get_mode_string(mode, &buf[0]);
+
+ if (arg1 == 0)
+ clen += printf("<%s> ", buf);
+ else
+ clen += printf("<%s>", buf);
+ break;
+ }
+
+ case FMT_ACCESS:
+ {
+ /*
+ * access
+ */
+ char mode[4];
+
+ memset(mode, '_', 4);
+ mode[4] = '\0';
+
+ if (ti->arg2 & R_OK)
+ mode[0] = 'R';
+ if (ti->arg2 & W_OK)
+ mode[1] = 'W';
+ if (ti->arg2 & X_OK)
+ mode[2] = 'X';
+ if (ti->arg2 == F_OK)
+ mode[3] = 'F';
+
+ if (arg1)
+ clen += printf(" [%3d] (%s) ", arg1, mode);
+ else
+ clen += printf(" (%s) ", mode);
+
+ nopadding = 1;
+ break;
+ }
+
+ case FMT_OPEN:
+ {
+ /*
+ * open
+ */
+ char mode[7];
+
+ memset(mode, '_', 6);
+ mode[6] = '\0';
+
+ if (ti->arg2 & O_RDWR) {
+ mode[0] = 'R';
+ mode[1] = 'W';
+ } else if (ti->arg2 & O_WRONLY)
+ mode[1] = 'W';
+ else
+ mode[0] = 'R';
+
+ if (ti->arg2 & O_CREAT)
+ mode[2] = 'C';
+
+ if (ti->arg2 & O_APPEND)
+ mode[3] = 'A';
+
+ if (ti->arg2 & O_TRUNC)
+ mode[4] = 'T';
+
+ if (ti->arg2 & O_EXCL)
+ mode[5] = 'E';
+
+ if (arg1)
+ clen += printf(" [%3d] (%s) ", arg1, mode);
+ else
+ clen += printf(" F=%-3d (%s) ", arg2, mode);
+
+ nopadding = 1;
+ break;
+ }
+
+ case FMT_SOCKET:
+ {
+ /*
+ * socket
+ *
+ */
+ char *domain;
+ char *type;
+
+ switch (ti->arg1) {
+
+ case AF_UNIX:
+ domain = "AF_UNIX";
+ break;
+
+ case AF_INET:
+ domain = "AF_INET";
+ break;
+
+ case AF_ISO:
+ domain = "AF_ISO";
+ break;
+
+ case AF_NS:
+ domain = "AF_NS";
+ break;
+
+ case AF_IMPLINK:
+ domain = "AF_IMPLINK";
+ break;
+
+ default:
+ domain = "UNKNOWN";
+ break;
+ }
+
+ switch (ti->arg2) {
+
+ case SOCK_STREAM:
+ type = "SOCK_STREAM";
+ break;
+
+ case SOCK_DGRAM:
+ type = "SOCK_DGRAM";
+ break;
+
+ case SOCK_RAW:
+ type = "SOCK_RAW";
+ break;
+
+ case SOCK_SEQPACKET:
+ type = "SOCK_SEQPACKET";
+ break;
+
+ case SOCK_RDM:
+ type = "SOCK_RDM";
+ break;
+
+ default:
+ type = "UNKNOWN";
+ break;
+ }
+
+ if (arg1)
+ clen += printf(" [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3);
+ else
+ clen += printf(" F=%-3d <%s, %s, 0x%x>", arg2, domain, type, ti->arg3);
+ break;
+ }
+
+ case FMT_AIO_FSYNC:
+ {
+ /*
+ * aio_fsync [errno] AIOCBP OP
+ */
+ char *op;
+
+ if (ti->arg1 == O_SYNC || ti->arg1 == 0)
+ op = "AIO_FSYNC";
+#if O_DSYNC
+ else if (ti->arg1 == O_DSYNC)
+ op = "AIO_DSYNC";
+#endif
+ else
+ op = "UNKNOWN";
+
+ if (arg1)
+ clen += printf(" [%3d] P=0x%8.8x <%s>", arg1, ti->arg2, op);
+ else
+ clen += printf(" P=0x%8.8x <%s>", ti->arg2, op);
+ break;
+ }
+
+ case FMT_AIO_RETURN:
+ /*
+ * aio_return [errno] AIOCBP IOSIZE
+ */
+ if (arg1)
+ clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
+ else
+ clen += printf(" P=0x%8.8x B=0x%-8x", ti->arg1, arg2);
+ break;
+
+ case FMT_AIO_SUSPEND:
+ /*
+ * aio_suspend [errno] NENTS
+ */
+ if (arg1)
+ clen += printf(" [%3d] N=%d", arg1, ti->arg2);
+ else
+ clen += printf(" N=%d", ti->arg2);
+ break;
+
+ case FMT_AIO_CANCEL:
+ /*
+ * aio_cancel [errno] FD or AIOCBP (if non-null)
+ */
+ if (ti->arg2) {
+ if (arg1)
+ clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg2);
+ else
+ clen += printf(" P=0x%8.8x", ti->arg2);
+ } else {
+ if (arg1)
+ clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
+ else
+ clen += printf(" F=%-3d", ti->arg1);
+ }
+ break;
+
+ case FMT_AIO:
+ /*
+ * aio_error, aio_read, aio_write [errno] AIOCBP
+ */
+ if (arg1)
+ clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
+ else
+ clen += printf(" P=0x%8.8x", ti->arg1);
+ break;
+
+ case FMT_LIO_LISTIO:
+ {
+ /*
+ * lio_listio [errno] NENTS MODE
+ */
+ char *op;
+
+ if (ti->arg1 == LIO_NOWAIT)
+ op = "LIO_NOWAIT";
+ else if (ti->arg1 == LIO_WAIT)
+ op = "LIO_WAIT";
+ else
+ op = "UNKNOWN";
+
+ if (arg1)
+ clen += printf(" [%3d] N=%d <%s>", arg1, ti->arg3, op);
+ else
+ clen += printf(" N=%d <%s>", ti->arg3, op);
+ break;
+ }
+
+ }
+ }
+
+ /*
+ * Calculate space available to print pathname
+ */
+ if (columns > MAXCOLS || wideflag)
+ clen = columns - (clen + 14 + 20);
+ else
+ clen = columns - (clen + 14 + 12);
+
+ if (class != FILEMGR_CLASS && !nopadding)
+ clen -= 3;
+
+ if (framework_name)
+ len = sprintf(&buf[0], " %s ", framework_name);
+ else if (*pathname != '\0')
+ len = sprintf(&buf[0], " %s ", pathname);
+ else
+ len = 0;
+
+ if (clen > len) {
+ /*
+ * Add null padding if column length
+ * is wider than the pathname length.
+ */
+ memset(&buf[len], ' ', clen - len);
+ buf[clen] = '\0';
+
+ pathname = buf;
+
+ } else if (clen == len) {
+ pathname = buf;
+
+ } else if ((clen > 0) && (clen < len)) {
+ /*
+ * This prints the tail end of the pathname
+ */
+ buf[len-clen] = ' ';
+
+ pathname = &buf[len - clen];
+
+ } else {
+ pathname = "";
+ }
+
+ /*
+ * fudge some additional system call overhead
+ * that currently isn't tracked... this also
+ * insures that we see a minimum of 1 us for
+ * an elapsed time
+ */
+ usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor);
+ secs = usecs / 1000000;
+ usecs -= secs * 1000000;
+
+ if (class != FILEMGR_CLASS && !nopadding)
+ p1 = " ";
+ else
+ p1 = "";
- printf(" %2ld.%06ld", (unsigned long)secs, (unsigned long)usecs);
-
- if (waited)
- printf(" W");
- else
- printf(" ");
-
- if (columns > MAXCOLS || wideflag)
- printf(" %-20.20s", command_name);
- else
- printf(" %-12.12s", command_name);
-
- printf("\n");
- fflush (0);
+ if (waited)
+ p2 = " W";
+ else
+ p2 = " ";
+
+ if (columns > MAXCOLS || wideflag)
+ printf("%s%s %3ld.%06ld%s %-20.20s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
+ else
+ printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
}
int
set_enable(0);
/*
- This flag is turned off when calling
- quit() due to a set_remove() failure.
- */
+ * This flag is turned off when calling
+ * quit() due to a set_remove() failure.
+ */
if (set_remove_flag)
set_remove();
if (!map)
{
- /* If reach here, then this is a new thread and
+ /*
+ * If reach here, then this is a new thread and
* there are no invalid entries to reuse
* Double the size of the thread map table.
*/
-
n = total_threads * 2;
mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
map->valid = 1;
map->thread = thread;
/*
- The trace entry that returns the command name will hold
- at most, MAXCOMLEN chars, and in that case, is not
- guaranteed to be null terminated.
- */
+ * The trace entry that returns the command name will hold
+ * at most, MAXCOMLEN chars, and in that case, is not
+ * guaranteed to be null terminated.
+ */
(void)strncpy (map->command, command, MAXCOMLEN);
map->command[MAXCOMLEN] = '\0';
kd_threadmap *map;
fd_threadmap *fdmap;
+ if (thread == last_thread)
+ map_is_the_same = 0;
+
if ((map = find_thread_map(thread))) {
map->valid = 0;
map->thread = 0;
if(kp_buffer[i].kp_proc.p_stat == 0)
continue;
else {
- if(!strcmp(str, kp_buffer[i].kp_proc.p_comm))
+ if(!strncmp(str, kp_buffer[i].kp_proc.p_comm,
+ sizeof(kp_buffer[i].kp_proc.p_comm) -1))
pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
}
}
-char *lookup_name(unsigned long addr)
+char *lookup_name(uint64_t user_addr)
{
register int i;
register int start, last;
-
-
- if (numFrameworks == 0 || addr < frameworkInfo[0].address || addr > frameworkInfo[numFrameworks].address)
- return (0);
-
- start = 0;
- last = numFrameworks;
-
- for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) {
-
- if (addr >= frameworkInfo[i].address && addr < frameworkInfo[i+1].address)
- return(frameworkInfo[i].name);
-
- if (addr >= frameworkInfo[i].address) {
- start = i;
- i = start + ((last - i) / 2);
- } else {
- last = i;
- i = start + ((i - start) / 2);
+
+ 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; ) {
+
+ if (user_addr >= frameworkInfo[i].b_address && user_addr < frameworkInfo[i].e_address)
+ return(frameworkInfo[i].name);
+
+ if (user_addr >= frameworkInfo[i].b_address) {
+ start = i;
+ i = start + ((last - i) / 2);
+ } else {
+ last = i;
+ i = start + ((i - start) / 2);
+ }
}
}
return (0);
LibraryInfo *a = (LibraryInfo *)aa;
LibraryInfo *b = (LibraryInfo *)bb;
- if (a->address < b->address) return -1;
- if (a->address == b->address) return 0;
+ if (a->b_address < b->b_address) return -1;
+ if (a->b_address == b->b_address) return 0;
return 1;
}
-int scanline(char *inputstring,char **argv)
+int scanline(char *inputstring, char **argv, int maxtokens)
{
int n = 0;
- char **ap = argv, *p, *val;
+ char **ap = argv, *p, *val;
- for (p = inputstring; p != NULL; )
+ for (p = inputstring; n < maxtokens && p != NULL; )
{
while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
*ap++ = val;
- n++;
+ n++;
}
*ap = 0;
return n;
}
-int ReadSegAddrTable()
+int ReadSharedCacheMap(const char *path, LibraryRange *lr)
{
- char buf[1024];
+ 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;
- FILE *fd;
- unsigned long frameworkAddress, frameworkDataAddress, previousFrameworkAddress;
- char frameworkName[256];
- char *tokens[64];
- int ntokens;
- char *substring,*ptr;
- int founddylib = 0;
+ bzero(buf, sizeof(buf));
+ bzero(tokens, sizeof(tokens));
+
+ lr->b_address = 0;
+ lr->e_address = 0;
- bzero(buf, sizeof(buf));
- bzero(tokens, sizeof(tokens));
- numFrameworks = 0;
+ if ((fd = fopen(path, "r")) == 0)
+ {
+ return 0;
+ }
+ while (fgets(buf, 1023, fd)) {
+ if (strncmp(buf, "mapping", 7))
+ break;
+ }
+ buf[strlen(buf)-1] = 0;
+
+ frameworkName[0] = 0;
- if ((fd = fopen(seg_addr_table, "r")) == 0)
- {
- return 0;
- }
- fgets(buf, 1023, fd);
+ for (;;) {
+ b_frameworkAddress = 0;
+ b_frameworkDataAddress = 0;
+ e_frameworkAddress = 0;
+ e_frameworkDataAddress = 0;
- if (*buf == '#')
- {
- founddylib = 0;
- frameworkName[0] = 0;
- previousFrameworkAddress = 0;
-
- while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
- {
- /*
- * Get rid of EOL
- */
- buf[strlen(buf)-1] = 0;
-
- if (strncmp(buf, "# dyld:", 7) == 0) {
- /*
- * the next line in the file will contain info about dyld
+ /*
+ * Extract lib name from path name
*/
- founddylib = 1;
- continue;
- }
- /*
- * This is a split library line: parse it into 3 tokens
- */
- ntokens = scanline(buf, tokens);
+ if ((substring = strrchr(buf, '.')))
+ {
+ /*
+ * There is a ".": name is whatever is between the "/" around the "."
+ */
+ while ( *substring != '/') { /* find "/" before "." */
+ substring--;
+ }
+ substring++;
+ strncpy(frameworkName, substring, 256); /* copy path from "/" */
+ frameworkName[255] = 0;
+ substring = frameworkName;
+
+ while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
+ substring++;
+ *substring = 0;
+ }
+ else
+ {
+ /*
+ * No ".": take segment after last "/"
+ */
+ ptr = buf;
+ substring = ptr;
+
+ while (*ptr)
+ {
+ if (*ptr == '/')
+ substring = ptr + 1;
+ ptr++;
+ }
+ strncpy(frameworkName, substring, 256);
+ frameworkName[255] = 0;
+ }
+ while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
+ {
+ /*
+ * Get rid of EOL
+ */
+ buf[strlen(buf)-1] = 0;
- if (ntokens < 3)
- continue;
+ ntokens = scanline(buf, tokens, 64);
- frameworkAddress = strtoul(tokens[0], 0, 16);
- frameworkDataAddress = strtoul(tokens[1], 0, 16);
+ if (ntokens < 4)
+ continue;
- if (founddylib) {
- /*
- * dyld entry is of a different form from the std split library
- * it consists of a base address and a size instead of a code
- * and data base address
+ 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
*/
- frameworkInfo[numFrameworks].address = frameworkAddress;
- frameworkInfo[numFrameworks+1].address = frameworkAddress + frameworkDataAddress;
+ if (b_frameworkAddress && b_frameworkDataAddress) {
- frameworkInfo[numFrameworks].name = (char *)"dylib";
- frameworkInfo[numFrameworks+1].name = (char *)0;
+ frameworkInfo[numFrameworks].b_address = b_frameworkAddress;
+ frameworkInfo[numFrameworks].e_address = e_frameworkAddress;
- numFrameworks += 2;
- founddylib = 0;
+ frameworkInfo[numFrameworks+1].b_address = b_frameworkDataAddress;
+ frameworkInfo[numFrameworks+1].e_address = e_frameworkDataAddress;
- continue;
- }
-
- /*
- * Make sure that we have 2 addresses and a path
- */
- if (!frameworkAddress)
- continue;
- if (!frameworkDataAddress)
- continue;
- if (*tokens[2] != '/')
- continue;
- if (frameworkAddress == previousFrameworkAddress)
- continue;
- previousFrameworkAddress = frameworkAddress;
-
- /*
- * Extract lib name from path name
- */
- if ((substring = strrchr(tokens[2], '.')))
- {
- /*
- * There is a ".": name is whatever is between the "/" around the "."
- */
- while ( *substring != '/') { /* find "/" before "." */
- substring--;
- }
- substring++;
- strcpy(frameworkName, substring); /* copy path from "/" */
- substring = frameworkName;
+ frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
+ strcpy(frameworkInfo[numFrameworks].name, frameworkName);
+ frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
- while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
- substring++;
- *substring = 0;
- }
- else
- {
- /*
- * No ".": take segment after last "/"
- */
- ptr = tokens[2];
- substring = ptr;
+ numFrameworks += 2;
+#if 0
+ printf("%s: %qx-%qx %qx-%qx\n", frameworkName, b_frameworkAddress, e_frameworkAddress, b_frameworkDataAddress, e_frameworkDataAddress);
+#endif
+ if (lr->b_address == 0)
+ lr->b_address = b_frameworkAddress;
- while (*ptr)
- {
- if (*ptr == '/')
- substring = ptr + 1;
- ptr++;
+ if (b_frameworkAddress < lr->b_address)
+ lr->b_address = b_frameworkAddress;
+
+ 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;
}
- strcpy(frameworkName, substring);
- }
- frameworkInfo[numFrameworks].address = frameworkAddress;
- frameworkInfo[numFrameworks+1].address = frameworkDataAddress;
+ if (fgets(buf, 1023, fd) == 0)
+ break;
- frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
- strcpy(frameworkInfo[numFrameworks].name, frameworkName);
- frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
+ buf[strlen(buf)-1] = 0;
+ }
+ fclose(fd);
- numFrameworks += 2;
- }
- }
- frameworkInfo[numFrameworks].address = frameworkInfo[numFrameworks - 1].address + 0x800000;
- frameworkInfo[numFrameworks].name = (char *)0;
+ return 1;
+}
- fclose(fd);
- qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
+void
+SortFrameworkAddresses()
+{
+
+ frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000;
+ frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address;
+ frameworkInfo[numFrameworks].name = (char *)0;
- return 1;
+ qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
}
p = " ";
break;
}
- if (check_filter_mode(NULL, dio->type,0, 0, p))
- format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 7, dio->completed_time, dio->issued_time, 1, "", dio);
+ if (check_filter_mode(NULL, dio->type, 0, 0, p))
+ format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 0, FMT_DISKIO, dio->completed_time, dio->issued_time, 1, "", dio);
}
if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
continue;
- sprintf(nbuf, "%s/%s", "/dev", dir->d_name);
+ snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
if (stat(nbuf, &st) < 0)
continue;
}
/* If the map is not big enough, then reallocate it */
- while (fdmap->fd_setsize < fd)
+ while (fdmap->fd_setsize <= fd)
{
fprintf(stderr, "reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
thread, fd, fdmap->fd_setsize);
unsigned int fd;
if (filter_mode == DEFAULT_DO_NOT_FILTER)
- return(1);
+ return(1);
- if (!strcmp (sc_name, "CACHE_HIT")) {
+ if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) {
if (filter_mode & CACHEHIT_FILTER)
/* Do not print if cachehit filter is set */
return(0);
- return (1);
+ return(1);
}
if (filter_mode & EXEC_FILTER)
{
- if (!strcmp (sc_name, "execve"))
- return(1);
- return(0);
+ if (type == BSC_execve)
+ return(1);
+ return(0);
}
+
+ if (filter_mode & PATHNAME_FILTER)
+ {
+ if (ti && ti->pathname[0])
+ return(1);
+ if (type == BSC_close || type == BSC_close_nocancel)
+ return(1);
+ return(0);
+ }
+
if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER)))
return(1);
if (ti == (struct th_info *)0)
{
- if(filter_mode & FILESYS_FILTER)
+ if (filter_mode & FILESYS_FILTER)
ret = 1;
else
ret = 0;
switch (type) {
case BSC_close:
+ case BSC_close_nocancel:
fd = ti->arg1;
network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
if (error == 0)
break;
case BSC_read:
case BSC_write:
+ case BSC_read_nocancel:
+ case BSC_write_nocancel:
/* we don't care about error in this case */
fd = ti->arg1;
network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
ret = 1;
break;
case BSC_accept:
+ case BSC_accept_nocancel:
case BSC_socket:
fd = retval;
if (error == 0)
case BSC_connect:
case BSC_bind:
case BSC_listen:
+ case BSC_sendto_nocancel:
+ case BSC_recvfrom_nocancel:
+ case BSC_recvmsg_nocancel:
+ case BSC_sendmsg_nocancel:
+ case BSC_connect_nocancel:
fd = ti->arg1;
if (error == 0)
fs_usage_fd_set(ti->thread, fd);
ret = 1;
break;
case BSC_select:
+ case BSC_select_nocancel:
case BSC_socketpair:
/* Cannot determine info about file descriptors */
if (filter_mode & NETWORK_FILTER)
_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
_POSIX_V6_LPBIG_OFFBIG_LIBS, _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
_POSIX_V6_WIDTH_RESTRICTED_ENVS, _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
+DARWIN_USER_DIR, _CS_DARWIN_USER_DIR
+DARWIN_USER_TEMP_DIR, _CS_DARWIN_USER_TEMP_DIR
+DARWIN_USER_CACHE_DIR, _CS_DARWIN_USER_CACHE_DIR
%%
int
find_confstr(const char *name, int *key)
.Xr confstr 3
variables provide information on the necessary compiler and linker flags
to use the standard programming environments described above.
+.Pp
+Many of these values are also available through the
+.Xr sysctl 8
+mechanism.
.Sh DIAGNOSTICS
.Ex -std
Use of a
.Sh SEE ALSO
.Xr pathconf 2 ,
.Xr confstr 3 ,
-.Xr sysconf 3
+.Xr sysconf 3 ,
+.Xr sysctl 8
.Sh STANDARDS
The
.Nm
}
if (argv[optind + 1] == NULL) { /* confstr or sysconf */
-#ifdef APPLE_GETCONF_SPEC
- if ((valid = find_progenv(name, &alt_path)) != 0) {
- printf(valid > 0 ? "defined\n" : "undefined\n");
- return 0;
- }
-#endif /* APPLE_GETCONF_SPEC */
if ((valid = find_limit(name, &limitval)) != 0) {
if (valid > 0)
printf("%" PRIdMAX "\n", limitval);
{
size_t len;
+ errno = 0;
len = confstr(key, 0, 0);
- if (len == (size_t)-1)
- err(EX_OSERR, "confstr: %s", name);
-
- if (len == 0)
- printf("undefined\n");
- else {
+ if (len == 0) {
+ if (errno != 0) {
+ err(EX_OSERR, "confstr: %s", name);
+ } else {
+ printf("undefined\n");
+ }
+ } else {
char buf[len + 1];
confstr(key, buf, len);
}
#ifdef APPLE_GETCONF_UNDERSCORE
if(*name == '_')
- alt = name + 1;
+ alt = (char *)name + 1;
else {
if((alt = (char *)alloca(strlen(name) + 2)) == NULL)
return 0;
POSIX_REC_MAX_XFER_SIZE, _PC_REC_MAX_XFER_SIZE
POSIX_REC_MIN_XFER_SIZE, _PC_REC_MIN_XFER_SIZE
POSIX_REC_XFER_ALIGN, _PC_REC_XFER_ALIGN
+POSIX2_SYMLINKS, _PC_2_SYMLINKS
SYMLINK_MAX, _PC_SYMLINK_MAX
TRUSTEDBSD_ACL_EXTENDED, _PC_ACL_EXTENDED
TRUSTEDBSD_ACL_PATH_MAX, _PC_ACL_PATH_MAX
}
#ifdef APPLE_GETCONF_UNDERSCORE
if(*name == '_')
- alt = name + 1;
+ alt = (char *)name + 1;
else {
if((alt = (char *)alloca(strlen(name) + 2)) == NULL)
return 0;
*/
#if defined(__alpha__) || defined(__sparc64__)
#define have_LP64_OFF64 NULL
+#elif defined(__APPLE__)
+#define have_LP64_OFF64 NULL
+#define have_LPBIG_OFFBIG NULL
#endif
#if defined(__i386__) || defined(__powerpc__)
POSIX_V6_ILP32_OFF32, notdef
POSIX_V6_ILP32_OFFBIG, have_ILP32_OFFBIG
POSIX_V6_LP64_OFF64, have_LP64_OFF64
-POSIX_V6_LPBIG_OFFBIG, notdef
+POSIX_V6_LPBIG_OFFBIG, have_LPBIG_OFFBIG
_POSIX_V6_ILP32_OFF32, notdef
_POSIX_V6_ILP32_OFFBIG, have_ILP32_OFFBIG
_POSIX_V6_LP64_OFF64, have_LP64_OFF64
-_POSIX_V6_LPBIG_OFFBIG, notdef
+_POSIX_V6_LPBIG_OFFBIG, have_LPBIG_OFFBIG
%%
int
find_progenv(const char *name, const char **alt_path)
_POSIX_SPAWN, _SC_SPAWN
_POSIX_SPIN_LOCKS, _SC_SPIN_LOCKS
_POSIX_SPORADIC_SERVER, _SC_SPORADIC_SERVER
+_POSIX_SS_REPL_MAX, _SC_SS_REPL_MAX
_POSIX_SYNCHRONIZED_IO, _SC_SYNCHRONIZED_IO
_POSIX_THREADS, _SC_THREADS
_POSIX_THREAD_ATTR_STACKADDR, _SC_THREAD_ATTR_STACKADDR
_POSIX_THREAD_SAFE_FUNCTIONS, _SC_THREAD_SAFE_FUNCTIONS
_POSIX_THREAD_SPORADIC_SERVER, _SC_THREAD_SPORADIC_SERVER
_POSIX_TIMEOUTS, _SC_TIMEOUTS
+_POSIX_TIMERS, _SC_TIMERS
_POSIX_TRACE, _SC_TRACE
_POSIX_TRACE_EVENT_FILTER, _SC_TRACE_EVENT_FILTER
+_POSIX_TRACE_EVENT_NAME_MAX, _SC_TRACE_EVENT_NAME_MAX
_POSIX_TRACE_INHERIT, _SC_TRACE_INHERIT
_POSIX_TRACE_LOG, _SC_TRACE_LOG
-_POSIX_TIMERS, _SC_TIMERS
+_POSIX_TRACE_NAME_MAX, _SC_TRACE_NAME_MAX
+_POSIX_TRACE_SYS_MAX, _SC_TRACE_SYS_MAX
+_POSIX_TRACE_USER_EVENT_MAX, _SC_TRACE_USER_EVENT_MAX
_POSIX_TYPED_MEMORY_OBJECTS, _SC_TYPED_MEMORY_OBJECTS
-_POSIX_VERSION, _SC_VERSION
_POSIX_V6_ILP32_OFF32, _SC_V6_ILP32_OFF32
_POSIX_V6_ILP32_OFFBIG, _SC_V6_ILP32_OFFBIG
_POSIX_V6_LP64_OFF64, _SC_V6_LP64_OFF64
-_POSIX_V6_LP64_OFFBIG, _SC_V6_LP64_OFFBIG
+_POSIX_V6_LPBIG_OFFBIG, _SC_V6_LPBIG_OFFBIG
+_POSIX_VERSION, _SC_VERSION
_XOPEN_CRYPT, _SC_XOPEN_CRYPT
_XOPEN_ENH_I18N, _SC_XOPEN_ENH_I18N
_XOPEN_LEGACY, _SC_XOPEN_LEGACY
}
#ifdef APPLE_GETCONF_UNDERSCORE
if(*name == '_')
- alt = name + 1;
+ alt = (char *)name + 1;
else {
if((alt = (char *)alloca(strlen(name) + 2)) == NULL)
return 0;
HFILES = extern.h gettytab.h pathnames.h
-CFILES = init.c main.c subr.c
+CFILES = chat.c init.c main.c subr.c
OTHERSRCS = Makefile.preamble Makefile Makefile.postamble getty.8\
- gettytab.5 ttys.5
+ gettytab.5 ttys.5 com.apple.getty.plist
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
# the top-level:
#OPTIMIZATION_CFLAG = -O
#DEBUG_SYMBOLS_CFLAG = -g
-#WARNING_CFLAGS = -Wall
+WARNING_CFLAGS = -Wall -Werror
#DEBUG_BUILD_CFLAGS = -DDEBUG
#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
# owned by the top-level Makefile API and no context has been set up for where
# derived files should go.
+LAUNCHD_PLIST_DIR = $(DSTROOT)/System/Library/LaunchDaemons
+LAUNCHD_PLIST = com.apple.getty.plist
+
+Embedded = $(shell tconf --test TARGET_OS_EMBEDDED)
+
after_install:
mkdir -p $(DSTROOT)/usr/share/man/man5
install -c -m 444 gettytab.5 $(DSTROOT)/usr/share/man/man5
install -c -m 444 ttys.5 $(DSTROOT)/usr/share/man/man5
mkdir -p $(DSTROOT)/usr/share/man/man8
install -c -m 444 getty.8 $(DSTROOT)/usr/share/man/man8
+ifeq "$(Embedded)" "YES"
+ install -d $(LAUNCHD_PLIST_DIR)
+ install -c -m 644 $(LAUNCHD_PLIST) $(LAUNCHD_PLIST_DIR)/$(LAUNCHD_PLIST)
+endif
## (e.g. change -O to -O2), see Makefile.postamble.
# Flags passed to compiler (in addition to -g, -O, etc)
-OTHER_CFLAGS =
+OTHER_CFLAGS = -fno-builtin-puts
# Flags passed to ld (in addition to -ObjC, etc.)
OTHER_LDFLAGS =
# Flags passed to libtool when building libraries
--- /dev/null
+/*-
+ * Copyright (c) 1997
+ * David L Nugent <davidn@blaze.net.au>.
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, is permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. This work was done expressly for inclusion into FreeBSD. Other use
+ * is permitted provided this notation is included.
+ * 4. Absolutely no warranty of function or purpose is made by the authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Modem chat module - send/expect style functions for getty
+ * For semi-intelligent modem handling.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD: src/libexec/getty/chat.c,v 1.11 2005/04/06 17:42:24 stefanf Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+
+#include <ctype.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "gettytab.h"
+#include "extern.h"
+
+#define PAUSE_CH (unsigned char)'\xff' /* pause kludge */
+
+#define CHATDEBUG_RECEIVE 0x01
+#define CHATDEBUG_SEND 0x02
+#define CHATDEBUG_EXPECT 0x04
+#define CHATDEBUG_MISC 0x08
+
+#define CHATDEBUG_DEFAULT 0
+#define CHAT_DEFAULT_TIMEOUT 10
+
+
+static int chat_debug = CHATDEBUG_DEFAULT;
+static int chat_alarm = CHAT_DEFAULT_TIMEOUT; /* Default */
+
+static volatile int alarmed = 0;
+
+
+static void chat_alrm(int);
+static int chat_unalarm(void);
+static int getdigit(unsigned char **, int, int);
+static char **read_chat(char **);
+static char *cleanchr(char **, unsigned char);
+static char *cleanstr(const char *, int);
+static const char *result(int);
+static int chat_expect(const char *);
+static int chat_send(char const *);
+
+
+/*
+ * alarm signal handler
+ * handle timeouts in read/write
+ * change stdin to non-blocking mode to prevent
+ * possible hang in read().
+ */
+
+static void
+chat_alrm(int signo)
+{
+ int on = 1;
+
+ alarm(1);
+ alarmed = 1;
+ signal(SIGALRM, chat_alrm);
+ ioctl(STDIN_FILENO, FIONBIO, &on);
+}
+
+
+/*
+ * Turn back on blocking mode reset by chat_alrm()
+ */
+
+static int
+chat_unalarm(void)
+{
+ int off = 0;
+ return ioctl(STDIN_FILENO, FIONBIO, &off);
+}
+
+
+/*
+ * convert a string of a given base (octal/hex) to binary
+ */
+
+static int
+getdigit(unsigned char **ptr, int base, int max)
+{
+ int i, val = 0;
+ unsigned char * q;
+
+ static const char xdigits[] = "0123456789abcdef";
+
+ for (i = 0, q = *ptr; i++ < max; ++q) {
+ int sval;
+ const char * s = strchr(xdigits, tolower(*q));
+
+ if (s == NULL || (sval = s - xdigits) >= base)
+ break;
+ val = (val * base) + sval;
+ }
+ *ptr = q;
+ return val;
+}
+
+
+/*
+ * read_chat()
+ * Convert a whitespace delimtied string into an array
+ * of strings, being expect/send pairs
+ */
+
+static char **
+read_chat(char **chatstr)
+{
+ char *str = *chatstr;
+ char **res = NULL;
+
+ if (str != NULL) {
+ char *tmp = NULL;
+ int l;
+
+ if ((l=strlen(str)) > 0 && (tmp=malloc(l + 1)) != NULL &&
+ (res=malloc((l / 2 + 1) * sizeof(char *))) != NULL) {
+ static char ws[] = " \t";
+ char * p;
+
+ for (l = 0, p = strtok(strcpy(tmp, str), ws);
+ p != NULL;
+ p = strtok(NULL, ws))
+ {
+ unsigned char *q, *r;
+
+ /* Read escapes */
+ for (q = r = (unsigned char *)p; *r; ++q)
+ {
+ if (*q == '\\')
+ {
+ /* handle special escapes */
+ switch (*++q)
+ {
+ case 'a': /* bell */
+ *r++ = '\a';
+ break;
+ case 'r': /* cr */
+ *r++ = '\r';
+ break;
+ case 'n': /* nl */
+ *r++ = '\n';
+ break;
+ case 'f': /* ff */
+ *r++ = '\f';
+ break;
+ case 'b': /* bs */
+ *r++ = '\b';
+ break;
+ case 'e': /* esc */
+ *r++ = 27;
+ break;
+ case 't': /* tab */
+ *r++ = '\t';
+ break;
+ case 'p': /* pause */
+ *r++ = PAUSE_CH;
+ break;
+ case 's':
+ case 'S': /* space */
+ *r++ = ' ';
+ break;
+ case 'x': /* hexdigit */
+ ++q;
+ *r++ = getdigit(&q, 16, 2);
+ --q;
+ break;
+ case '0': /* octal */
+ ++q;
+ *r++ = getdigit(&q, 8, 3);
+ --q;
+ break;
+ default: /* literal */
+ *r++ = *q;
+ break;
+ case 0: /* not past eos */
+ --q;
+ break;
+ }
+ } else {
+ /* copy standard character */
+ *r++ = *q;
+ }
+ }
+
+ /* Remove surrounding quotes, if any
+ */
+ if (*p == '"' || *p == '\'') {
+ q = (unsigned char*)strrchr(p+1, *p);
+ if (q != NULL && *q == *p && q[1] == '\0') {
+ *q = '\0';
+ strcpy(p, p+1);
+ }
+ }
+
+ res[l++] = p;
+ }
+ res[l] = NULL;
+ *chatstr = tmp;
+ return res;
+ }
+ free(tmp);
+ }
+ return res;
+}
+
+
+/*
+ * clean a character for display (ctrl/meta character)
+ */
+
+static char *
+cleanchr(char **buf, unsigned char ch)
+{
+ int l;
+ static char tmpbuf[5];
+ char * tmp = buf ? *buf : tmpbuf;
+
+ if (ch & 0x80) {
+ strcpy(tmp, "M-");
+ l = 2;
+ ch &= 0x7f;
+ } else
+ l = 0;
+
+ if (ch < 32) {
+ tmp[l++] = '^';
+ tmp[l++] = ch + '@';
+ } else if (ch == 127) {
+ tmp[l++] = '^';
+ tmp[l++] = '?';
+ } else
+ tmp[l++] = ch;
+ tmp[l] = '\0';
+
+ if (buf)
+ *buf = tmp + l;
+ return tmp;
+}
+
+
+/*
+ * clean a string for display (ctrl/meta characters)
+ */
+
+static char *
+cleanstr(const char *s, int l)
+{
+ static char * tmp = NULL;
+ static int tmplen = 0;
+
+ if (tmplen < l * 4 + 1)
+ tmp = realloc(tmp, tmplen = l * 4 + 1);
+
+ if (tmp == NULL) {
+ tmplen = 0;
+ return (char *)"(mem alloc error)";
+ } else {
+ int i = 0;
+ char * p = tmp;
+
+ while (i < l)
+ cleanchr(&p, s[i++]);
+ *p = '\0';
+ }
+
+ return tmp;
+}
+
+
+/*
+ * return result as a pseudo-english word
+ */
+
+static const char *
+result(int r)
+{
+ static const char * results[] = {
+ "OK", "MEMERROR", "IOERROR", "TIMEOUT"
+ };
+ return results[r & 3];
+}
+
+
+/*
+ * chat_expect()
+ * scan input for an expected string
+ */
+
+static int
+chat_expect(const char *str)
+{
+ int len, r = 0;
+
+ if (chat_debug & CHATDEBUG_EXPECT)
+ syslog(LOG_DEBUG, "chat_expect '%s'", cleanstr(str, strlen(str)));
+
+ if ((len = strlen(str)) > 0) {
+ int i = 0;
+ char * got;
+
+ if ((got = malloc(len + 1)) == NULL)
+ r = 1;
+ else {
+
+ memset(got, 0, len+1);
+ alarm(chat_alarm);
+ alarmed = 0;
+
+ while (r == 0 && i < len) {
+ if (alarmed)
+ r = 3;
+ else {
+ unsigned char ch;
+
+ if (read(STDIN_FILENO, &ch, 1) == 1) {
+
+ if (chat_debug & CHATDEBUG_RECEIVE)
+ syslog(LOG_DEBUG, "chat_recv '%s' m=%d",
+ cleanchr(NULL, ch), i);
+
+ if (ch == str[i])
+ got[i++] = ch;
+ else if (i > 0) {
+ int j = 1;
+
+ /* See if we can resync on a
+ * partial match in our buffer
+ */
+ while (j < i && memcmp(got + j, str, i - j) != 0)
+ j++;
+ if (j < i)
+ memcpy(got, got + j, i - j);
+ i -= j;
+ }
+ } else
+ r = alarmed ? 3 : 2;
+ }
+ }
+ alarm(0);
+ chat_unalarm();
+ alarmed = 0;
+ free(got);
+ }
+ }
+
+ if (chat_debug & CHATDEBUG_EXPECT)
+ syslog(LOG_DEBUG, "chat_expect %s", result(r));
+
+ return r;
+}
+
+
+/*
+ * chat_send()
+ * send a chat string
+ */
+
+static int
+chat_send(char const *str)
+{
+ int r = 0;
+
+ if (chat_debug && CHATDEBUG_SEND)
+ syslog(LOG_DEBUG, "chat_send '%s'", cleanstr(str, strlen(str)));
+
+ if (*str) {
+ alarm(chat_alarm);
+ alarmed = 0;
+ while (r == 0 && *str)
+ {
+ unsigned char ch = (unsigned char)*str++;
+
+ if (alarmed)
+ r = 3;
+ else if (ch == PAUSE_CH)
+ usleep(500000); /* 1/2 second */
+ else {
+ usleep(10000); /* be kind to modem */
+ if (write(STDOUT_FILENO, &ch, 1) != 1)
+ r = alarmed ? 3 : 2;
+ }
+ }
+ alarm(0);
+ chat_unalarm();
+ alarmed = 0;
+ }
+
+ if (chat_debug & CHATDEBUG_SEND)
+ syslog(LOG_DEBUG, "chat_send %s", result(r));
+
+ return r;
+}
+
+
+/*
+ * getty_chat()
+ *
+ * Termination codes:
+ * -1 - no script supplied
+ * 0 - script terminated correctly
+ * 1 - invalid argument, expect string too large, etc.
+ * 2 - error on an I/O operation or fatal error condition
+ * 3 - timeout waiting for a simple string
+ *
+ * Parameters:
+ * char *scrstr - unparsed chat script
+ * timeout - seconds timeout
+ * debug - debug value (bitmask)
+ */
+
+int
+getty_chat(char *scrstr, int timeout, int debug)
+{
+ int r = -1;
+
+ chat_alarm = timeout ? timeout : CHAT_DEFAULT_TIMEOUT;
+ chat_debug = debug;
+
+ if (scrstr != NULL) {
+ char **script;
+
+ if (chat_debug & CHATDEBUG_MISC)
+ syslog(LOG_DEBUG, "getty_chat script='%s'", scrstr);
+
+ if ((script = read_chat(&scrstr)) != NULL) {
+ int i = r = 0;
+ int off = 0;
+ sig_t old_alarm;
+
+ /*
+ * We need to be in raw mode for all this
+ * Rely on caller...
+ */
+
+ old_alarm = signal(SIGALRM, chat_alrm);
+ chat_unalarm(); /* Force blocking mode at start */
+
+ /*
+ * This is the send/expect loop
+ */
+ while (r == 0 && script[i] != NULL)
+ if ((r = chat_expect(script[i++])) == 0 && script[i] != NULL)
+ r = chat_send(script[i++]);
+
+ signal(SIGALRM, old_alarm);
+ free(script);
+ free(scrstr);
+
+ /*
+ * Ensure stdin is in blocking mode
+ */
+ ioctl(STDIN_FILENO, FIONBIO, &off);
+ }
+
+ if (chat_debug & CHATDEBUG_MISC)
+ syslog(LOG_DEBUG, "getty_chat %s", result(r));
+
+ }
+ return r;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.getty</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/libexec/getty</string>
+ <string>std.9600</string>
+ <string>console</string>
+ </array>
+ <key>SessionCreate</key>
+ <true/>
+ <key>KeepAlive</key>
+ <true/>
+</dict>
+</plist>
-/*
- * 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.
* SUCH DAMAGE.
*
* from: @(#)extern.h 8.1 (Berkeley) 6/4/93
- * $Id: extern.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ * $FreeBSD: src/libexec/getty/extern.h,v 1.9 2005/04/06 17:42:24 stefanf Exp $
*/
struct delayval;
+struct termios;
-int adelay __P((int, struct delayval *));
-char *autobaud __P((void));
-int delaybits __P((void));
-void edithost __P((char *));
-void gendefaults __P((void));
-int getent __P((char *, char *));
-int getflag __P((char *));
-long getnum __P((char *));
-char *getstr __P((char *, char **));
-void gettable __P((char *, char *));
-void makeenv __P((char *[]));
-char *portselector __P((void));
-void set_ttydefaults __P((int));
-void setchars __P((void));
-void setdefaults __P((void));
-void setflags __P((int));
-int speed __P((int));
+extern char hostname[];
+extern int hopcount;
+extern struct termios tmode, omode;
+extern struct gettyflags gettyflags[];
+extern struct gettynums gettynums[];
+extern struct gettystrs gettystrs[];
-int login_tty __P((int)); /* From libutil. */
+int adelay(int, struct delayval *);
+const char *autobaud(void);
+int delaybits(void);
+void edithost(const char *);
+void gendefaults(void);
+void gettable(const char *, char *);
+void makeenv(char *[]);
+const char *portselector(void);
+void set_ttydefaults(int);
+void setchars(void);
+void setdefaults(void);
+void set_flags(int);
+int speed(int);
+int getty_chat(char *, int, int);
.\" SUCH DAMAGE.
.\"
.\" from: @(#)getty.8 8.1 (Berkeley) 6/4/93
-.\" $Id: getty.8,v 1.1 1999/05/02 04:21:29 wsanchez Exp $
-.\"
+.\" $FreeBSD: src/libexec/getty/getty.8,v 1.16 2005/01/18 09:29:39 ru Exp $
+.\" "
.Dd June 4, 1993
.Dt GETTY 8
-.Os BSD 4
+.Os
.Sh NAME
.Nm getty
.Nd set terminal mode
.Sh SYNOPSIS
-.Nm getty
-.Oo
+.Nm
+.Oo
.Ar type
.Op Ar tty
.Oc
.Sh DESCRIPTION
The
-.Nm getty
-program
-is called by
-.Xr init 8
+.Nm
+utility is called by
+.Xr launchd 8
to open and initialize the tty line, read a login name, and invoke
.Xr login 1 .
.Pp
.Pa /dev
to open for the terminal (for example, ``ttyh0'').
If there is no argument or the argument is
-.Ql Fl ,
+.Sq Fl ,
the tty line is assumed to be open as file descriptor 0.
.Pp
The
.Ar type
argument can be used to make
-.Nm getty
+.Nm
treat the terminal line specially.
This argument is used as an index into the
-.Nm gettytab 5
+.Xr gettytab 5
database, to determine the characteristics of the line.
If there is no argument, or there is no such table, the
.Em default
.Pa /etc/gettytab
a set of system defaults is used.
If indicated by the table located,
-.Nm getty
+.Nm
will clear the terminal screen,
print a banner heading,
and prompt for a login name.
the system hostname.
.Pp
Most of the default actions of
-.Nm getty
+.Nm
can be circumvented, or modified, by a suitable
-.Nm gettytab
+.Pa gettytab
table.
.Pp
The
-.Nm getty
-program
-can be set to timeout after some interval,
+.Nm
+utility can be set to timeout after some interval,
which will cause dial up lines to hang up
if the login name is not entered reasonably quickly.
+.Sh FILES
+.Bl -tag -width /etc/gettytab -compact
+.It Pa /etc/gettytab
+.It Pa /etc/ttys
+.El
.Sh DIAGNOSTICS
.Bl -diag
.It "ttyxx: No such device or address."
.It "ttyxx: No such file or address."
+.Pp
A terminal which is turned
on in the
-.Xr ttys
+.Pa ttys
file cannot be opened, likely because the requisite
lines are either not configured into the system, the associated device
was not attached during boot-time system configuration,
.Pa /dev
does not exist.
.El
-.Sh FILES
-.Bl -tag -width /etc/gettytab -compact
-.It Pa /etc/gettytab
-.El
.Sh SEE ALSO
-.Xr gettytab 5 ,
-.Xr init 8 ,
.Xr login 1 ,
.Xr ioctl 2 ,
.Xr tty 4 ,
-.Xr ttys 5
+.Xr gettytab 5 ,
+.Xr ttys 5 ,
+.Xr launchd 8
.Sh HISTORY
A
-.Nm getty
-program appeared in
+.Nm
+utility appeared in
.At v6 .
.\" SUCH DAMAGE.
.\"
.\" from: @(#)gettytab.5 8.4 (Berkeley) 4/19/94
-.\" $Id: gettytab.5,v 1.1 1999/05/02 04:21:29 wsanchez Exp $
-.\"
+.\" $FreeBSD: src/libexec/getty/gettytab.5,v 1.41 2005/01/18 09:29:39 ru Exp $
+.\" "
.Dd April 19, 1994
.Dt GETTYTAB 5
-.Os BSD 4.2
+.Os
.Sh NAME
.Nm gettytab
.Nd terminal configuration data base
.Sh SYNOPSIS
-.Nm gettytab
+.Nm
.Sh DESCRIPTION
The
-.Nm gettytab
+.Nm
file
is a simplified version of the
.Xr termcap 5
The initial terminal login process
.Xr getty 8
accesses the
-.Nm gettytab
+.Nm
file each time it starts, allowing simpler
reconfiguration of terminal characteristics.
Each entry in the data base
is used to describe one class of terminals.
.Pp
There is a default terminal class,
-.Em default ,
+.Va default ,
that is used to set global defaults for all other classes.
(That is, the
-.Em default
+.Va default
entry is read, then the entry for the class required
is used to override particular settings.)
.Sh CAPABILITIES
.Xr termcap 5
for a description of the file layout.
The
-.Em default
+.Va default
column below lists defaults obtained if there is
no entry in the table obtained, nor one in the special
-.Em default
+.Va default
table.
-.Bl -column Namexx /usr/bin/login Default
-.It Sy Name Type Default Description
+.Bl -column Name Type /usr/bin/login
+.It Sy "Name Type Default Description
+.It "ac str unused expect-send chat script for modem answer"
+.It "al str unused user to auto-login instead of prompting"
.It "ap bool false terminal uses any parity"
.It "bk str 0377 alternate end of line character (input break)"
.It "c0 num unused tty control flags to write messages"
.It "c2 num unused tty control flags to leave terminal as"
.It "ce bool false use crt erase algorithm"
.It "ck bool false use crt kill algorithm"
-.It "cl str" Ta Dv NULL Ta
+.It "cl str" Ta Dv NULL Ta
.No "screen clear sequence"
.It "co bool false console - add"
.Ql \en
after login prompt
+.It "ct num 10 chat timeout for"
+.Va \&ac
+and
+.Va \&ic
+scripts
+.It "dc num 0 chat debug bitmask"
+.It "de num 0 delay secs and flush input before writing first prompt"
+.It "df str %+ the" Xr strftime 3 "format used for \&%d in the banner message"
.It "ds str" Ta So Li ^Y Sc Ta
.No "delayed suspend character"
.It "dx bool false set"
.Dv DECCTLQ
.It "ec bool false leave echo"
-.Tn OFF
+.Em OFF
.It "ep bool false terminal uses even parity"
.It "er str" Ta So Li ^? Sc Ta
.No "erase character"
.No "end of text"
.Pq Dv EOF
character
-.It "ev str" Ta Dv NULL Ta
+.It "ev str" Ta Dv NULL Ta
.No "initial environment"
.It "f0 num unused tty mode flags to write messages"
.It "f1 num unused tty mode flags to read login name"
.It "fl str" Ta So Li ^O Sc Ta
.No "output flush character"
.It "hc bool false do"
-.Tn NOT
+.Em NOT
hangup line on last close
-.It "he str" Ta Dv NULL Ta
+.It "he str" Ta Dv NULL Ta
.No "hostname editing string"
.It "hn str hostname hostname"
.It "ht bool false terminal has real tabs"
+.It "hw bool false do cts/rts hardware flow control"
.It "i0 num unused tty input flags to write messages"
.It "i1 num unused tty input flags to read login name"
.It "i2 num unused tty input flags to leave terminal as"
+.It "ic str unused expect-send chat script for modem initialization"
+.It "if str unused display named file before prompt, like /etc/issue"
.It "ig bool false ignore garbage characters in login name"
.It "im str" Ta Dv NULL Ta
.No "initial (banner) message"
.It "l0 num unused tty local flags to write messages"
.It "l1 num unused tty local flags to read login name"
.It "l2 num unused tty local flags to leave terminal as"
-.It "lc bool false terminal has lower case"
.It "lm str login: login prompt"
.It "ln str" Ta So Li ^V Sc Ta
.No "``literal next'' character"
.It "lo str" Ta Pa /usr/bin/login Ta
.No "program to exec when name obtained"
.It "mb bool false do flow control based on carrier"
+.It "nc bool false terminal does not supply carrier (set clocal)"
.It "nl bool false terminal has (or might have) a newline character"
.It "np bool false terminal uses no parity (i.e. 8-bit characters)"
.It "nx str default next table (for auto speed selection)"
.It "pe bool false use printer (hard copy) erase algorithm"
.It "pf num 0 delay"
between first prompt and following flush (seconds)
+.It "pl bool false start PPP login program unconditionally if"
+.Va \&pp
+is specified
+.It "pp str unused PPP login program"
.It "ps bool false line connected to a"
.Tn MICOM
port selector
.No "quit character"
.It "rp str" Ta So Li ^R Sc Ta
.No "line retype character"
+.It "rt num unused ring timeout when using"
+.Va \&ac
.It "rw bool false do"
-.Tn NOT
+.Em NOT
use raw for input, use cbreak
.It "sp num unused line speed (input and output)"
.It "su str" Ta So Li ^Z Sc Ta
.It "we str" Ta So Li ^W Sc Ta
.No "word erase character"
.It "xc bool false do
-.Tn NOT
+.Em NOT
echo control chars as
.Ql ^X
.It "xf str" Ta So Li ^S Sc Ta Dv XOFF
(stop output) character
.It "xn str" Ta So Li ^Q Sc Ta Dv XON
(start output) character
+.It "Lo str C the locale name used for \&%d in the banner message"
.El
.Pp
-The following capabilities are no longer supported by getty(8):
-.Bl -column Namexx /usr/bin/login Default
+The following capabilities are no longer supported by
+.Xr getty 8 :
+.Bl -column Name Type /usr/bin/login
.It "bd num 0 backspace delay"
.It "cb bool false use crt backspace mode"
.It "cd num 0 carriage-return delay"
.It "fd num 0 form-feed (vertical motion) delay"
+.It "lc bool false terminal has lower case"
.It "nd num 0 newline (line-feed) delay"
.It "uc bool false terminal is known upper case only"
.El
If the derivation should prove inadequate,
any (or all) of these three may be overridden
with one of the
-.Em \&c0 ,
-.Em \&c1 ,
-.Em \&c2 ,
-.Em \&i0 ,
-.Em \&i1 ,
-.Em \&i2 ,
-.Em \&l0 ,
-.Em \&l1 ,
-.Em \&l2 ,
-.Em \&o0 ,
-.Em \&o1 ,
+.Va \&c0 ,
+.Va \&c1 ,
+.Va \&c2 ,
+.Va \&i0 ,
+.Va \&i1 ,
+.Va \&i2 ,
+.Va \&l0 ,
+.Va \&l1 ,
+.Va \&l2 ,
+.Va \&o0 ,
+.Va \&o1 ,
or
-.Em \&o2
+.Va \&o2
numeric specifications, which can be used to specify
(usually in octal, with a leading '0')
the exact values of the flags.
These flags correspond to the termios
-.Em c_cflag ,
-.Em c_iflag ,
-.Em c_lflag ,
+.Va c_cflag ,
+.Va c_iflag ,
+.Va c_lflag ,
and
-.Em c_oflag
-fields, respectively. Each these sets must be completely specified to be
-effective.
+.Va c_oflag
+fields, respectively.
+Each of these sets must be completely specified to be effective.
+.Pp
The
-.Em \&f0 ,
-.Em \&f1 ,
+.Va \&f0 ,
+.Va \&f1 ,
and
-.Em \&f2
+.Va \&f2
are excepted for backwards compatibility with a previous incarnation of
-the TTY sub-system. In these flags the bottom 16 bits of the (32 bits)
+the TTY sub-system.
+In these flags the bottom 16 bits of the (32 bits)
value contain the sgttyb
-.Em sg_flags
+.Va sg_flags
field, while the top 16 bits represent the local mode word.
.Pp
Should
-.Xr getty
+.Xr getty 8
receive a null character
(presumed to indicate a line break)
it will restart using the table indicated by the
-.Em nx
-entry. If there is none, it will re-use its original table.
+.Va \&nx
+entry.
+If there is none, it will re-use its original table.
.Pp
Delays are specified in milliseconds, the nearest possible
delay available in the tty driver will be used.
choosing that particular delay algorithm from the driver.
.Pp
The
-.Em \&cl
+.Va \&cl
screen clear string may be preceded by a (decimal) number
of milliseconds of delay required (a la termcap).
This delay is simulated by repeated use of the pad character
-.Em \&pc .
+.Va \&pc .
.Pp
-The initial message, and login message,
-.Em \&im
+The initial message, login message, and initial file;
+.Va \&im ,
+.Va \&lm
and
-.Em \&lm
-may include the character sequence
-.Em \&%h
-or
-.Em \&%t
-to obtain
-the hostname or tty name respectively.
-.Pf ( Em %%
-obtains a single '%' character.)
-The hostname is normally obtained from the system,
-but may be set by the
-.Em \&hn
+.Va \&if
+may include any of the following character sequences, which expand to
+information about the environment in which
+.Xr getty 8
+is running.
+.Pp
+.Bl -tag -offset indent -width \&%xxxxxxxxxxxxxx
+.It \&%d
+The current date and time formatted according to the
+.Va \&Lo
+and
+.Va \&df
+strings.
+.It \&%h
+The hostname of the machine, which is normally obtained from the
+system using
+.Xr gethostname 3 ,
+but may also be overridden by the
+.Va \&hn
table entry.
-In either case it may be edited with
-.Em \&he .
-The
-.Em \&he
-string is a sequence of characters, each character that
-is neither '@' nor '#' is copied into the final hostname.
+In either case it may be edited with the
+.Va \&he
+string.
A '@' in the
-.Em \&he
-string, causes one character from the real hostname to
+.Va \&he
+string causes one character from the real hostname to
be copied to the final hostname.
A '#' in the
-.Em \&he
-string, causes the next character of the real hostname
+.Va \&he
+string causes the next character of the real hostname
to be skipped.
+Each character that
+is neither '@' nor '#' is copied into the final hostname.
Surplus '@' and '#' characters are ignored.
+.It \&%t
+The tty name.
+.It "\&%m, \&%r, \&%s, \&%v"
+The type of machine, release of the operating system, name of the
+operating system, and version of the kernel, respectively, as
+returned by
+.Xr uname 3 .
+.It \&%%
+A
+.Dq %
+character.
+.El
.Pp
When getty execs the login process, given
in the
-.Em \&lo
+.Va \&lo
string (usually
.Dq Pa /usr/bin/login ) ,
it will have set
the environment to include the terminal type, as indicated
by the
-.Em \&tt
+.Va \&tt
string (if it exists).
The
-.Em \&ev
+.Va \&ev
string, can be used to enter additional data into
the environment.
It is a list of comma separated strings, each of which
will presumably be of the form
-.Em name=value .
+.Li name=value .
.Pp
If a non-zero timeout is specified, with
-.Em \&to ,
+.Va \&to ,
then getty will exit within the indicated
number of seconds, either having
received a login name and passed control
to
-.Xr login ,
+.Xr login 1 ,
or having received an alarm signal, and exited.
This may be useful to hangup dial in lines.
.Pp
Output from
-.Xr getty
+.Xr getty 8
is even parity unless
-.Em \&op
+.Va \&op
or
-.Em \&np
+.Va \&np
is specified.
The
-.Em \&op
+.Va \&op
string
may be specified with
-.Em \&ap
+.Va \&ap
to allow any parity on input, but generate odd parity output.
Note: this only applies while getty is being run,
terminal driver limitations prevent a more complete
implementation.
-.Xr Getty
-does not check parity of input characters in
+The
+.Xr getty 8
+utility does not check parity of input characters in
.Dv RAW
mode.
+.Pp
+If a
+.Va \&pp
+string is specified and a PPP link bring-up sequence is recognized,
+getty will invoke the program referenced by the
+.Va \&pp
+option.
+This can be used to handle incoming PPP calls.
+If the
+.Va \&pl
+option is true as well,
+.Xr getty 8
+will skip the user name prompt and the PPP detection phase, and will
+invoke the program specified by
+.Va \&pp
+instantly.
+.Pp
+.Nm Getty
+provides some basic intelligent modem handling by providing a chat
+script feature available via two capabilities:
+.Pp
+.Bl -tag -offset indent -width \&xxxxxxxx -compact
+.It ic
+Chat script to initialize modem.
+.It ac
+Chat script to answer a call.
+.El
+.Pp
+A chat script is a set of expect/send string pairs.
+When a chat string starts,
+.Nm getty
+will wait for the first string, and if it finds it, will send the
+second, and so on.
+Strings specified are separated by one or more tabs or spaces.
+Strings may contain standard ASCII characters and special 'escapes',
+which consist of a backslash character followed by one or more
+characters which are interpreted as follows:
+.Pp
+.Bl -tag -offset indent -width \&xxxxxxxx -compact
+.It \ea
+bell character.
+.It \eb
+backspace.
+.It \en
+newline.
+.It \ee
+escape.
+.It \ef
+formfeed.
+.It \ep
+half-second pause.
+.It \er
+carriage return.
+.It \eS , \es
+space character.
+.It \et
+tab.
+.It \exNN
+hexadecimal byte value.
+.It \e0NNN
+octal byte value.
+.El
+.Pp
+Note that the
+.Ql \ep
+sequence is only valid for send strings and causes a half-second
+pause between sending the previous and next characters.
+Hexadecimal values are, at most, 2 hex digits long, and octal
+values are a maximum of 3 octal digits.
+.Pp
+The
+.Va \&ic
+chat sequence is used to initialize a modem or similar device.
+A typical example of an init chat script for a modem with a
+hayes compatible command set might look like this:
+.Pp
+.Dl :ic="" ATE0Q0V1\er OK\er ATS0=0\er OK\er:
+.Pp
+This script waits for nothing (which always succeeds), sends
+a sequence to ensure that the modem is in the correct mode
+(suppress command echo, send responses in verbose mode),
+and then disables auto-answer.
+It waits for an "OK" response before it terminates.
+The init sequence is used to check modem responses to ensure that
+the modem is functioning correctly.
+If the init script fails to complete,
+.Nm getty
+considers this to be fatal, and results in an error logged via
+.Xr syslogd 8 ,
+and exiting.
+.Pp
+Similarly, an answer chat script is used to manually answer the
+phone in response to (usually) a "RING".
+When run with an answer script,
+.Nm getty
+opens the port in non-blocking mode, clears any extraneous input
+and waits for data on the port.
+As soon as any data is available, the answer chat script is
+started and scanned for a string, and responds according to
+the answer chat script.
+With a hayes compatible modem, this would normally look something
+like:
+.Pp
+.Dl :ac=RING\er ATA\er CONNECT:
+.Pp
+This causes the modem to answer the call via the "ATA" command,
+then scans input for a "CONNECT" string.
+If this is received before a
+.Va \&ct
+timeout, then a normal login sequence commences.
+.Pp
+The
+.Va \&ct
+capability specifies a timeout for all send and expect strings.
+This timeout is set individually for each expect wait and send
+string and must be at least as long as the time it takes for
+a connection to be established between a remote and local
+modem (usually around 10 seconds).
+.Pp
+In most situations, you will want to flush any additional
+input after the connection has been detected, and the
+.Va \&de
+capability may be used to do that, as well as delay for a
+short time after the connection has been established during
+which all of the connection data has been sent by the modem.
.Sh SEE ALSO
.Xr login 1 ,
+.Xr gethostname 3 ,
+.Xr uname 3 ,
.Xr termcap 5 ,
-.Xr getty 8 .
+.Xr getty 8 ,
+.Xr telnetd 8
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 4.2 .
.Sh BUGS
The special characters (erase, kill, etc.) are reset to system defaults
by
The terminal driver should support sane delay settings.
.Pp
The
-.Em \&he
+.Va \&he
capability is stupid.
.Pp
The
-.Xr termcap
+.Xr termcap 5
format is horrid, something more rational should
have been chosen.
.Pp
This should be converted to use
.Xr termios 4 .
-.Sh HISTORY
-The
-.Nm gettytab
-file format appeared in 4.2BSD.
-/*
- * 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) 1983, 1993, 1994
* The Regents of the University of California. All rights reserved.
* SUCH DAMAGE.
*
* from: @(#)gettytab.h 8.2 (Berkeley) 3/30/94
- * $Id: gettytab.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ * $FreeBSD: src/libexec/getty/gettytab.h,v 1.14 2003/06/10 18:30:41 yar Exp $
*/
/*
* Getty description definitions.
*/
struct gettystrs {
- char *field; /* name to lookup in gettytab */
+ const char *field; /* name to lookup in gettytab */
char *defalt; /* value we find by looking in defaults */
char *value; /* value that we find there */
};
struct gettynums {
- char *field; /* name to lookup */
+ const char *field; /* name to lookup */
long defalt; /* number we find in defaults */
long value; /* number we find there */
int set; /* we actually got this one */
};
struct gettyflags {
- char *field; /* name to lookup */
+ const char *field; /* name to lookup */
char invrt; /* name existing in gettytab --> false */
char defalt; /* true/false in defaults */
char value; /* true/false flag */
#define FL gettystrs[21].value
#define WE gettystrs[22].value
#define LN gettystrs[23].value
+#define Lo gettystrs[24].value
+#define PP gettystrs[25].value
+#define IF gettystrs[26].value
+#define IC gettystrs[27].value
+#define AC gettystrs[28].value
+#define AL gettystrs[29].value
+#define DF gettystrs[30].value
/*
* Numeric definitions.
#define O1set gettynums[23].set
#define O2 gettynums[24].value
#define O2set gettynums[24].set
+#define DE gettynums[25].value
+#define RTset gettynums[26].set
+#define RT gettynums[26].value
+#define CT gettynums[27].value
+#define DC gettynums[28].value
/*
* Boolean values.
#define AB gettyflags[19].value
#define DX gettyflags[20].value
#define NP gettyflags[21].value
+#define NPset gettyflags[21].set
#define MB gettyflags[22].value
-
-int getent __P((char *, char *));
-long getnum __P((char *));
-int getflag __P((char *));
-char *getstr __P((char *, char **));
-
-extern struct gettyflags gettyflags[];
-extern struct gettynums gettynums[];
-extern struct gettystrs gettystrs[];
-extern int hopcount;
+#define HW gettyflags[23].value
+#define NC gettyflags[24].value
+#define PL gettyflags[25].value
-/*
- * 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) 1983, 1993
* The Regents of the University of California. All rights reserved.
*/
#ifndef lint
-/*static char sccsid[] = "from: @(#)init.c 8.1 (Berkeley) 6/4/93";*/
-static char rcsid[] = "$Id: init.c,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $";
+#if 0
+static char sccsid[] = "@(#)from: init.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$FreeBSD: src/libexec/getty/init.c,v 1.16 2005/04/06 17:42:24 stefanf Exp $";
#endif /* not lint */
/*
*/
#include <termios.h>
#include "gettytab.h"
+#include "extern.h"
#include "pathnames.h"
-extern struct termios tmode;
-extern char hostname[];
+static char loginmsg[] = "login: ";
+static char nullstr[] = "";
+static char loginprg[] = _PATH_LOGIN;
+static char datefmt[] = "%+";
struct gettystrs gettystrs[] = {
{ "nx" }, /* next table */
{ "cl" }, /* screen clear characters */
{ "im" }, /* initial message */
- { "lm", "login: " }, /* login message */
- { "er", &tmode.c_cc[VERASE] }, /* erase character */
- { "kl", &tmode.c_cc[VKILL] }, /* kill character */
- { "et", &tmode.c_cc[VEOF] }, /* eof chatacter (eot) */
- { "pc", "" }, /* pad character */
+ { "lm", loginmsg }, /* login message */
+ { "er", (char*)&omode.c_cc[VERASE] }, /* erase character */
+ { "kl", (char*)&omode.c_cc[VKILL] }, /* kill character */
+ { "et", (char*)&omode.c_cc[VEOF] }, /* eof chatacter (eot) */
+ { "pc", nullstr }, /* pad character */
{ "tt" }, /* terminal type */
{ "ev" }, /* enviroment */
- { "lo", _PATH_LOGIN }, /* login program */
+ { "lo", loginprg }, /* login program */
{ "hn", hostname }, /* host name */
{ "he" }, /* host name edit */
- { "in", &tmode.c_cc[VINTR] }, /* interrupt char */
- { "qu", &tmode.c_cc[VQUIT] }, /* quit char */
- { "xn", &tmode.c_cc[VSTART] }, /* XON (start) char */
- { "xf", &tmode.c_cc[VSTOP] }, /* XOFF (stop) char */
- { "bk", &tmode.c_cc[VEOL] }, /* brk char (alt \n) */
- { "su", &tmode.c_cc[VSUSP] }, /* suspend char */
- { "ds", &tmode.c_cc[VDSUSP] }, /* delayed suspend */
- { "rp", &tmode.c_cc[VREPRINT] },/* reprint char */
- { "fl", &tmode.c_cc[VDISCARD] },/* flush output */
- { "we", &tmode.c_cc[VWERASE] }, /* word erase */
- { "ln", &tmode.c_cc[VLNEXT] }, /* literal next */
+ { "in", (char*)&omode.c_cc[VINTR] }, /* interrupt char */
+ { "qu", (char*)&omode.c_cc[VQUIT] }, /* quit char */
+ { "xn", (char*)&omode.c_cc[VSTART] }, /* XON (start) char */
+ { "xf", (char*)&omode.c_cc[VSTOP] }, /* XOFF (stop) char */
+ { "bk", (char*)&omode.c_cc[VEOL] }, /* brk char (alt \n) */
+ { "su", (char*)&omode.c_cc[VSUSP] }, /* suspend char */
+ { "ds", (char*)&omode.c_cc[VDSUSP] }, /* delayed suspend */
+ { "rp", (char*)&omode.c_cc[VREPRINT] },/* reprint char */
+ { "fl", (char*)&omode.c_cc[VDISCARD] },/* flush output */
+ { "we", (char*)&omode.c_cc[VWERASE] }, /* word erase */
+ { "ln", (char*)&omode.c_cc[VLNEXT] }, /* literal next */
+ { "Lo" }, /* locale for strftime() */
+ { "pp" }, /* ppp login program */
+ { "if" }, /* sysv-like 'issue' filename */
+ { "ic" }, /* modem init-chat */
+ { "ac" }, /* modem answer-chat */
+ { "al" }, /* user to auto-login */
+ { "df", datefmt}, /* format for strftime() */
{ 0 }
};
{ "o0" }, /* output o_flags */
{ "o1" }, /* input o_flags */
{ "o2" }, /* user mode o_flags */
- { 0 }
+ { "de" }, /* delay before sending 1st prompt */
+ { "rt" }, /* reset timeout */
+ { "ct" }, /* chat script timeout */
+ { "dc" }, /* debug chat script value */
+ { 0 }
};
+
struct gettyflags gettyflags[] = {
{ "ht", 0 }, /* has tabs */
{ "dx", 0 }, /* set decctlq */
{ "np", 0 }, /* no parity at all (8bit chars) */
{ "mb", 0 }, /* do MDMBUF flow control */
+ { "hw", 0 }, /* do CTSRTS flow control */
+ { "nc", 0 }, /* set clocal (no carrier) */
+ { "pl", 0 }, /* use PPP instead of login(1) */
{ 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) 1980, 1993
* The Regents of the University of California. All rights reserved.
+ * Portions copyright (c) 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
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
+static const char copyright[] =
"@(#) Copyright (c) 1980, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/
-static char rcsid[] = "$Id: main.c,v 1.3 2004/08/26 00:32:22 lindak Exp $";
+#if 0
+static char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93";
+#endif
+static const char rcsid[] =
+ "$FreeBSD: src/libexec/getty/main.c,v 1.47 2005/04/06 17:42:24 stefanf Exp $";
#endif /* not lint */
#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/termios.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/ttydefaults.h>
#include <sys/utsname.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <time.h>
+
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
+#include <locale.h>
+#include <libutil.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <termios.h>
#include <time.h>
#include <unistd.h>
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
#include "gettytab.h"
-#include "pathnames.h"
#include "extern.h"
+#include "pathnames.h"
/*
* Set the amount of running time that getty should accumulate
*/
#define GETTY_TIMEOUT 60 /* seconds */
-struct termios tmode, omode;
+#undef CTRL
+#define CTRL(x) (x&037)
+
+/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
+
+#define PPP_FRAME 0x7e /* PPP Framing character */
+#define PPP_STATION 0xff /* "All Station" character */
+#define PPP_ESCAPE 0x7d /* Escape Character */
+#define PPP_CONTROL 0x03 /* PPP Control Field */
+#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
+#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
+#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
+
+/* original mode; flags've been reset using values from <sys/ttydefaults.h> */
+struct termios omode;
+/* current mode */
+struct termios tmode;
int crmod, digit, lower, upper;
char hostname[MAXHOSTNAMELEN];
-struct utsname kerninfo;
-char name[MAXLOGNAME+1];
+char name[MAXLOGNAME*3];
char dev[] = _PATH_DEV;
char ttyn[32];
-char *portselector();
-char *ttyname();
#define OBUFSIZ 128
#define TABBUFSIZ 512
char defent[TABBUFSIZ];
char tabent[TABBUFSIZ];
+const char *tname;
char *env[128];
#define KILL tmode.c_cc[VKILL]
#define EOT tmode.c_cc[VEOF]
+#define puts Gputs
+
+static void defttymode(void);
+static void dingdong(int);
+static void dogettytab(void);
+static int getname(void);
+static void interrupt(int);
+static void oflush(void);
+static void prompt(void);
+static void putchr(int);
+static void putf(const char *);
+static void putpad(const char *);
+static void puts(const char *);
+static void timeoverrun(int);
+static char *getline(int);
+static void setttymode(int);
+static int opentty(const char *, int);
+
jmp_buf timeout;
static void
-dingdong()
+dingdong(int signo __unused)
{
-
alarm(0);
- signal(SIGALRM, SIG_DFL);
longjmp(timeout, 1);
}
jmp_buf intrupt;
static void
-interrupt()
+interrupt(int signo __unused)
{
-
- signal(SIGINT, interrupt);
longjmp(intrupt, 1);
}
/*
* Action to take when getty is running too long.
*/
-void
-timeoverrun(signo)
- int signo;
+static void
+timeoverrun(int signo __unused)
{
- syslog(LOG_ERR, "getty exiting due to excessive running time\n");
+ syslog(LOG_ERR, "getty exiting due to excessive running time");
exit(1);
}
-static int getname __P((void));
-static void oflush __P((void));
-static void prompt __P((void));
-static void putchr __P((int));
-static void putf __P((char *));
-static void putpad __P((char *));
-static void puts __P((char *));
-
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
- extern char **environ;
- char *tname;
- long allflags;
- int repcnt = 0;
+ extern char **environ;
+ int first_sleep = 1, first_time = 1;
struct rlimit limit;
- int ttyopenmode;
+ int rval;
+#ifdef __APPLE__
+ int ttyopenmode = O_RDWR;
+#endif
signal(SIGINT, SIG_IGN);
-/*
- signal(SIGQUIT, SIG_DFL);
-*/
- openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
- gethostname(hostname, sizeof(hostname));
+ signal(SIGQUIT, SIG_IGN);
+
+ openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
+ gethostname(hostname, sizeof(hostname) - 1);
+ hostname[sizeof(hostname) - 1] = '\0';
if (hostname[0] == '\0')
strcpy(hostname, "Amnesiac");
- uname(&kerninfo);
/*
* Limit running time to deal with broken or dead lines.
limit.rlim_cur = GETTY_TIMEOUT;
(void)setrlimit(RLIMIT_CPU, &limit);
+ gettable("default", defent);
+ gendefaults();
+ tname = "default";
+ if (argc > 1)
+ tname = argv[1];
+
/*
* The following is a work around for vhangup interactions
* which cause great problems getting window systems started.
* If the tty line is "-", we do the old style getty presuming
- * that the file descriptors are already set up for us.
+ * that the file descriptors are already set up for us.
* J. Gettys - MIT Project Athena.
*/
if (argc <= 2 || strcmp(argv[2], "-") == 0)
- strcpy(ttyn, ttyname(0));
+#ifdef __APPLE__
+ {
+ // <rdar://problem/5178373>
+ char* n = ttyname(STDIN_FILENO);
+ if (n) {
+ strlcpy(ttyn, n, sizeof(ttyn));
+ } else {
+ syslog(LOG_ERR, "ttyname %m");
+ exit(1);
+ }
+ }
+#else
+ strcpy(ttyn, ttyname(STDIN_FILENO));
+#endif
else {
- int i;
-
strcpy(ttyn, dev);
strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
if (strcmp(argv[0], "+") != 0) {
chown(ttyn, 0, 0);
chmod(ttyn, 0600);
revoke(ttyn);
+
+ /*
+ * Do the first scan through gettytab.
+ * Terminal mode parameters will be wrong until
+ * defttymode() called, but they're irrelevant for
+ * the initial setup of the terminal device.
+ */
+ dogettytab();
+
+#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
+ if (strncmp(ttyn, _PATH_CONSOLE, sizeof(ttyn)) == 0)
+ ttyopenmode |= O_POPUP;
+#endif
/*
- * Delay the open so DTR stays down long enough to be detected.
+ * Init or answer modem sequence has been specified.
*/
- sleep(2);
+ if (IC || AC) {
#ifdef __APPLE__
- ttyopenmode = ((strcmp(ttyn, _PATH_CONSOLE)==0)
- ? (O_RDWR |O_POPUP): O_RDWR);
-#else /* __APPLE __ */
- ttyopenmode = O_RDWR;
-#endif /* __APPLE__ */
-
- while ((i = open(ttyn, ttyopenmode)) == -1) {
- if (repcnt % 10 == 0) {
- syslog(LOG_ERR, "%s: %m", ttyn);
- closelog();
+ if (!opentty(ttyn, ttyopenmode))
+#else
+ if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
+#endif
+ exit(1);
+ defttymode();
+ setttymode(1);
+ }
+
+ if (IC) {
+ if (getty_chat(IC, CT, DC) > 0) {
+ syslog(LOG_ERR, "modem init problem on %s", ttyn);
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
+ exit(1);
}
- repcnt++;
- sleep(60);
}
- login_tty(i);
- }
- }
- /* Start with default tty settings */
- if (tcgetattr(0, &tmode) < 0) {
- syslog(LOG_ERR, "%s: %m", ttyn);
- exit(1);
+ if (AC) {
+ int i, rfds;
+ struct timeval to;
+
+ rfds = 1 << 0; /* FD_SET */
+ to.tv_sec = RT;
+ to.tv_usec = 0;
+ i = select(32, (fd_set*)&rfds, (fd_set*)NULL,
+ (fd_set*)NULL, RT ? &to : NULL);
+ if (i < 0) {
+ syslog(LOG_ERR, "select %s: %m", ttyn);
+ } else if (i == 0) {
+ syslog(LOG_NOTICE, "recycle tty %s", ttyn);
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
+ exit(0); /* recycle for init */
+ }
+ i = getty_chat(AC, CT, DC);
+ if (i > 0) {
+ syslog(LOG_ERR, "modem answer problem on %s", ttyn);
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
+ exit(1);
+ }
+ } else { /* maybe blocking open */
+#ifdef __APPLE__
+ if (!opentty(ttyn, ttyopenmode | (NC ? O_NONBLOCK : 0 )))
+#else
+ if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 )))
+#endif
+ exit(1);
+ }
+ }
}
- omode = tmode;
- gettable("default", defent);
- gendefaults();
- tname = "default";
- if (argc > 1)
- tname = argv[1];
+ defttymode();
for (;;) {
- int off;
-
- gettable(tname, tabent);
- if (OPset || EPset || APset)
- APset++, OPset++, EPset++;
- setdefaults();
- off = 0;
- ioctl(0, TIOCFLUSH, &off); /* clear out the crap */
- ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
- ioctl(0, FIOASYNC, &off); /* ditto for async mode */
-
- if (IS)
- cfsetispeed(&tmode, IS);
- else if (SP)
- cfsetispeed(&tmode, SP);
- if (OS)
- cfsetospeed(&tmode, OS);
- else if (SP)
- cfsetospeed(&tmode, SP);
- setflags(0);
- setchars();
- if (tcsetattr(0, TCSANOW, &tmode) < 0) {
- syslog(LOG_ERR, "%s: %m", ttyn);
- exit(1);
+
+ /*
+ * if a delay was specified then sleep for that
+ * number of seconds before writing the initial prompt
+ */
+ if (first_sleep && DE) {
+ sleep(DE);
+ /* remove any noise */
+ (void)tcflush(STDIN_FILENO, TCIOFLUSH);
}
- if (AB) {
- extern char *autobaud();
+ first_sleep = 0;
+ setttymode(0);
+ if (AB) {
tname = autobaud();
+ dogettytab();
continue;
}
if (PS) {
tname = portselector();
+ dogettytab();
continue;
}
if (CL && *CL)
putpad(CL);
edithost(HE);
- if (IM && *IM)
+
+ /* if this is the first time through this, and an
+ issue file has been given, then send it */
+ if (first_time && IF) {
+ int fd;
+
+ if ((fd = open(IF, O_RDONLY)) != -1) {
+ char * cp;
+
+ while ((cp = getline(fd)) != NULL) {
+ putf(cp);
+ }
+ close(fd);
+ }
+ }
+ first_time = 0;
+
+ if (IM && *IM && !(PL && PP))
putf(IM);
if (setjmp(timeout)) {
- tmode.c_ispeed = tmode.c_ospeed = 0;
- (void)tcsetattr(0, TCSANOW, &tmode);
+ cfsetispeed(&tmode, B0);
+ cfsetospeed(&tmode, B0);
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
exit(1);
}
if (TO) {
signal(SIGALRM, dingdong);
alarm(TO);
}
- if (getname()) {
- register int i;
+
+ rval = 0;
+ if (AL) {
+ const char *p = AL;
+ char *q = name;
+
+ while (*p && q < &name[sizeof name - 1]) {
+ if (isupper(*p))
+ upper = 1;
+ else if (islower(*p))
+ lower = 1;
+ else if (isdigit(*p))
+ digit = 1;
+ *q++ = *p++;
+ }
+ } else if (!(PL && PP))
+ rval = getname();
+ if (rval == 2 || (PL && PP)) {
+ oflush();
+ alarm(0);
+ limit.rlim_max = RLIM_INFINITY;
+ limit.rlim_cur = RLIM_INFINITY;
+ (void)setrlimit(RLIMIT_CPU, &limit);
+ execle(PP, "ppplogin", ttyn, (char *) 0, env);
+ syslog(LOG_ERR, "%s: %m", PP);
+ exit(1);
+ } else if (rval || AL) {
+ int i;
oflush();
alarm(0);
signal(SIGALRM, SIG_DFL);
+ if (name[0] == '\0')
+ continue;
if (name[0] == '-') {
puts("user names may not start with '-'.");
continue;
}
- if (!(upper || lower || digit))
- continue;
- setflags(2);
+ if (!(upper || lower || digit)) {
+ if (AL) {
+ syslog(LOG_ERR,
+ "invalid auto-login name: %s", AL);
+ exit(1);
+ } else
+ continue;
+ }
+ set_flags(2);
if (crmod) {
tmode.c_iflag |= ICRNL;
tmode.c_oflag |= ONLCR;
}
-#if XXX
+#if REALLY_OLD_TTYS
if (upper || UC)
tmode.sg_flags |= LCASE;
if (lower || LC)
tmode.sg_flags &= ~LCASE;
#endif
- if (tcsetattr(0, TCSANOW, &tmode) < 0) {
- syslog(LOG_ERR, "%s: %m", ttyn);
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
+ syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
exit(1);
}
signal(SIGINT, SIG_DFL);
limit.rlim_max = RLIM_INFINITY;
limit.rlim_cur = RLIM_INFINITY;
(void)setrlimit(RLIMIT_CPU, &limit);
- execle(LO, "login", "-p1", name, (char *) 0, env);
+#ifdef __APPLE__
+ // <rdar://problem/3205179>
+ execle(LO, "login", AL ? "-fp1" : "-p1", name,
+#else
+ execle(LO, "login", AL ? "-fp" : "-p", name,
+#endif
+ (char *) 0, env);
syslog(LOG_ERR, "%s: %m", LO);
exit(1);
}
alarm(0);
signal(SIGALRM, SIG_DFL);
signal(SIGINT, SIG_IGN);
- if (NX && *NX)
+ if (NX && *NX) {
tname = NX;
+ dogettytab();
+ }
+ }
+}
+
+static int
+opentty(const char *tty, int flags)
+{
+ int i;
+ int failopenlogged = 0;
+
+ while ((i = open(tty, flags)) == -1)
+ {
+ if (!failopenlogged) {
+ syslog(LOG_ERR, "open %s: %m", tty);
+ failopenlogged = 1;
+ }
+ sleep(60);
+ }
+ if (login_tty(i) < 0) {
+#ifndef __APPLE__
+ if (daemon(0,0) < 0) {
+ syslog(LOG_ERR,"daemon: %m");
+ close(i);
+ return 0;
+ }
+#endif
+ if (login_tty(i) < 0) {
+ syslog(LOG_ERR, "login_tty %s: %m", tty);
+ close(i);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void
+defttymode()
+{
+
+ /* Start with default tty settings. */
+ if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
+ syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
+ exit(1);
+ }
+ omode = tmode; /* fill c_cc for dogettytab() */
+ dogettytab();
+ /*
+ * Don't rely on the driver too much, and initialize crucial
+ * things according to <sys/ttydefaults.h>. Avoid clobbering
+ * the c_cc[] settings however, the console drivers might wish
+ * to leave their idea of the preferred VERASE key value
+ * there.
+ */
+ tmode.c_iflag = TTYDEF_IFLAG;
+ tmode.c_oflag = TTYDEF_OFLAG;
+ tmode.c_lflag = TTYDEF_LFLAG;
+ tmode.c_cflag = TTYDEF_CFLAG;
+ if (NC)
+ tmode.c_cflag |= CLOCAL;
+ omode = tmode;
+}
+
+static void
+setttymode(int raw)
+{
+ int off = 0;
+
+ (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
+ ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
+ ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
+
+ if (IS)
+ cfsetispeed(&tmode, speed(IS));
+ else if (SP)
+ cfsetispeed(&tmode, speed(SP));
+ if (OS)
+ cfsetospeed(&tmode, speed(OS));
+ else if (SP)
+ cfsetospeed(&tmode, speed(SP));
+ set_flags(0);
+ setchars();
+ if (raw)
+ cfmakeraw(&tmode);
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
+ syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
+ exit(1);
}
}
+
static int
-getname()
+getname(void)
{
- register int c;
- register char *np;
- char cs;
+ int c;
+ char *np;
+ unsigned char cs;
+ int ppp_state = 0;
+ int ppp_connection = 0;
/*
* Interrupt may happen if we use CBREAK mode
return (0);
}
signal(SIGINT, interrupt);
- setflags(1);
+ set_flags(1);
prompt();
+ oflush();
if (PF > 0) {
- oflush();
sleep(PF);
PF = 0;
}
- if (tcsetattr(0, TCSANOW, &tmode) < 0) {
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
syslog(LOG_ERR, "%s: %m", ttyn);
exit(1);
}
exit(0);
if ((c = cs&0177) == 0)
return (0);
- if (c == EOT)
- exit(1);
+
+ /* PPP detection state machine..
+ Look for sequences:
+ PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
+ PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
+ See RFC1662.
+ Derived from code from Michael Hancock, <michaelh@cet.co.jp>
+ and Erik 'PPP' Olson, <eriko@wrq.com>
+ */
+
+ if (PP && (cs == PPP_FRAME)) {
+ ppp_state = 1;
+ } else if (ppp_state == 1 && cs == PPP_STATION) {
+ ppp_state = 2;
+ } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
+ ppp_state = 3;
+ } else if ((ppp_state == 2 && cs == PPP_CONTROL)
+ || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
+ ppp_state = 4;
+ } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
+ ppp_state = 5;
+ } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
+ ppp_connection = 1;
+ break;
+ } else {
+ ppp_state = 0;
+ }
+
+ if (c == EOT || c == CTRL('d'))
+ exit(0);
if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
putf("\r\n");
break;
lower = 1;
else if (isupper(c))
upper = 1;
- else if (c == ERASE || c == '#' || c == '\b') {
+ else if (c == ERASE || c == '\b' || c == 0177) {
if (np > name) {
np--;
if (cfgetospeed(&tmode) >= 1200)
putchr(cs);
}
continue;
- } else if (c == KILL || c == '@') {
- putchr(cs);
+ } else if (c == KILL || c == CTRL('u')) {
putchr('\r');
if (cfgetospeed(&tmode) < 1200)
putchr('\n');
else if (np > name)
puts(" \r");
prompt();
+ digit = lower = upper = 0;
np = name;
continue;
} else if (isdigit(c))
- digit++;
+ digit = 1;
if (IG && (c <= ' ' || c > 0176))
continue;
*np++ = c;
*np = 0;
if (c == '\r')
crmod = 1;
- if (upper && !lower && !LC || UC)
+ if ((upper && !lower && !LC) || UC)
for (np = name; *np; np++)
if (isupper(*np))
*np = tolower(*np);
- return (1);
+ return (1 + ppp_connection);
}
static void
-putpad(s)
- register char *s;
+putpad(const char *s)
{
- register pad = 0;
+ int pad = 0;
speed_t ospeed = cfgetospeed(&tmode);
if (isdigit(*s)) {
}
static void
-puts(s)
- register char *s;
+puts(const char *s)
{
while (*s)
putchr(*s++);
int obufcnt = 0;
static void
-putchr(cc)
- int cc;
+putchr(int cc)
{
char c;
}
static void
-oflush()
+oflush(void)
{
if (obufcnt)
write(STDOUT_FILENO, outbuf, obufcnt);
}
static void
-prompt()
+prompt(void)
{
putf(LM);
putchr('\n');
}
+
+static char *
+getline(int fd)
+{
+ int i = 0;
+ static char linebuf[512];
+
+ /*
+ * This is certainly slow, but it avoids having to include
+ * stdio.h unnecessarily. Issue files should be small anyway.
+ */
+ while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
+ if (linebuf[i] == '\n') {
+ /* Don't rely on newline mode, assume raw */
+ linebuf[i++] = '\r';
+ linebuf[i++] = '\n';
+ linebuf[i] = '\0';
+ return linebuf;
+ }
+ ++i;
+ }
+ linebuf[i] = '\0';
+ return i ? linebuf : 0;
+}
+
static void
-putf(cp)
- register char *cp;
+putf(const char *cp)
{
extern char editedhost[];
time_t t;
char *slash, db[100];
+ static struct utsname kerninfo;
+
+ if (!*kerninfo.sysname)
+ uname(&kerninfo);
+
while (*cp) {
if (*cp != '%') {
putchr(*cp++);
break;
case 'd': {
- static char fmt[] = "%l:% %P on %A, %d %B %Y";
-
- fmt[4] = 'M'; /* I *hate* SCCS... */
+ t = (time_t)0;
(void)time(&t);
- (void)strftime(db, sizeof(db), fmt, localtime(&t));
+ if (Lo)
+ (void)setlocale(LC_TIME, Lo);
+ (void)strftime(db, sizeof(db), DF, localtime(&t));
puts(db);
break;
cp++;
}
}
+
+/*
+ * Read a gettytab database entry and perform necessary quirks.
+ */
+static void
+dogettytab()
+{
+
+ /* Read the database entry. */
+ gettable(tname, tabent);
+
+ /*
+ * Avoid inheriting the parity values from the default entry
+ * if any of them is set in the current entry.
+ * Mixing different parity settings is unreasonable.
+ */
+ if (OPset || EPset || APset || NPset)
+ OPset = EPset = APset = NPset = 1;
+
+ /* Fill in default values for unset capabilities. */
+ setdefaults();
+}
-/*
- * 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) 1989, 1993
* The Regents of the University of California. All rights reserved.
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 8.1 (Berkeley) 6/4/93
- * $Id: pathnames.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ * $FreeBSD: src/libexec/getty/pathnames.h,v 1.7 1999/08/28 00:09:36 peter Exp $
*/
#include <paths.h>
-/*
- * 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) 1983, 1993
* The Regents of the University of California. All rights reserved.
*/
#ifndef lint
-/*static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";*/
-static char rcsid[] = "$Id: subr.c,v 1.2 2004/09/30 22:57:04 lindak Exp $";
+#if 0
+static char sccsid[] = "@(#)from: subr.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$FreeBSD: src/libexec/getty/subr.c,v 1.19 2004/06/25 10:11:28 phk Exp $";
#endif /* not lint */
/*
* Melbourne getty.
*/
-#define COMPAT_43_TTY 1
+#ifdef DEBUG
+#include <stdio.h>
+#endif
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
#include <termios.h>
+#include <unistd.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <syslog.h>
#include "gettytab.h"
#include "pathnames.h"
#include "extern.h"
-extern struct termios tmode, omode;
-static void compatflags __P((long));
/*
* Get a table entry.
*/
void
-gettable(name, buf)
- char *name, *buf;
+gettable(const char *name, char *buf)
{
- register struct gettystrs *sp;
- register struct gettynums *np;
- register struct gettyflags *fp;
+ struct gettystrs *sp;
+ struct gettynums *np;
+ struct gettyflags *fp;
long n;
- char *dba[2];
+ int l;
+ char *p;
+ char *msg = NULL;
+ const char *dba[2];
+
+ static int firsttime = 1;
+
dba[0] = _PATH_GETTYTAB;
dba[1] = 0;
- if (cgetent(&buf, dba, name) != 0)
+ if (firsttime) {
+ /*
+ * we need to strdup() anything in the strings array
+ * initially in order to simplify things later
+ */
+ for (sp = gettystrs; sp->field; sp++)
+ if (sp->value != NULL) {
+ /* handle these ones more carefully */
+ if (sp >= &gettystrs[4] && sp <= &gettystrs[6])
+ l = 2;
+ else
+ l = strlen(sp->value) + 1;
+ if ((p = malloc(l)) != NULL) {
+ strncpy(p, sp->value, l);
+ p[l-1] = '\0';
+ }
+ /*
+ * replace, even if NULL, else we'll
+ * have problems with free()ing static mem
+ */
+ sp->value = p;
+ }
+ firsttime = 0;
+ }
+
+ switch (cgetent(&buf, (char **)dba, (char *)name)) {
+ case 1:
+ msg = "%s: couldn't resolve 'tc=' in gettytab '%s'";
+ case 0:
+ break;
+ case -1:
+ msg = "%s: unknown gettytab entry '%s'";
+ break;
+ case -2:
+ msg = "%s: retrieving gettytab entry '%s': %m";
+ break;
+ case -3:
+ msg = "%s: recursive 'tc=' reference gettytab entry '%s'";
+ break;
+ default:
+ msg = "%s: unexpected cgetent() error for entry '%s'";
+ break;
+ }
+
+ if (msg != NULL) {
+ syslog(LOG_ERR, msg, "getty", name);
return;
+ }
+
+ for (sp = gettystrs; sp->field; sp++) {
+ if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) {
+ if (sp->value) {
+ /* prefer existing value */
+ if (strcmp(p, sp->value) != 0)
+ free(sp->value);
+ else {
+ free(p);
+ p = sp->value;
+ }
+ }
+ sp->value = p;
+ } else if (l == -1) {
+ free(sp->value);
+ sp->value = NULL;
+ }
+ }
- for (sp = gettystrs; sp->field; sp++)
- cgetstr(buf, sp->field, &sp->value);
for (np = gettynums; np->field; np++) {
- if (cgetnum(buf, np->field, &n) == -1)
+ if (cgetnum(buf, (char*)np->field, &n) == -1)
np->set = 0;
else {
np->set = 1;
np->value = n;
}
}
+
for (fp = gettyflags; fp->field; fp++) {
- if (cgetcap(buf, fp->field, ':') == NULL)
+ if (cgetcap(buf, (char *)fp->field, ':') == NULL)
fp->set = 0;
else {
fp->set = 1;
fp->value = 1 ^ fp->invrt;
}
}
+
#ifdef DEBUG
- printf("name=\"%s\", buf=\"%s\"\n", name, buf);
+ printf("name=\"%s\", buf=\"%s\"\r\n", name, buf);
for (sp = gettystrs; sp->field; sp++)
- printf("cgetstr: %s=%s\n", sp->field, sp->value);
+ printf("cgetstr: %s=%s\r\n", sp->field, sp->value);
for (np = gettynums; np->field; np++)
- printf("cgetnum: %s=%d\n", np->field, np->value);
+ printf("cgetnum: %s=%d\r\n", np->field, np->value);
for (fp = gettyflags; fp->field; fp++)
- printf("cgetflags: %s='%c' set='%c'\n", fp->field,
+ printf("cgetflags: %s='%c' set='%c'\r\n", fp->field,
fp->value + '0', fp->set + '0');
- exit(1);
#endif /* DEBUG */
}
void
-gendefaults()
+gendefaults(void)
{
- register struct gettystrs *sp;
- register struct gettynums *np;
- register struct gettyflags *fp;
+ struct gettystrs *sp;
+ struct gettynums *np;
+ struct gettyflags *fp;
for (sp = gettystrs; sp->field; sp++)
if (sp->value)
- sp->defalt = sp->value;
+ sp->defalt = strdup(sp->value);
for (np = gettynums; np->field; np++)
if (np->set)
np->defalt = np->value;
}
void
-setdefaults()
+setdefaults(void)
{
- register struct gettystrs *sp;
- register struct gettynums *np;
- register struct gettyflags *fp;
+ struct gettystrs *sp;
+ struct gettynums *np;
+ struct gettyflags *fp;
for (sp = gettystrs; sp->field; sp++)
if (!sp->value)
- sp->value = sp->defalt;
+ sp->value = !sp->defalt ? sp->defalt
+ : strdup(sp->defalt);
for (np = gettynums; np->field; np++)
if (!np->set)
np->value = np->defalt;
static char *
charvars[] = {
- &tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
- &tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
- &tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
- &tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
- &tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
+ (char*)&tmode.c_cc[VERASE],
+ (char*)&tmode.c_cc[VKILL],
+ (char*)&tmode.c_cc[VINTR],
+ (char*)&tmode.c_cc[VQUIT],
+ (char*)&tmode.c_cc[VSTART],
+ (char*)&tmode.c_cc[VSTOP],
+ (char*)&tmode.c_cc[VEOF],
+ (char*)&tmode.c_cc[VEOL],
+ (char*)&tmode.c_cc[VSUSP],
+ (char*)&tmode.c_cc[VDSUSP],
+ (char*)&tmode.c_cc[VREPRINT],
+ (char*)&tmode.c_cc[VDISCARD],
+ (char*)&tmode.c_cc[VWERASE],
+ (char*)&tmode.c_cc[VLNEXT],
+ 0
};
void
-setchars()
+setchars(void)
{
- register int i;
- register char *p;
+ int i;
+ const char *p;
for (i = 0; charnames[i]; i++) {
p = *charnames[i];
}
}
+/* Macros to clear/set/test flags. */
+#define SET(t, f) (t) |= (f)
+#define CLR(t, f) (t) &= ~(f)
+#define ISSET(t, f) ((t) & (f))
+
void
-setflags(n)
- int n;
+set_flags(int n)
{
- register tcflag_t iflag, oflag, cflag, lflag;
+ tcflag_t iflag, oflag, cflag, lflag;
-#ifdef COMPAT_43
- switch (n) {
- case 0:
- if (F0set) {
- compatflags(F0);
- return;
- }
- break;
- case 1:
- if (F1set) {
- compatflags(F1);
- return;
- }
- break;
- default:
- if (F2set) {
- compatflags(F2);
- return;
- }
- break;
- }
-#endif
switch (n) {
case 0:
break;
}
-#define BIC(v,c) (v) &= ~(c)
-#define BIS(v,s) (v) |= (s)
-#define BICS(v,c,s) BIC(v,c),BIS(v,s)
-
iflag = omode.c_iflag;
oflag = omode.c_oflag;
cflag = omode.c_cflag;
lflag = omode.c_lflag;
if (NP) {
- BIC(iflag, ISTRIP|INPCK|IGNPAR);
- BICS(cflag, CSIZE|PARENB|PARODD, CS8);
- } else if (OP && !EP) {
- BIS(iflag, ISTRIP|INPCK|IGNPAR);
- BICS(cflag, CSIZE, PARENB|PARODD|CS7);
- if (AP)
- BIC(iflag, INPCK);
- } else if (EP && !OP) {
- BIS(iflag, ISTRIP|INPCK|IGNPAR);
- BICS(cflag, CSIZE|PARODD, PARENB|CS7);
- if (AP)
- BIC(iflag, INPCK);
- } else if (AP || EP && OP) {
- BICS(iflag, INPCK|IGNPAR, ISTRIP);
- BICS(cflag, CSIZE|PARODD, PARENB|CS7);
+ CLR(cflag, CSIZE|PARENB);
+ SET(cflag, CS8);
+ CLR(iflag, ISTRIP|INPCK|IGNPAR);
+ } else if (AP || EP || OP) {
+ CLR(cflag, CSIZE);
+ SET(cflag, CS7|PARENB);
+ SET(iflag, ISTRIP);
+ if (OP && !EP) {
+ SET(iflag, INPCK|IGNPAR);
+ SET(cflag, PARODD);
+ if (AP)
+ CLR(iflag, INPCK);
+ } else if (EP && !OP) {
+ SET(iflag, INPCK|IGNPAR);
+ CLR(cflag, PARODD);
+ if (AP)
+ CLR(iflag, INPCK);
+ } else if (AP || (EP && OP)) {
+ CLR(iflag, INPCK|IGNPAR);
+ CLR(cflag, PARODD);
+ }
} /* else, leave as is */
#if 0
#endif
if (HC)
- cflag |= HUPCL;
+ SET(cflag, HUPCL);
+ else
+ CLR(cflag, HUPCL);
+
+ if (MB)
+ SET(cflag, MDMBUF);
+ else
+ CLR(cflag, MDMBUF);
+
+ if (HW)
+ SET(cflag, CRTSCTS);
else
- cflag &= ~HUPCL;
+ CLR(cflag, CRTSCTS);
if (NL) {
- iflag |= ICRNL;
- oflag |= ONLCR;
+ SET(iflag, ICRNL);
+ SET(oflag, ONLCR|OPOST);
+ } else {
+ CLR(iflag, ICRNL);
+ CLR(oflag, ONLCR);
}
+ if (!HT)
+ SET(oflag, OXTABS|OPOST);
+ else
+ CLR(oflag, OXTABS);
+
#ifdef XXX_DELAY
- f |= delaybits();
+ SET(f, delaybits());
#endif
if (n == 1) { /* read mode flags */
if (RW) {
iflag = 0;
- oflag = 0;
- cflag = CREAD|CS8;
+ CLR(oflag, OPOST);
+ CLR(cflag, CSIZE|PARENB);
+ SET(cflag, CS8);
lflag = 0;
} else {
- lflag &= ~ICANON;
+ CLR(lflag, ICANON);
}
goto out;
}
- if (HT)
- oflag &= ~OXTABS;
- else
- oflag |= OXTABS;
-
if (n == 0)
goto out;
#if 0
if (CB)
- f |= CRTBS;
+ SET(f, CRTBS);
#endif
if (CE)
- lflag |= ECHOE;
+ SET(lflag, ECHOE);
+ else
+ CLR(lflag, ECHOE);
if (CK)
- lflag |= ECHOKE;
+ SET(lflag, ECHOKE);
+ else
+ CLR(lflag, ECHOKE);
if (PE)
- lflag |= ECHOPRT;
+ SET(lflag, ECHOPRT);
+ else
+ CLR(lflag, ECHOPRT);
if (EC)
- lflag |= ECHO;
+ SET(lflag, ECHO);
+ else
+ CLR(lflag, ECHO);
if (XC)
- lflag |= ECHOCTL;
+ SET(lflag, ECHOCTL);
+ else
+ CLR(lflag, ECHOCTL);
if (DX)
- lflag |= IXANY;
-
- if (MB)
- cflag |= MDMBUF;
+ SET(lflag, IXANY);
else
- cflag &= ~MDMBUF;
+ CLR(lflag, IXANY);
out:
tmode.c_iflag = iflag;
tmode.c_lflag = lflag;
}
-#ifdef COMPAT_43
-/*
- * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
- */
-void
-compatflags(flags)
-register long flags;
-{
- register tcflag_t iflag, oflag, cflag, lflag;
-
- iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
- oflag = (OPOST|ONLCR|OXTABS);
- cflag = (CREAD);
- lflag = (ICANON|ISIG|IEXTEN);
-
- if (flags & TANDEM)
- iflag |= IXOFF;
- else
- iflag &= ~IXOFF;
- if (flags & ECHO)
- lflag |= ECHO;
- else
- lflag &= ~ECHO;
- if (flags & CRMOD) {
- iflag |= ICRNL;
- oflag |= ONLCR;
- } else {
- iflag &= ~ICRNL;
- oflag &= ~ONLCR;
- }
- if (flags & XTABS)
- oflag |= OXTABS;
- else
- oflag &= ~OXTABS;
-
- if (flags & RAW) {
- iflag &= IXOFF;
- lflag &= ~(ISIG|ICANON|IEXTEN);
- } else {
- iflag |= BRKINT|IXON|IMAXBEL;
- lflag |= ISIG|IEXTEN;
- if (flags & CBREAK)
- lflag &= ~ICANON;
- else
- lflag |= ICANON;
- }
-
- switch (flags & ANYP) {
- case EVENP:
- iflag |= INPCK;
- cflag &= ~PARODD;
- break;
- case ODDP:
- iflag |= INPCK;
- cflag |= PARODD;
- break;
- default:
- iflag &= ~INPCK;
- break;
- }
-
- if (flags & (RAW|LITOUT|PASS8)) {
- cflag &= ~(CSIZE|PARENB);
- cflag |= CS8;
- if ((flags & (RAW|PASS8)) == 0)
- iflag |= ISTRIP;
- else
- iflag &= ~ISTRIP;
- if ((flags & (RAW|LITOUT)) == 0)
- oflag |= OPOST;
- else
- oflag &= ~OPOST;
- } else {
- cflag &= ~CSIZE;
- cflag |= CS7|PARENB;
- iflag |= ISTRIP;
- oflag |= OPOST;
- }
-
- if (flags & PRTERA)
- lflag |= ECHOPRT;
- else
- lflag &= ~ECHOPRT;
- if (flags & CRTERA)
- lflag |= ECHOE;
- else
- lflag &= ~ECHOE;
- if (flags & MDMBUF)
- cflag |= MDMBUF;
- else
- cflag &= ~MDMBUF;
- if (flags & NOHANG)
- cflag &= ~HUPCL;
- else
- cflag |= HUPCL;
- if (flags & CRTKIL)
- lflag |= ECHOKE;
- else
- lflag &= ~ECHOKE;
- if (flags & CTLECH)
- lflag |= ECHOCTL;
- else
- lflag &= ~ECHOCTL;
- if ((flags & DECCTQ) == 0)
- lflag |= IXANY;
- else
- lflag &= ~IXANY;
- lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
- lflag |= flags & (TOSTOP|FLUSHO|PENDIN|NOFLSH);
-
- if (flags & (RAW|LITOUT|PASS8)) {
- cflag &= ~(CSIZE|PARENB);
- cflag |= CS8;
- if ((flags & (RAW|PASS8)) == 0)
- iflag |= ISTRIP;
- else
- iflag &= ~ISTRIP;
- if ((flags & (RAW|LITOUT)) == 0)
- oflag |= OPOST;
- else
- oflag &= ~OPOST;
- } else {
- cflag &= ~CSIZE;
- cflag |= CS7|PARENB;
- iflag |= ISTRIP;
- oflag |= OPOST;
- }
-
- tmode.c_iflag = iflag;
- tmode.c_oflag = oflag;
- tmode.c_cflag = cflag;
- tmode.c_lflag = lflag;
-}
-#endif
#ifdef XXX_DELAY
struct delayval {
};
struct delayval tbdelay[] = {
- { 1, TAB1 },
- { 2, TAB2 },
+ { 1, TAB1 },
+ { 2, TAB2 },
{ 3, XTABS }, /* this is expand tabs */
- { 100, TAB1 },
- { 0, TAB2 },
+ { 100, TAB1 },
+ { 0, TAB2 },
};
int
-delaybits()
+delaybits(void)
{
- register int f;
+ int f;
f = adelay(CD, crdelay);
f |= adelay(ND, nldelay);
}
int
-adelay(ms, dp)
- register ms;
- register struct delayval *dp;
+adelay(int ms, struct delayval *dp)
{
if (ms == 0)
return (0);
}
#endif
-char editedhost[32];
+char editedhost[MAXHOSTNAMELEN];
void
-edithost(pat)
- register char *pat;
+edithost(const char *pat)
{
- register char *host = HN;
- register char *res = editedhost;
+ const char *host = HN;
+ char *res = editedhost;
if (!pat)
pat = "";
editedhost[sizeof editedhost - 1] = '\0';
}
+static struct speedtab {
+ int speed;
+ int uxname;
+} speedtab[] = {
+ { 50, B50 },
+ { 75, B75 },
+ { 110, B110 },
+ { 134, B134 },
+ { 150, B150 },
+ { 200, B200 },
+ { 300, B300 },
+ { 600, B600 },
+ { 1200, B1200 },
+ { 1800, B1800 },
+ { 2400, B2400 },
+ { 4800, B4800 },
+ { 9600, B9600 },
+ { 19200, EXTA },
+ { 19, EXTA }, /* for people who say 19.2K */
+ { 38400, EXTB },
+ { 38, EXTB },
+ { 7200, EXTB }, /* alternative */
+ { 57600, B57600 },
+ { 115200, B115200 },
+ { 230400, B230400 },
+ { 0 }
+};
+
+int
+speed(int val)
+{
+ struct speedtab *sp;
+
+ if (val <= B230400)
+ return (val);
+
+ for (sp = speedtab; sp->speed; sp++)
+ if (sp->speed == val)
+ return (sp->uxname);
+
+ return (B300); /* default in impossible cases */
+}
+
void
-makeenv(env)
- char *env[];
+makeenv(char *env[])
{
static char termbuf[128] = "TERM=";
- register char *p, *q;
- register char **ep;
+ char *p, *q;
+ char **ep;
ep = env;
if (TT && *TT) {
- strcat(termbuf, TT);
+ strlcat(termbuf, TT, sizeof(termbuf));
*ep++ = termbuf;
}
- if (p = EV) {
+ if ((p = EV)) {
q = p;
- while (q = strchr(q, ',')) {
+ while ((q = strchr(q, ','))) {
*q++ = '\0';
*ep++ = p;
p = q;
* The routine below returns the terminal type mapped from derived speed.
*/
struct portselect {
- char *ps_baud;
- char *ps_type;
+ const char *ps_baud;
+ const char *ps_type;
} portspeeds[] = {
{ "B110", "std.110" },
{ "B134", "std.134" },
{ 0 }
};
-char *
-portselector()
+const char *
+portselector(void)
{
- char c, baud[20], *type = "default";
- register struct portselect *ps;
+ char c, baud[20];
+ const char *type = "default";
+ struct portselect *ps;
int len;
alarm(5*60);
* portselector. Selection is done by looking at how the character '\r'
* is garbled at the different speeds.
*/
-#include <sys/time.h>
-
-char *
-autobaud()
+const char *
+autobaud(void)
{
int rfds;
struct timeval timeout;
- char c, *type = "9600-baud";
- int null = 0;
+ char c;
+ const char *type = "9600-baud";
- ioctl(0, TIOCFLUSH, &null);
+ (void)tcflush(0, TCIOFLUSH);
rfds = 1 << 0;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
timeout.tv_usec = 20;
(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
- ioctl(0, TIOCFLUSH, &null);
+ (void)tcflush(0, TCIOFLUSH);
switch (c & 0377) {
case 0200: /* 300-baud */
.\" SUCH DAMAGE.
.\"
.\" from: @(#)ttys.5 8.1 (Berkeley) 6/4/93
-.\" $Id: ttys.5,v 1.1 1999/05/02 04:21:29 wsanchez Exp $
-.\"
-.Dd June 4, 1993
+.\" $FreeBSD: src/libexec/getty/ttys.5,v 1.18 2005/06/14 08:40:10 ru Exp $
+.\" "
+.Dd May 27, 2005
.Dt TTYS 5
.Os
.Sh NAME
.Nd terminal initialization information
.Sh DESCRIPTION
The file
-.Nm ttys
+.Nm
contains information that is used by various routines to initialize
and control the use of terminal special files.
This information is read with the
.Xr getttyent 3
library routines.
-There is one line in the
-.Nm ttys
+There is one line in the
+.Nm
file per special device file.
Fields are separated by tabs and/or spaces.
Fields comprised of more than one word should be enclosed in double
are delimited by hash marks (``#'') and new lines.
Any unspecified fields will default to null.
.Pp
-The first field is the
+The first field is normally the
name of the terminal special file as it is found in
.Pa /dev .
+However, it can be any arbitrary string
+when the associated command is not related to a tty.
.Pp
The second field of the file is the command to execute for the line,
usually
.Xr termcap 5
data base file.
The environment variable
-.Dv TERM
+.Ev TERM
is initialized with the value by
either
.Xr getty 8
The remaining fields set flags in the
.Fa ty_status
entry (see
-.Xr getttyent 3 )
-or specify a window system process that
-.Xr init 8
+.Xr getttyent 3 ) ,
+specify a window system process that
+.Xr launchd 8
will maintain for the terminal line.
.Pp
As flag values, the strings ``on'' and ``off'' specify that
-.Xr init
+.Xr launchd 8
should (should not) execute the command given in the second field,
while ``secure'' (if ``on'' is also specified) allows users with a
uid of 0 to login on
.Pp
The string ``window='' may be followed by a quoted command
string which
-.Xr init
+.Xr launchd 8
will execute
.Em before
starting the command specified by the second field.
+.Sh FILES
+.Bl -tag -width /etc/ttys -compact
+.It Pa /etc/ttys
+.El
+.Sh NUMERIC SEQUENCES
+Numeric sequences of terminals can be represented in a more compact format.
+A matching pair of square bracket may enclose two numbers (the start and
+stop values), separated by a hyphen.
+The numbers are assumed to be decimal, unless prefixed with ``0x'', in which
+case they are interpreted as hexadecimal.
+The number of characters (not including any ``0x'') in the starting value gives
+the minimum width; sequence values are zero padded up to this width.
+Thus ``tty[00-07]'' represents the eight terminals ``tty00'' through ``tty07''.
.Sh EXAMPLES
.Bd -literal
# root login on console at 1200 baud
console "/usr/libexec/getty std.1200" vt100 on secure
# dialup at 1200 baud, no root logins
-ttyd0 "/usr/libexec/getty d1200" dialup on # 555-1234
+ttyd0 "/usr/libexec/getty d1200" dialup on # 555-1234
# Mike's terminal: hp2621
-ttyh0 "/usr/libexec/getty std.9600" hp2621-nl on # 457 Evans
+ttyh0 "/usr/libexec/getty std.9600" hp2621-nl on # 457 Evans
# John's terminal: vt100
-ttyh1 "/usr/libexec/getty std.9600" vt100 on # 459 Evans
+ttyh1 "/usr/libexec/getty std.9600" vt100 on # 459 Evans
# terminal emulate/window system
-ttyv0 "/usr/new/xterm -L :0" vs100 on window="/usr/new/Xvs100 0"
+ttyv0 "/usr/X11/bin/xterm -display :0" xterm on window="/usr/X11/bin/X :0"
+# the sequence of eight terminals tty00 through tty07
+tty[00-07] "/usr/libexec/getty std.9600" vt100 on
# Network pseudo ttys -- don't enable getty
-ttyp0 none network
-ttyp1 none network off
+ttyp0 none network
+ttyp1 none network off
+# All sixteen of a pseudo tty sequence
+ttyq[0x0-0xf] none network
.Ed
-.Sh FILES
-.Bl -tag -width /etc/ttys -compact
-.It Pa /etc/ttys
-.El
.Sh SEE ALSO
.Xr login 1 ,
.Xr getttyent 3 ,
.Xr gettytab 5 ,
.Xr termcap 5 ,
.Xr getty 8 ,
-.Xr init 8 ,
-.Xr ttyflags 8
+.Xr launchd 8
+.\" .Xr ttyflags 8
.Sh HISTORY
A
.Nm
int main(int argc, char *argv[])
{
kern_return_t ret;
- int size;
+ unsigned int size, count;
char *cpu_name, *cpu_subname;
- int i, count;
+ int i;
int mib[2];
size_t len;
uint64_t memsize;
.Tn I/O
statistics
.Sh SYNOPSIS
-.Nm
-.Op Fl CdKIoT?\&
+.Nm iostat
+.Op Fl CUdKIoT?\&
.Op Fl c Ar count
.Op Fl n Ar devs
.Op Fl w Ar wait
.Pp
The options are as follows:
.Bl -tag -width flag
+.\" ==========
+.It Fl ?\&
+Display a usage statement and exit.
+.\" ==========
+.It Fl C
+Display CPU statistics.
+This is on by default, unless
+.Fl d
+is specified.
+.\" ==========
.It Fl c
Repeat the display
.Ar count
If no
.Ar wait
interval is specified, the default is 1 second.
-.It Fl C
-Display CPU statistics.
-This is on by default, unless
-.Fl d
-is specified.
+.\" ==========
.It Fl d
Display only device statistics.
If this flag is turned on, only device statistics will be displayed, unless
.Fl C
or
+.Fl U
+or
.Fl T
-is also specfied to enable the display of CPU or TTY statistics.
+is also specfied to enable the display of CPU, load average or TTY statistics.
+.\" ==========
.It Fl I
Display total statstics for a given time period, rather than average
statistics for each second during that time period.
+.\" ==========
.It Fl K
In the blocks transferred display (-o), display block count in kilobytes rather
then the device native block size.
+.\" ==========
.It Fl n
Display up to
.Ar devs
number of devices.
-.Nm
+.Nm iostat
will display fewer devices if there aren't
.Ar devs
devices present.
+.\" ==========
.It Fl o
Display old-style
-.Nm
+.Nm iostat
device statistics.
Sectors per second, transfers per second, and miliseconds per seek are
displayed.
.Fl I
is specified, total blocks/sectors, total transfers, and
miliseconds per seek are displayed.
+.\" ==========
.It Fl T
Display TTY statistics.
This is on by default, unless
.Fl d
is specified.
+.\" ==========
+.It Fl U
+Display system load averages.
+This is on by default, unless
+.Fl d
+is specified.
+.\" ==========
.It Fl w
Pause
.Ar wait
If no repeat
.Ar count
is specified, the default is infinity.
-.It Fl ?\&
-Display a usage statement and exit.
.El
.Pp
.Nm Iostat
.It devices
Device operations.
The header of the field is the device name and unit number.
-.Nm
+.Nm iostat
will display as many devices as will fit in a standard 80 column screen, or
the maximum number of devices in the system, whichever is smaller.
If
.Fl n
is specified on the command line,
-.Nm
+.Nm iostat
will display the smaller of the
requested number of devices, and the maximum number of devices in the system.
To force
-.Nm
+.Nm iostat
to display specific drives, their names may be supplied on the command
line.
-.Nm
+.Nm iostat
will not display more devices than will fit in an 80 column screen, unless
the
.Fl n
devices to display, or the list of specified devices exceeds 80 columns.
If fewer devices are specified on the command line than will fit in an 80
column screen,
-.Nm
+.Nm iostat
will show only the specified devices.
.Pp
The standard
-.Nm
+.Nm iostat
device display shows the following statistics:
.Pp
.Bl -tag -width indent -compact
.El
.Pp
The standard
-.Nm
+.Nm iostat
device display, with the
.Fl I
flag specified, shows the following statistics:
.El
.Pp
The old-style
-.Nm
+.Nm iostat
display (using
.Fl o )
shows the following statistics:
.El
.Pp
The old-style
-.Nm
+.Nm iostat
display, with the
.Fl I
flag specified, shows the following statistics:
.Xr netstat 1 ,
.Xr nfsstat 1 ,
.Xr ps 1 ,
-.Xr pstat 8 ,
+.Xr pstat 8
.Pp
The sections starting with ``Interpreting system activity'' in
.%T "Installing and Operating 4.3BSD" .
.Sh HISTORY
This version of
-.Nm
+.Nm iostat
first appeared in
.Nm FreeBSD 3.0 .
#include <IOKit/storage/IOBlockStorageDriver.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/IOBSD.h>
-
+#include <mach/mach_host.h> /* host_statistics */
#include <err.h>
#include <signal.h>
#include <stdio.h>
static int num_devices;
static int maxshowdevs;
-static int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
+static int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Uflag = 0, Kflag = 0;
static volatile sig_atomic_t phdr_flag = 0;
+static IONotificationPortRef notifyPort;
/* local function declarations */
static void usage(void);
static void do_phdr();
static void devstats(int perf_select, long double etime, int havelast);
static void cpustats(void);
+static void loadstats(void);
static int readvar(const char *name, void *ptr, size_t len);
static int record_all_devices(void);
+static void record_drivelist(void* context, io_iterator_t drivelist);
+static void remove_drivelist(void* context, io_iterator_t drivelist);
static int record_one_device(char *name);
static int record_device(io_registry_entry_t drive);
+static int compare_drivestats(const void* pa, const void* pb);
+
static long double compute_etime(struct timeval cur_time,
struct timeval prev_time);
* This isn't mentioned in the man page, or the usage statement,
* but it is supported.
*/
- fprintf(stderr, "usage: iostat [-CdIKoT?] [-c count] [-n devs]\n"
+ fprintf(stderr, "usage: iostat [-CUdIKoT?] [-c count] [-n devs]\n"
"\t [-w wait] [drives]\n");
}
int num_devices_specified;
int havelast = 0;
+ CFRunLoopSourceRef rls;
+
maxshowdevs = 3;
- while ((c = getopt(argc, argv, "c:CdIKM:n:oTw:?")) != -1) {
+ while ((c = getopt(argc, argv, "c:CdIKM:n:oTUw:?")) != -1) {
switch(c) {
case 'c':
cflag++;
case 'T':
Tflag++;
break;
+ case 'U':
+ Uflag++;
+ break;
case 'w':
wflag++;
waittime = atoi(optarg);
*/
IOMasterPort(bootstrap_port, &masterPort);
+ notifyPort = IONotificationPortCreate(masterPort);
+ rls = IONotificationPortGetRunLoopSource(notifyPort);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+
/*
- * Make sure Tflag and/or Cflag are set if dflag == 0. If dflag is
+ * Make sure Tflag, Cflag and Uflag are set if dflag == 0. If dflag is
* greater than 0, they may be 0 or non-zero.
*/
if (dflag == 0) {
Cflag = 1;
Tflag = 1;
+ Uflag = 1;
}
/*
}
}
- if (phdr_flag) {
+ if (!--headercount || phdr_flag) {
phdr_flag = 0;
+ headercount = 20;
do_phdr();
}
- if (!--headercount) {
- do_phdr();
- headercount = 20;
- }
-
last_time = cur_time;
gettimeofday(&cur_time, NULL);
if (Cflag > 0)
cpustats();
+ if (Uflag > 0)
+ loadstats();
+
printf("\n");
fflush(stdout);
if (count >= 0 && --count <= 0)
break;
- sleep(waittime);
+ /*
+ * Instead of sleep(waittime), wait in
+ * the RunLoop for IONotifications.
+ */
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, (CFTimeInterval)waittime, 1);
+
havelast = 1;
}
if (Tflag > 0)
(void)printf(" tty");
- for (i = 0; (i < num_devices); i++){
+ for (i = 0; i < num_devices && i < maxshowdevs; i++){
if (oflag > 0)
(void)printf("%12.6s ", drivestat[i].name);
else
}
if (Cflag > 0)
- (void)printf(" cpu\n");
+ (void)printf(" cpu");
+
+ if (Uflag > 0)
+ (void)printf(" load average\n");
else
(void)printf("\n");
if (Tflag > 0)
(void)printf(" tin tout");
- for (i=0; i < num_devices; i++){
+ for (i=0; i < num_devices && i < maxshowdevs; i++){
if (oflag > 0) {
if (Iflag == 0)
(void)printf(" sps tps msps ");
(void)printf(" blk xfr msps ");
} else {
if (Iflag == 0)
- printf(" KB/t tps MB/s ");
+ printf(" KB/t tps MB/s ");
else
- printf(" KB/t xfrs MB ");
+ printf(" KB/t xfrs MB ");
}
}
if (Cflag > 0)
- (void)printf(" us sy id\n");
+ (void)printf(" us sy id");
+
+ if (Uflag > 0)
+ (void)printf(" 1m 5m 15m\n");
else
printf("\n");
}
kern_return_t status;
int i;
- for (i = 0; i < num_devices; i++) {
+ for (i = 0; i < num_devices && i < maxshowdevs; i++) {
/*
* If the drive goes away, we may not get any properties
kCFAllocatorDefault,
kNilOptions);
if (status != KERN_SUCCESS)
- err(1, "device has no properties");
+ continue;
/* get statistics from properties */
statistics = (CFDictionaryRef)CFDictionaryGetValue(properties,
ms_per_transaction);
} else {
if (Iflag == 0)
- printf(" %5.2Lf %3.0Lf %5.2Lf ",
+ printf(" %7.2Lf %3.0Lf %5.2Lf ",
kb_per_transfer,
transfers_per_second,
mb_per_second);
interval_mb = interval_bytes;
interval_mb /= 1024 * 1024;
- printf(" %5.2Lf %3.1qu %5.2Lf ",
+ printf(" %7.2Lf %3.1qu %5.2Lf ",
kb_per_transfer,
interval_transfers,
interval_mb);
/*
* Print times.
*/
- printf("%3.0f",
- rint(100. * cur.load.cpu_ticks[CPU_STATE_USER]
- / (time ? time : 1)));
- printf("%3.0f",
- rint(100. * cur.load.cpu_ticks[CPU_STATE_SYSTEM]
- / (time ? time : 1)));
- printf("%3.0f",
- rint(100. * cur.load.cpu_ticks[CPU_STATE_IDLE]
- / (time ? time : 1)));
+#define PTIME(kind) { \
+ double cpu = rint(100. * cur.load.cpu_ticks[kind] / (time ? time : 1));\
+ printf("%*.0f", (100 == cpu) ? 4 : 3, cpu); \
+}
+ PTIME(CPU_STATE_USER);
+ PTIME(CPU_STATE_SYSTEM);
+ PTIME(CPU_STATE_IDLE);
+}
+
+static void
+loadstats(void)
+{
+ double loadavg[3];
+
+ if(getloadavg(loadavg,3)!=3)
+ errx(1, "couldn't fetch load average");
+
+ printf(" %4.2f %4.2f %4.2f",loadavg[0],loadavg[1],loadavg[2]);
}
static int
record_all_devices(void)
{
io_iterator_t drivelist;
- io_registry_entry_t drive;
CFMutableDictionaryRef match;
- int error, ndrives;
kern_return_t status;
/*
*/
match = IOServiceMatching("IOMedia");
CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
- status = IOServiceGetMatchingServices(masterPort, match, &drivelist);
+
+ CFRetain(match);
+ status = IOServiceAddMatchingNotification(notifyPort, kIOFirstMatchNotification, match, &record_drivelist, NULL, &drivelist);
+
if (status != KERN_SUCCESS)
errx(1, "couldn't match whole IOMedia devices");
*
* XXX What about RAID devices?
*/
- error = 1;
- ndrives = 0;
- while ((drive = IOIteratorNext(drivelist))
- && (ndrives < maxshowdevs)) {
- if (!record_device(drive)) {
- error = 0;
- ndrives++;
+
+ record_drivelist(NULL, drivelist);
+
+
+ status = IOServiceAddMatchingNotification(notifyPort, kIOTerminatedNotification, match, &remove_drivelist, NULL, &drivelist);
+
+ if (status != KERN_SUCCESS)
+ errx(1, "couldn't match whole IOMedia device removal");
+
+ remove_drivelist(NULL, drivelist);
+
+ return(0);
+}
+
+static void record_drivelist(void* context, io_iterator_t drivelist)
+{
+ io_registry_entry_t drive;
+ while ((drive = IOIteratorNext(drivelist))) {
+ if (num_devices < MAXDRIVES) {
+ record_device(drive);
+ phdr_flag = 1;
}
IOObjectRelease(drive);
}
- IOObjectRelease(drivelist);
+ qsort(drivestat, num_devices, sizeof(struct drivestats), &compare_drivestats);
+}
+
+static void remove_drivelist(void* context, io_iterator_t drivelist)
+{
+ io_registry_entry_t drive;
+ while ((drive = IOIteratorNext(drivelist))) {
+ kern_return_t status;
+ char bsdname[MAXDRIVENAME];
+ CFDictionaryRef properties;
+ CFStringRef name;
+
+ /* get drive properties */
+ status = IORegistryEntryCreateCFProperties(drive,
+ (CFMutableDictionaryRef *)&properties,
+ kCFAllocatorDefault,
+ kNilOptions);
+ if (status != KERN_SUCCESS) continue;
- return(error);
+ /* get name from properties */
+ name = (CFStringRef)CFDictionaryGetValue(properties,
+ CFSTR(kIOBSDNameKey));
+ CFRelease(properties);
+ if (!name) continue;
+
+ if (CFStringGetCString(name, bsdname, MAXDRIVENAME, CFStringGetSystemEncoding())) {
+ int i;
+ for (i = 0; i < num_devices; ++i) {
+ if (strcmp(bsdname,drivestat[i].name) == 0) {
+ if (i < MAXDRIVES-1) {
+ memmove(&drivestat[i], &drivestat[i+1], sizeof(struct drivestats)*(MAXDRIVES-i));
+ }
+ --num_devices;
+ phdr_flag = 1;
+ qsort(drivestat, num_devices, sizeof(struct drivestats), &compare_drivestats);
+ break;
+ }
+ }
+ }
+
+ IOObjectRelease(drive);
+ }
}
/*
/*
* Get the first match (should only be one)
*/
- if ((drive = IOIteratorNext(drivelist)) == NULL)
+ if (!(drive = IOIteratorNext(drivelist)))
errx(1, "'%s' not found", name);
if (!IOObjectConformsTo(drive, "IOMedia"))
errx(1, "'%s' is not a storage device", name);
/* get name from properties */
name = (CFStringRef)CFDictionaryGetValue(properties,
CFSTR(kIOBSDNameKey));
- CFStringGetCString(name, drivestat[num_devices].name,
- MAXDRIVENAME, CFStringGetSystemEncoding());
+ if (name)
+ CFStringGetCString(name, drivestat[num_devices].name,
+ MAXDRIVENAME, CFStringGetSystemEncoding());
+ else {
+ errx(1, "device does not have a BSD name");
+ }
/* get blocksize from properties */
number = (CFNumberRef)CFDictionaryGetValue(properties,
CFSTR(kIOMediaPreferredBlockSizeKey));
- CFNumberGetValue(number, kCFNumberSInt64Type,
- &drivestat[num_devices].blocksize);
+ if (number)
+ CFNumberGetValue(number, kCFNumberSInt64Type,
+ &drivestat[num_devices].blocksize);
+ else
+ errx(1, "device does not have a preferred block size");
/* clean up, return success */
CFRelease(properties);
IOObjectRelease(parent);
return(1);
}
+
+static int
+compare_drivestats(const void* pa, const void* pb)
+{
+ struct drivestats* a = (struct drivestats*)pa;
+ struct drivestats* b = (struct drivestats*)pb;
+ return strcmp(a->name, b->name);
+}
+++ /dev/null
-#
-# 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 = kdump
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = kdump.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kdump.1\
- mkioctls syscalls.c
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/bin
-WINDOWS_INSTALLDIR = /usr/bin
-PDO_UNIX_INSTALLDIR = /usr/bin
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-HEADER_PATHS = -I../ktrace.tproj -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders
-NEXTSTEP_PB_CFLAGS = -DMACH_USER_API
-WINDOWS_PB_CFLAGS = -DMACH_USER_API
-PDO_UNIX_PB_CFLAGS = -DMACH_USER_API
-
-
-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
+++ /dev/null
-VPATH += :../ktrace.tproj
-
-ioctl.c: mkioctls
- $(SHELL) mkioctls -s /usr/include > $(SFILE_DIR)/ioctl.c
-
-install-man-page:
- install -d $(DSTROOT)/usr/share/man/man1
- install -c -m 444 kdump.1 $(DSTROOT)/usr/share/man/man1/kdump.1
+++ /dev/null
-KTRACE_CFILES = subr.c
-GENERATED_CFILES = ioctl.c
-OTHER_INITIAL_DEPENDS = $(GENERATED_CFILES)
-OTHER_OFILES = $(GENERATED_CFILES:.c=.o) $(KTRACE_CFILES:.c=.o)
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-AFTER_INSTALL += install-man-page
--include ../Makefile.include
+++ /dev/null
-{
- APPCLASS = NSApplication;
- FILESTABLE = {
- FRAMEWORKS = ();
- HEADERSEARCH = (../ktrace.tproj);
- H_FILES = ();
- M_FILES = ();
- OTHER_LIBS = ();
- OTHER_LINKED = (kdump.c);
- OTHER_SOURCES = (
- Makefile.preamble,
- Makefile,
- Makefile.postamble,
- kdump.1,
- mkioctls,
- syscalls.c
- );
- };
- LANGUAGE = English;
- LOCALIZABLE_FILES = {};
- NEXTSTEP_BUILDTOOL = make;
- NEXTSTEP_COMPILEROPTIONS = "-DMACH_USER_API";
- NEXTSTEP_INSTALLDIR = /usr/bin;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_MAINNIB = kdump;
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDTOOL = make;
- PDO_UNIX_COMPILEROPTIONS = "-DMACH_USER_API";
- PDO_UNIX_INSTALLDIR = /usr/bin;
- PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac";
- PDO_UNIX_MAINNIB = kdump;
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = kdump;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 2.8;
- WINDOWS_BUILDTOOL = make;
- WINDOWS_COMPILEROPTIONS = "-DMACH_USER_API";
- WINDOWS_INSTALLDIR = /usr/bin;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_MAINNIB = kdump;
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-.\" 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.
-.\"
-.\" @(#)kdump.1 8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/kdump/kdump.1,v 1.5.2.2 2001/08/16 13:16:51 ru Exp $
-.\"
-.Dd June 6, 1993
-.Dt KDUMP 1
-.Os
-.Sh NAME
-.Nm kdump
-.Nd display kernel trace data
-.Sh SYNOPSIS
-.Nm
-.Op Fl dnlRT
-.Op Fl f Ar file
-.Op Fl m Ar maxdata
-.Op Fl t Op cnisuw
-.Sh DESCRIPTION
-The
-.Nm
-command displays the kernel trace files produced with
-.Xr ktrace 1
-in human readable format.
-By default, the file
-.Pa ktrace.out
-in the current directory is displayed.
-.Pp
-The options are as follows:
-.Bl -tag -width Fl
-.It Fl d
-Display all numbers in decimal.
-.It Fl f Ar file
-Display the specified file instead of
-.Pa ktrace.out .
-.It Fl l
-Loop reading the trace file, once the end-of-file is reached, waiting for
-more data.
-.It Fl m Ar maxdata
-Display at most
-.Ar maxdata
-bytes when decoding
-.Tn I/O .
-.It Fl n
-Suppress ad hoc translations.
-Normally
-.Nm
-tries to decode many system calls into a more human readable format.
-For example,
-.Xr ioctl 2
-values are replaced with the macro name and
-.Va errno
-values are replaced with the
-.Xr strerror 3
-string.
-Suppressing this feature yields a more consistent output format and is
-easily amenable to further processing.
-.It Fl R
-Display relative timestamps (time since previous entry).
-.It Fl T
-Display absolute timestamps for each entry (seconds since epoch).
-.It Fl t Ar cnisuw
-See the
-.Fl t
-option of
-.Xr ktrace 1 .
-.El
-.Sh SEE ALSO
-.Xr ktrace 1
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.4 .
+++ /dev/null
-/*
- * Copyright (c) 1999, 2000-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@
- */
-/*-
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <sys/cdefs.h>
-
-#ifndef lint
-__unused static const char copyright[] =
-"@(#) Copyright (c) 1988, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-__unused static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93";
-#endif
-__unused static const char rcsid[] =
- "$FreeBSD: src/usr.bin/kdump/kdump.c,v 1.17 1999/12/29 05:05:33 peter Exp $";
-#endif /* not lint */
-
-#include <errno.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/ktrace.h>
-#include <sys/ioctl.h>
-#include <sys/ptrace.h>
-#include <err.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <vis.h>
-#include "ktrace.h"
-
-#define ERESTART -1
-#define EJUSTRETURN -2
-int timestamp, decimal, fancy = 1, tail, maxdata;
-char *tracefile = DEF_TRACEFILE;
-struct ktr_header ktr_header;
-
-#define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
-
-/* Forward declarations */
-void usage(void);
-int fread_tail(char *buf, int size, int num);
-void dumpheader(struct ktr_header *kth);
-void dumpheader(struct ktr_header *kth);
-void ktrsyscall(struct ktr_syscall *ktr);
-void ktrsysret(struct ktr_sysret *ktr);
-void ktrnamei(char *cp, int len);
-void ktrgenio(struct ktr_genio *ktr, int len);
-void ktrpsig(struct ktr_psig *psig);
-void ktrcsw(struct ktr_csw *cs);
-void ktruser(int len, unsigned char *p);
-
-int
-main(int argc, char *argv[])
-{
- int ch, ktrlen, size;
- void *m;
- int trpoints = ALL_POINTS;
-
- (void) setlocale(LC_CTYPE, "");
-
- while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1)
- switch((char)ch) {
- case 'f':
- tracefile = optarg;
- break;
- case 'd':
- decimal = 1;
- break;
- case 'l':
- tail = 1;
- break;
- case 'm':
- maxdata = atoi(optarg);
- break;
- case 'n':
- fancy = 0;
- break;
- case 'R':
- timestamp = 2; /* relative timestamp */
- break;
- case 'T':
- timestamp = 1;
- break;
- case 't':
- trpoints = getpoints(optarg);
- if (trpoints < 0)
- errx(1, "unknown trace point in %s", optarg);
- break;
- default:
- usage();
- }
-
- if (argc > optind)
- usage();
-
- m = (void *)malloc(size = 1025);
- if (m == NULL)
- errx(1, "%s", strerror(ENOMEM));
- if (!freopen(tracefile, "r", stdin))
- err(1, "%s", tracefile);
- while (fread_tail((char *)&ktr_header, sizeof(struct ktr_header), 1)) {
- if (trpoints & (1<<ktr_header.ktr_type))
- dumpheader(&ktr_header);
- if ((ktrlen = ktr_header.ktr_len) < 0)
- errx(1, "bogus length 0x%x", ktrlen);
- if (ktrlen > size) {
- m = (void *)realloc(m, ktrlen+1);
- if (m == NULL)
- errx(1, "%s", strerror(ENOMEM));
- size = ktrlen;
- }
- if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
- errx(1, "data too short");
- if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
- continue;
- switch (ktr_header.ktr_type) {
- case KTR_SYSCALL:
- ktrsyscall((struct ktr_syscall *)m);
- break;
- case KTR_SYSRET:
- ktrsysret((struct ktr_sysret *)m);
- break;
- case KTR_NAMEI:
- ktrnamei(m, ktrlen);
- break;
- case KTR_GENIO:
- ktrgenio((struct ktr_genio *)m, ktrlen);
- break;
- case KTR_PSIG:
- ktrpsig((struct ktr_psig *)m);
- break;
- case KTR_CSW:
- ktrcsw((struct ktr_csw *)m);
- break;
- case KTR_USER:
- ktruser(ktrlen, m);
- break;
- }
- if (tail)
- (void)fflush(stdout);
- }
-
- return 0;
-}
-
-int
-fread_tail(char *buf, int size, int num)
-{
- int i;
-
- while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
- (void)sleep(1);
- clearerr(stdin);
- }
- return (i);
-}
-
-void
-dumpheader(struct ktr_header *kth)
-{
- static char unknown[64];
- static struct timeval prevtime, temp;
- char *type;
-
- switch (kth->ktr_type) {
- case KTR_SYSCALL:
- type = "CALL";
- break;
- case KTR_SYSRET:
- type = "RET ";
- break;
- case KTR_NAMEI:
- type = "NAMI";
- break;
- case KTR_GENIO:
- type = "GIO ";
- break;
- case KTR_PSIG:
- type = "PSIG";
- break;
- case KTR_CSW:
- type = "CSW";
- break;
- case KTR_USER:
- type = "USER";
- break;
- default:
- (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
- type = unknown;
- }
-
- (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
- if (timestamp) {
- if (timestamp == 2) {
- temp = kth->ktr_time;
- timevalsub(&kth->ktr_time, &prevtime);
- prevtime = temp;
- }
- (void)printf("%ld.%06d ",
- kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
- }
- (void)printf("%s ", type);
-}
-
-#include <sys/syscall.h>
-#include "syscalls.c"
-int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
-
-static char *ptrace_ops[] = {
- "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
- "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
- "PT_KILL", "PT_STEP", "PT_ATTACH", "PT_DETACH",
- "PT_SIGEXC", "PT_THUPDATE", "PT_ATTACHEXC",
-};
-
-void
-ktrsyscall(struct ktr_syscall *ktr)
-{
- register_t narg = ktr->ktr_narg;
- unsigned long long *ip;
- char *ioctlname();
-
- if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
- (void)printf("[%d]", ktr->ktr_code);
- else
- (void)printf("%s", syscallnames[ktr->ktr_code]);
- ip = &ktr->ktr_args[0];
- if (narg) {
- char c = '(';
- if (fancy) {
- if (ktr->ktr_code == SYS_ioctl) {
- char *cp;
- if (decimal)
- (void)printf("(%ld", (long)*ip);
- else
- (void)printf("(%#lx", (long)*ip);
- ip++;
- narg--;
- if ((cp = ioctlname(*ip)) != NULL)
- (void)printf(",%s", cp);
- else {
- if (decimal)
- (void)printf(",%ld", (long)*ip);
- else
- (void)printf(",%#lx ", (long)*ip);
- }
- c = ',';
- ip++;
- narg--;
- } else if (ktr->ktr_code == SYS_ptrace) {
- if (*ip < sizeof(ptrace_ops) /
- sizeof(ptrace_ops[0]) && *ip >= 0)
- (void)printf("(%s", ptrace_ops[*ip]);
-#ifdef PT_FORCEQUOTA
- else if (*ip == PT_FORCEQUOTA)
- (void)printf("(%s", "PT_FORCEQUOTA");
-#endif
-#ifdef PT_DENY_ATTACH
- else if (*ip == PT_DENY_ATTACH)
- (void)printf("(%s", "PT_DENY_ATTACH");
-#endif
-#ifdef PT_FIRSTMACH
- else if (*ip == PT_FIRSTMACH)
- (void)printf("(%s", "PT_FIRSTMACH");
-#endif
- else
- (void)printf("(%ld", (long)*ip);
- c = ',';
- ip++;
- narg--;
- }
- }
- while (narg) {
- if (decimal)
- (void)printf("%c%ld", c, (long)*ip);
- else
- (void)printf("%c%#lx", c, (long)*ip);
- c = ',';
- ip++;
- narg--;
- }
- (void)putchar(')');
- }
- (void)putchar('\n');
-}
-
-void
-ktrsysret(struct ktr_sysret *ktr)
-{
- register_t ret = ktr->ktr_retval;
- int error = ktr->ktr_error;
- int code = ktr->ktr_code;
-
- if (code >= nsyscalls || code < 0)
- (void)printf("[%d] ", code);
- else
- (void)printf("%s ", syscallnames[code]);
-
- if (error == 0) {
- if (fancy) {
- (void)printf("%d", ret);
- if (ret < 0 || ret > 9)
- (void)printf("/%#lx", (long)ret);
- } else {
- if (decimal)
- (void)printf("%ld", (long)ret);
- else
- (void)printf("%#lx", (long)ret);
- }
- } else if (error == ERESTART)
- (void)printf("RESTART");
- else if (error == EJUSTRETURN)
- (void)printf("JUSTRETURN");
- else {
- (void)printf("-1 errno %d", ktr->ktr_error);
- if (fancy)
- (void)printf(" %s", strerror(ktr->ktr_error));
- }
- (void)putchar('\n');
-}
-
-void
-ktrnamei(char *cp, int len)
-{
- (void)printf("\"%.*s\"\n", len, cp);
-}
-
-void
-ktrgenio(struct ktr_genio *ktr, int len)
-{
- int datalen = len - sizeof (struct ktr_genio);
- char *dp = (char *)ktr + sizeof (struct ktr_genio);
- char *cp;
- int col = 0;
- int width;
- char visbuf[5];
- static int screenwidth = 0;
-
- if (screenwidth == 0) {
- struct winsize ws;
-
- if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
- ws.ws_col > 8)
- screenwidth = ws.ws_col;
- else
- screenwidth = 80;
- }
- printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
- ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
- datalen == 1 ? "" : "s");
- if (maxdata && datalen > maxdata)
- datalen = maxdata;
- (void)printf(" \"");
- col = 8;
- for (;datalen > 0; datalen--, dp++) {
- (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
- cp = visbuf;
- /*
- * Keep track of printables and
- * space chars (like fold(1)).
- */
- if (col == 0) {
- (void)putchar('\t');
- col = 8;
- }
- switch(*cp) {
- case '\n':
- col = 0;
- (void)putchar('\n');
- continue;
- case '\t':
- width = 8 - (col&07);
- break;
- default:
- width = strlen(cp);
- }
- if (col + width > (screenwidth-2)) {
- (void)printf("\\\n\t");
- col = 8;
- }
- col += width;
- do {
- (void)putchar(*cp++);
- } while (*cp);
- }
- if (col == 0)
- (void)printf(" ");
- (void)printf("\"\n");
-}
-
-char *signames[] = {
- "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", /* 1 - 6 */
- "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */
- "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */
- "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */
- "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", /* 25 - 30 */
- "USR2", NULL, /* 31 - 32 */
-};
-
-void
-ktrpsig(struct ktr_psig *psig)
-{
- (void)printf("SIG%s ", signames[psig->signo]);
- if (psig->action == SIG_DFL)
- (void)printf("SIG_DFL\n");
- else
- (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
- (u_long)psig->action, psig->mask, psig->code);
-}
-
-void
-ktrcsw(struct ktr_csw *cs)
-{
- (void)printf("%s %s\n", cs->out ? "stop" : "resume",
- cs->user ? "user" : "kernel");
-}
-
-void
-ktruser(int len, unsigned char *p)
-{
- (void)printf("%d ", len);
- while (len--)
- (void)printf(" %02x", *p++);
- (void)printf("\n");
-
-}
-
-void
-usage(void)
-{
- (void)fprintf(stderr,
- "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n");
- exit(1);
-}
+++ /dev/null
-set -e
-
-# $FreeBSD: src/usr.bin/kdump/mkioctls,v 1.15.2.3 2001/04/07 11:09:28 ru Exp $
-
-if [ "x$1" = "x-s" ]; then
- use_switch=1
- shift
-else
- use_switch=0
-fi
-
-if [ -z "$1" ]; then
- echo "usage: sh $0 [-s] include-dir"
- exit 1
-fi
-
-LC_ALL=C; export LC_ALL
-
-# Build a list of headers that have ioctls in them.
-# XXX should we use an ANSI cpp?
-# XXX netipx conflicts with netns (leave out netns).
-ioctl_includes=`
- cd $1
- find * -name '*.h' |
- egrep -v '^(netns)/' |
- egrep -v 'if_atm' |
- egrep -v 'disklabel' |
- egrep -v 'if_ppp' |
- egrep -v 'bpf' |
- egrep -v '^(netiso)/' |
- egrep -v '^(netccitt)/' |
- xargs egrep -l \
-'^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO[^a-z0-9_]' |
- sed -e 's/^/#include </' -e s'/$/>/'
-`
-
-echo "/* XXX obnoxious prerequisites. */"
-echo "#define COMPAT_43_TTY 1"
-echo "#include <sys/param.h>"
-echo "#include <sys/socket.h>"
-echo "#include <sys/time.h>"
-echo "#include <sys/tty.h>"
-echo "#include <net/ethernet.h>"
-echo "#include <net/if.h>"
-echo "#include <net/if_var.h>"
-echo "#include <net/route.h>"
-echo "#include <netinet/in.h>"
-echo "#include <netinet/ip_compat.h>"
-echo "#include <netinet/ip_mroute.h>"
-echo "#include <netinet6/in6_var.h>"
-echo "#include <netinet6/nd6.h>"
-echo "#include <netinet6/ip6_mroute.h>"
-echo "#include <netat/appletalk.h>"
-echo "#include <stdio.h>"
-echo ""
-echo "$ioctl_includes"
-echo ""
-
-echo "$ioctl_includes" |
- cc -no-cpp-precomp -E -I$1 -dM - |
- awk -v use_switch="$use_switch" '
-BEGIN {
- print "char *"
- print "ioctlname(register_t val)"
- print "{"
- print ""
- if (use_switch)
- print "\tswitch(val) {"
-}
-
-/^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO/ {
-
- # find where the name starts
- for (i = 1; i <= NF; i++)
- if ($i ~ /define/)
- break;
- ++i;
- #
- if ($i == "SIOCADDRT" || $i == "SIOCDELRT") {
- printf("#if 0\n");
- }
- if (use_switch)
- printf("\tcase %s:\n\t\treturn(\"%s\");\n", $i, $i);
- else
- printf("\tif (val == %s)\n\t\treturn(\"%s\");\n", $i, $i);
- if ($i == "SIOCADDRT" || $i == "SIOCDELRT") {
- printf("#endif\n");
- }
-
-}
-END {
- if (use_switch)
- print "\t}"
- print "\n\treturn(NULL);"
- print "}"
-}
-'
+++ /dev/null
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- *
- *
- * System call switch table.
- *
- * DO NOT EDIT-- this file is automatically generated.
- * created from syscalls.master
- */
-
-const char *syscallnames[] = {
- "syscall", /* 0 = syscall indirect syscall */
- "exit", /* 1 = exit */
- "fork", /* 2 = fork */
- "read", /* 3 = read */
- "write", /* 4 = write */
- "open", /* 5 = open */
- "close", /* 6 = close */
- "wait4", /* 7 = wait4 */
- "#8", /* 8 = old creat */
- "link", /* 9 = link */
- "unlink", /* 10 = unlink */
- "#11", /* 11 = old execv */
- "chdir", /* 12 = chdir */
- "fchdir", /* 13 = fchdir */
- "mknod", /* 14 = mknod */
- "chmod", /* 15 = chmod */
- "chown", /* 16 = chown */
- "obreak", /* 17 = obreak old break */
-#if COMPAT_GETFSSTAT
- "ogetfsstat", /* 18 = ogetfsstat */
-#else
- "getfsstat", /* 18 = getfsstat */
-#endif
- "#19", /* 19 = old lseek */
- "getpid", /* 20 = getpid */
- "#21", /* 21 = old mount */
- "#22", /* 22 = old umount */
- "setuid", /* 23 = setuid */
- "getuid", /* 24 = getuid */
- "geteuid", /* 25 = geteuid */
- "ptrace", /* 26 = ptrace */
- "recvmsg", /* 27 = recvmsg */
- "sendmsg", /* 28 = sendmsg */
- "recvfrom", /* 29 = recvfrom */
- "accept", /* 30 = accept */
- "getpeername", /* 31 = getpeername */
- "getsockname", /* 32 = getsockname */
- "access", /* 33 = access */
- "chflags", /* 34 = chflags */
- "fchflags", /* 35 = fchflags */
- "sync", /* 36 = sync */
- "kill", /* 37 = kill */
- "#38", /* 38 = old stat */
- "getppid", /* 39 = getppid */
- "#40", /* 40 = old lstat */
- "dup", /* 41 = dup */
- "pipe", /* 42 = pipe */
- "getegid", /* 43 = getegid */
- "profil", /* 44 = profil */
- "ktrace", /* 45 = ktrace */
- "sigaction", /* 46 = sigaction */
- "getgid", /* 47 = getgid */
- "sigprocmask", /* 48 = sigprocmask */
- "getlogin", /* 49 = getlogin */
- "setlogin", /* 50 = setlogin */
- "acct", /* 51 = acct */
- "sigpending", /* 52 = sigpending */
- "sigaltstack", /* 53 = sigaltstack */
- "ioctl", /* 54 = ioctl */
- "reboot", /* 55 = reboot */
- "revoke", /* 56 = revoke */
- "symlink", /* 57 = symlink */
- "readlink", /* 58 = readlink */
- "execve", /* 59 = execve */
- "umask", /* 60 = umask */
- "chroot", /* 61 = chroot */
- "#62", /* 62 = old fstat */
- "#63", /* 63 = used internally , reserved */
- "#64", /* 64 = old getpagesize */
- "msync", /* 65 = msync */
- "vfork", /* 66 = vfork */
- "#67", /* 67 = old vread */
- "#68", /* 68 = old vwrite */
- "sbrk", /* 69 = sbrk */
- "sstk", /* 70 = sstk */
- "#71", /* 71 = old mmap */
- "ovadvise", /* 72 = ovadvise old vadvise */
- "munmap", /* 73 = munmap */
- "mprotect", /* 74 = mprotect */
- "madvise", /* 75 = madvise */
- "#76", /* 76 = old vhangup */
- "#77", /* 77 = old vlimit */
- "mincore", /* 78 = mincore */
- "getgroups", /* 79 = getgroups */
- "setgroups", /* 80 = setgroups */
- "getpgrp", /* 81 = getpgrp */
- "setpgid", /* 82 = setpgid */
- "setitimer", /* 83 = setitimer */
- "#84", /* 84 = old wait */
- "swapon", /* 85 = swapon */
- "getitimer", /* 86 = getitimer */
- "#87", /* 87 = old gethostname */
- "#88", /* 88 = old sethostname */
- "getdtablesize", /* 89 = getdtablesize */
- "dup2", /* 90 = dup2 */
- "#91", /* 91 = old getdopt */
- "fcntl", /* 92 = fcntl */
- "select", /* 93 = select */
- "#94", /* 94 = old setdopt */
- "fsync", /* 95 = fsync */
- "setpriority", /* 96 = setpriority */
- "socket", /* 97 = socket */
- "connect", /* 98 = connect */
- "#99", /* 99 = old accept */
- "getpriority", /* 100 = getpriority */
- "#101", /* 101 = old send */
- "#102", /* 102 = old recv */
-#ifdef __ppc__
- "#103", /* 103 = old sigreturn */
-#else
- "sigreturn", /* 103 = sigreturn */
-#endif
- "bind", /* 104 = bind */
- "setsockopt", /* 105 = setsockopt */
- "listen", /* 106 = listen */
- "#107", /* 107 = old vtimes */
- "#108", /* 108 = old sigvec */
- "#109", /* 109 = old sigblock */
- "#110", /* 110 = old sigsetmask */
- "sigsuspend", /* 111 = sigsuspend */
- "#112", /* 112 = old sigstack */
- "#113", /* 113 = old recvmsg */
- "#114", /* 114 = old sendmsg */
- "#115", /* 115 = old vtrace */
-#ifdef __ppc__
- "ppc_gettimeofday", /* 116 = ppc_gettimeofday */
-#else
- "gettimeofday", /* 116 = gettimeofday */
-#endif
- "getrusage", /* 117 = getrusage */
- "getsockopt", /* 118 = getsockopt */
- "#119", /* 119 = old resuba */
- "readv", /* 120 = readv */
- "writev", /* 121 = writev */
- "settimeofday", /* 122 = settimeofday */
- "fchown", /* 123 = fchown */
- "fchmod", /* 124 = fchmod */
- "#125", /* 125 = old recvfrom */
- "#126", /* 126 = old setreuid */
- "#127", /* 127 = old setregid */
- "rename", /* 128 = rename */
- "#129", /* 129 = old truncate */
- "#130", /* 130 = old ftruncate */
- "flock", /* 131 = flock */
- "mkfifo", /* 132 = mkfifo */
- "sendto", /* 133 = sendto */
- "shutdown", /* 134 = shutdown */
- "socketpair", /* 135 = socketpair */
- "mkdir", /* 136 = mkdir */
- "rmdir", /* 137 = rmdir */
- "utimes", /* 138 = utimes */
- "futimes", /* 139 = futimes */
- "adjtime", /* 140 = adjtime */
- "#141", /* 141 = old getpeername */
- "#142", /* 142 = old gethostid */
- "#143", /* 143 = old sethostid */
- "#144", /* 144 = old getrlimit */
- "#145", /* 145 = old setrlimit */
- "#146", /* 146 = old killpg */
- "setsid", /* 147 = setsid */
- "#148", /* 148 = old setquota */
- "#149", /* 149 = old qquota */
- "#150", /* 150 = old getsockname */
- "getpgid", /* 151 = getpgid */
- "setprivexec", /* 152 = setprivexec */
- "pread", /* 153 = pread */
- "pwrite", /* 154 = pwrite */
-#if NFSSERVER
- "nfssvc", /* 155 = nfssvc */
-#else
- "#155", /* 155 = */
-#endif
- "#156", /* 156 = old getdirentries */
- "statfs", /* 157 = statfs */
- "fstatfs", /* 158 = fstatfs */
- "unmount", /* 159 = unmount */
- "#160", /* 160 = old async_daemon */
-#if NFSCLIENT
- "getfh", /* 161 = getfh */
-#else
- "#161", /* 161 = */
-#endif
- "#162", /* 162 = old getdomainname */
- "#163", /* 163 = old setdomainname */
- "#164", /* 164 = */
- "quotactl", /* 165 = quotactl */
- "#166", /* 166 = old exportfs */
- "mount", /* 167 = mount */
- "#168", /* 168 = old ustat */
- "#169", /* 169 = */
- "table", /* 170 = table old table */
- "#171", /* 171 = old wait3 */
- "#172", /* 172 = old rpause */
- "waitid", /* 173 = waitid */
- "#174", /* 174 = old getdents */
- "#175", /* 175 = old gc_control */
- "add_profil", /* 176 = add_profil */
- "#177", /* 177 = */
- "#178", /* 178 = */
- "#179", /* 179 = */
- "kdebug_trace", /* 180 = kdebug_trace */
- "setgid", /* 181 = setgid */
- "setegid", /* 182 = setegid */
- "seteuid", /* 183 = seteuid */
-#ifdef __ppc__
- "sigreturn", /* 184 = sigreturn */
-#else
- "#184", /* 184 = */
-#endif
- "#185", /* 185 = */
- "#186", /* 186 = */
- "#187", /* 187 = */
- "stat", /* 188 = stat */
- "fstat", /* 189 = fstat */
- "lstat", /* 190 = lstat */
- "pathconf", /* 191 = pathconf */
- "fpathconf", /* 192 = fpathconf */
-#if COMPAT_GETFSSTAT
- "getfsstat", /* 193 = getfsstat */
-#else
- "#193", /* 193 = */
-#endif
- "getrlimit", /* 194 = getrlimit */
- "setrlimit", /* 195 = setrlimit */
- "getdirentries", /* 196 = getdirentries */
- "mmap", /* 197 = mmap */
- "#198", /* 198 = __syscall */
- "lseek", /* 199 = lseek */
- "truncate", /* 200 = truncate */
- "ftruncate", /* 201 = ftruncate */
- "__sysctl", /* 202 = __sysctl */
- "mlock", /* 203 = mlock */
- "munlock", /* 204 = munlock */
- "undelete", /* 205 = undelete */
-#ifdef __ppc__
- "ATsocket", /* 206 = ATsocket */
- "ATgetmsg", /* 207 = ATgetmsg */
- "ATputmsg", /* 208 = ATputmsg */
- "ATPsndreq", /* 209 = ATPsndreq */
- "ATPsndrsp", /* 210 = ATPsndrsp */
- "ATPgetreq", /* 211 = ATPgetreq */
- "ATPgetrsp", /* 212 = ATPgetrsp */
- "#213", /* 213 = Reserved for AppleTalk */
-#else
- "ATsocket", /* 206 = ATsocket */
- "ATgetmsg", /* 207 = ATgetmsg */
- "ATputmsg", /* 208 = ATputmsg */
- "ATPsndreq", /* 209 = ATPsndreq */
- "ATPsndrsp", /* 210 = ATPsndrsp */
- "ATPgetreq", /* 211 = ATPgetreq */
- "ATPgetrsp", /* 212 = ATPgetrsp */
- "#213", /* 213 = Reserved for AppleTalk */
-#endif /* __ppc__ */
- "kqueue_from_portset_np", /* 214 = kqueue_from_portset_np */
- "kqueue_portset_np", /* 215 = kqueue_portset_np */
- "mkcomplex", /* 216 = mkcomplex soon to be obsolete */
- "statv", /* 217 = statv soon to be obsolete */
- "lstatv", /* 218 = lstatv soon to be obsolete */
- "fstatv", /* 219 = fstatv soon to be obsolete */
- "getattrlist", /* 220 = getattrlist */
- "setattrlist", /* 221 = setattrlist */
- "getdirentriesattr", /* 222 = getdirentriesattr */
- "exchangedata", /* 223 = exchangedata */
-#ifdef __APPLE_API_OBSOLETE
- "checkuseraccess", /* 224 = checkuseraccess */
-#else
- "#224", /* 224 = HFS checkuseraccess check access to a file */
-#endif /* __APPLE_API_OBSOLETE */
- "searchfs", /* 225 = searchfs */
- "delete", /* 226 = delete private delete ( Carbon semantics ) */
- "copyfile", /* 227 = copyfile */
- "#228", /* 228 = */
- "#229", /* 229 = */
- "poll", /* 230 = poll */
- "watchevent", /* 231 = watchevent */
- "waitevent", /* 232 = waitevent */
- "modwatch", /* 233 = modwatch */
- "getxattr", /* 234 = getxattr */
- "fgetxattr", /* 235 = fgetxattr */
- "setxattr", /* 236 = setxattr */
- "fsetxattr", /* 237 = fsetxattr */
- "removexattr", /* 238 = removexattr */
- "fremovexattr", /* 239 = fremovexattr */
- "listxattr", /* 240 = listxattr */
- "flistxattr", /* 241 = flistxattr */
- "fsctl", /* 242 = fsctl */
- "#243", /* 243 = */
- "#244", /* 244 = */
- "#245", /* 245 = */
- "#246", /* 246 = */
-#if NFSCLIENT
- "nfsclnt", /* 247 = nfsclnt */
- "fhopen", /* 248 = fhopen */
-#else
- "#247", /* 247 = */
- "#248", /* 248 = */
-#endif
- "#249", /* 249 = */
- "minherit", /* 250 = minherit */
- "semsys", /* 251 = semsys */
- "msgsys", /* 252 = msgsys */
- "shmsys", /* 253 = shmsys */
- "semctl", /* 254 = semctl */
- "semget", /* 255 = semget */
- "semop", /* 256 = semop */
- "#257", /* 257 = */
- "msgctl", /* 258 = msgctl */
- "msgget", /* 259 = msgget */
- "msgsnd", /* 260 = msgsnd */
- "msgrcv", /* 261 = msgrcv */
- "shmat", /* 262 = shmat */
- "shmctl", /* 263 = shmctl */
- "shmdt", /* 264 = shmdt */
- "shmget", /* 265 = shmget */
- "shm_open", /* 266 = shm_open */
- "shm_unlink", /* 267 = shm_unlink */
- "sem_open", /* 268 = sem_open */
- "sem_close", /* 269 = sem_close */
- "sem_unlink", /* 270 = sem_unlink */
- "sem_wait", /* 271 = sem_wait */
- "sem_trywait", /* 272 = sem_trywait */
- "sem_post", /* 273 = sem_post */
- "sem_getvalue", /* 274 = sem_getvalue */
- "sem_init", /* 275 = sem_init */
- "sem_destroy", /* 276 = sem_destroy */
- "open_extended", /* 277 = open_extended */
- "umask_extended", /* 278 = umask_extended */
- "stat_extended", /* 279 = stat_extended */
- "lstat_extended", /* 280 = lstat_extended */
- "fstat_extended", /* 281 = fstat_extended */
- "chmod_extended", /* 282 = chmod_extended */
- "fchmod_extended", /* 283 = fchmod_extended */
- "access_extended", /* 284 = access_extended */
- "settid", /* 285 = settid */
- "gettid", /* 286 = gettid */
- "setsgroups", /* 287 = setsgroups */
- "getsgroups", /* 288 = getsgroups */
- "setwgroups", /* 289 = setwgroups */
- "getwgroups", /* 290 = getwgroups */
- "mkfifo_extended", /* 291 = mkfifo_extended */
- "mkdir_extended", /* 292 = mkdir_extended */
- "identitysvc", /* 293 = identitysvc */
- "#294", /* 294 = */
- "#295", /* 295 = */
- "load_shared_file", /* 296 = load_shared_file */
- "reset_shared_file", /* 297 = reset_shared_file */
- "new_system_shared_regions", /* 298 = new_system_shared_regions */
- "shared_region_map_file_np", /* 299 = shared_region_map_file_np */
- "shared_region_make_private_np", /* 300 = shared_region_make_private_np */
- "#301", /* 301 = */
- "#302", /* 302 = */
- "#303", /* 303 = */
- "#304", /* 304 = */
- "#305", /* 305 = */
- "#306", /* 306 = */
- "#307", /* 307 = */
- "#308", /* 308 = */
- "#309", /* 309 = */
- "getsid", /* 310 = getsid */
- "#311", /* 311 = */
- "#312", /* 312 = */
- "aio_fsync", /* 313 = aio_fsync */
- "aio_return", /* 314 = aio_return */
- "aio_suspend", /* 315 = aio_suspend */
- "aio_cancel", /* 316 = aio_cancel */
- "aio_error", /* 317 = aio_error */
- "aio_read", /* 318 = aio_read */
- "aio_write", /* 319 = aio_write */
- "lio_listio", /* 320 = lio_listio */
- "#321", /* 321 = */
- "#322", /* 322 = */
- "#323", /* 323 = */
- "mlockall", /* 324 = mlockall */
- "munlockall", /* 325 = munlockall */
- "#326", /* 326 = */
- "issetugid", /* 327 = issetugid */
- "__pthread_kill", /* 328 = __pthread_kill */
- "pthread_sigmask", /* 329 = pthread_sigmask */
- "sigwait", /* 330 = sigwait */
- "__disable_threadsignal", /* 331 = __disable_threadsignal */
- "__pthread_markcancel", /* 332 = __pthread_markcancel */
- "__pthread_canceled", /* 333 = __pthread_canceled */
- "__semwait_signal", /* 334 = __semwait_signal */
- "utrace", /* 335 = utrace */
- "#336", /* 336 = */
- "#337", /* 337 = */
- "#338", /* 338 = */
- "#339", /* 339 = */
- "#340", /* 340 = */
- "#341", /* 341 = */
- "#342", /* 342 = */
- "#343", /* 343 = */
- "#344", /* 344 = */
- "#345", /* 345 = */
- "#346", /* 346 = */
- "#347", /* 347 = */
- "#348", /* 348 = */
- "#349", /* 349 = */
- "audit", /* 350 = audit */
- "auditon", /* 351 = auditon */
- "#352", /* 352 = */
- "getauid", /* 353 = getauid */
- "setauid", /* 354 = setauid */
- "getaudit", /* 355 = getaudit */
- "setaudit", /* 356 = setaudit */
- "getaudit_addr", /* 357 = getaudit_addr */
- "setaudit_addr", /* 358 = setaudit_addr */
- "auditctl", /* 359 = auditctl */
- "#360", /* 360 = */
- "#361", /* 361 = */
- "kqueue", /* 362 = kqueue */
- "kevent", /* 363 = kevent */
- "lchown", /* 364 = lchown */
- "#365", /* 365 = */
- "#366", /* 366 = */
- "#367", /* 367 = */
- "#368", /* 368 = */
- "#369", /* 369 = */
-};
+++ /dev/null
-#
-# 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
+++ /dev/null
-###############################################################################
-# NeXT Makefile.postamble Template
-# Copyright 1993, NeXT Computer, Inc.
-#
-# This Makefile is used for configuring the standard app makefiles associated
-# with ProjectBuilder.
-#
-# Use this template to set attributes for a project, sub-project, bundle, or
-# palette. Each node in the project's tree of sub-projects and bundles
-# should have it's own Makefile.preamble and Makefile.postamble. Additional
-# rules (e.g., after_install) that are defined by the developer should be
-# defined in this file.
-#
-###############################################################################
-#
-# Here are the variables exported by the common "app" makefiles that can be
-# used in any customizations you make to the template below:
-#
-# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
-# OFILE_DIR - Directory into which .o object files are generated.
-# (Note that this name is calculated based on the target
-# architectures specified in Project Builder).
-# DERIVED_SRC_DIR - Directory used for all other derived files
-# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
-#
-# NAME - name of application, bundle, subproject, palette, etc.
-# LANGUAGE - langage in which the project is written (default "English")
-# ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
-# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
-# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES - non-localized resources of project
-# PROJECTVERSION - version of ProjectBuilder that output Makefile
-# APPICON - application icon file
-# DOCICONS - dock icon files
-# ICONSECTIONS - Specifies icon sections when linking executable
-#
-# CLASSES - Class implementation files in project.
-# HFILES - Header files in project.
-# MFILES - Other Objective-C source files in project.
-# CFILES - Other C source files in project.
-# PSWFILES - .psw files in the project
-# PSWMFILES - .pswm files in the project
-# SUBPROJECTS - Subprojects of this project
-# BUNDLES - Bundle subprojects of this project
-# OTHERSRCS - Other miscellaneous sources of this project
-# OTHERLINKED - Source files not matching a standard source extention
-#
-# LIBS - Libraries to link with when making app target
-# DEBUG_LIBS - Libraries to link with when making debug target
-# PROF_LIBS - Libraries to link with when making profile target
-# OTHERLINKEDOFILES - Other relocatable files to (always) link in.
-#
-# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
-# MAKEFILEDIR - Directory in which to find $(MAKEFILE)
-# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
-# INSTALLDIR - Directory app will be installed into by 'install' target
-
-
-# Change defaults assumed by the standard app makefiles here. Edit the
-# following default values as appropriate. (Note that if no Makefile.postamble
-# exists, these values will have defaults set in common.make).
-
-# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
-# you would like changes to them to invalidate previous builds. The project
-# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
-#MAKEFILES = Makefile
-
-# Optimization flag passed to compiler:
-#OPTIMIZATION_CFLAG = -O
-
-# Flags always passed to compiler:
-#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall
-
-# Flags passed to compiler in normal 'app' compiles:
-#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
-
-# Flags passed to compiler in 'debug' compiles:
-#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
-
-# Flags passed to compiler in 'profile' compiles
-#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
-
-# Flags passed to yacc
-#YFLAGS = -d
-
-# Ownership and permissions of files installed by 'install' target
-#
-# This program may safely be run setuid-root to allow non-root
-# users to start, stop, and reset profiling buffers.
-#
-#INSTALL_AS_USER = root # User to chown app to
-#INSTALL_AS_GROUP = wheel # Group to chgrp app to
-#INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this
-
-# Options to strip for bundles, apps with bundles, and apps without bundles,
-# respectively.
-#RELOCATABLE_STRIP_OPTS = -x -u
-#DYLD_APP_STRIP_OPTS = -A -n
-#APP_STRIP_OPTS =
-#TOOL_STRIP_OPTS =
-#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols
-# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
-# developers doing their own dynamic loading should set this to
-# $(DYLD_APP_STRIP_OPTS)).
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Typical
-# user-defined rules are before_install and after_install (please don't
-# redefine things like install or app, as they are owned by the top-level
-# Makefile API), which are rules that get invoked before and after the install
-# target runs. Such rules should be specified with the '::' syntax rather than
-# a single colon.
-
-after_install:
- mkdir -p $(DSTROOT)/usr/share/man/man8
- install -c -m 444 kgmon.8 $(DSTROOT)/usr/share/man/man8
+++ /dev/null
-###############################################################################
-# NeXT Makefile.preamble Template
-# Copyright 1993, NeXT Computer, Inc.
-#
-# This Makefile is used for configuring the standard app makefiles associated
-# with ProjectBuilder.
-#
-# Use this template to set attributes for a project, sub-project, bundle, or
-# palette. Each node in the project's tree of sub-projects and bundles
-# should have it's own Makefile.preamble and Makefile.postamble.
-#
-###############################################################################
-## Configure the flags passed to $(CC) here. These flags will also be
-## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and
-## -L flags here. To change the default flags that get passed to ${CC}
-## (e.g. change -O to -O2), see Makefile.postamble.
-
-# Flags passed to compiler (in addition to -g, -O, etc)
-OTHER_CFLAGS =
-# Flags passed to ld (in addition to -ObjC, etc.)
-OTHER_LDFLAGS =
-
-BUNDLELDFLAGS = # use iff project is a bundle
-PALETTELDFLAGS = # use iff project is a palette
-
-## Specify which headers in this project should be published to the outside
-## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be
-## prepended by DSTROOT, below. Any subset of these public headers can be
-## precompiled automatically after installation, with extra user-defined flags.
-PUBLIC_HEADER_DIR =
-PUBLIC_HEADERS =
-PUBLIC_PRECOMPILED_HEADERS =
-PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
-
-## Configure what is linked in at each level here. Libraries are only used in
-## the final 'app' linking step. Final 'app' linking is only done via the
-## 'app', 'debug', and 'profile' targets when they are invoked for
-## the top-level app.
-
-# Additional relocatables to be linked in at this level
-OTHER_OFILES =
-# Additional libs to link apps against ('app' target)
-#OTHER_LIBS =
-# Additional libs to link apps against ('debug' target)
-OTHER_DEBUG_LIBS =
-# Additional libs to link apps against ('profile' target)
-OTHER_PROF_LIBS =
-
-# More 'app' libraries when $(JAPANESE) = "YES"
-OTHER_JAPANESE_LIBS =
-# More 'debug' libraries when $(JAPANESE) = "YES"
-OTHER_JAPANESE_DEBUG_LIBS =
-# More 'profile' libs when $(JAPANESE) = "YES"
-OTHER_JAPANESE_PROF_LIBS =
-
-# If this is a bundle, and you *know* the enclosing application will not
-# be linking with a library which you require in your bundle code, then
-# mention it here so that it gets linked into the bundle. Note that this
-# is wasteful but sometimes necessary.
-BUNDLE_LIBS =
-
-## Configure how things get built here. Additional dependencies, sourcefiles,
-## derived files, and build order should be specified here.
-
-# Other dependencies of this project
-OTHER_PRODUCT_DEPENDS =
-# Built *before* building subprojects/bundles
-OTHER_INITIAL_TARGETS =
-# Other source files maintained by .pre/postamble
-OTHER_SOURCEFILES =
-# Additional files to be removed by `make clean'
-OTHER_GARBAGE =
-# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
-PRECOMPS =
-
-# Targets to be built before installation
-OTHER_INSTALL_DEPENDS =
-
-# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR)
-# passed from ProjectBuilder.
-DSTROOT =
-
-# Set the following to "YES" if you want the old behavior of recursively
-# cleaning all nested subprojects during 'make clean'.
-CLEAN_ALL_SUBPROJECTS =
-
-## Add more obscure source files here to cause them to be automatically
-## processed by the appropriate tool. Note that these files should also be
-## added to "Supporting Files" in ProjectBuilder. The desired .o files that
-## result from these files should also be added to OTHER_OFILES above so they
-## will be linked in.
-
-# .msg files that should have msgwrap run on them
-MSGFILES =
-# .defs files that should have mig run on them
-DEFSFILES =
-# .mig files (no .defs files) that should have mig run on them
-MIGFILES =
-
-## Add additional Help directories here (add them to the project as "Other
-## Resources" in Project Builder) so that they will be compressed into .store
-## files and copied into the app wrapper. If the help directories themselves
-## need to also be in the app wrapper, then a cp command will need to be added
-## in an after_install target.
-OTHER_HELP_DIRS =
-
-# Don't add more rules here unless you want the first one to be the default
-# target for make! Put all your targets in Makefile.postamble.
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
+++ /dev/null
-{
- DOCICONFILES = ();
- FILESTABLE = {
- C_FILES = ();
- H_FILES = ();
- OTHER_LIBS = ();
- OTHER_LINKED = (kgmon.c);
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kgmon.8);
- PRECOMPILED_HEADERS = ();
- PROJECT_HEADERS = ();
- PUBLIC_HEADERS = ();
- SUBPROJECTS = ();
- };
- GENERATEMAIN = YES;
- LANGUAGE = English;
- LOCALIZABLE_FILES = {};
- NEXTSTEP_BUILDDIR = "";
- NEXTSTEP_BUILDTOOL = /bin/make;
- NEXTSTEP_COMPILEROPTIONS = "";
- NEXTSTEP_INSTALLDIR = /usr/sbin;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_LINKEROPTIONS = "";
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDDIR = "";
- PDO_UNIX_BUILDTOOL = /bin/make;
- PDO_UNIX_COMPILEROPTIONS = "";
- PDO_UNIX_INSTALLDIR = /usr/sbin;
- PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
- PDO_UNIX_LINKEROPTIONS = "";
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = kgmon;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 2.8;
- WINDOWS_BUILDDIR = "";
- WINDOWS_BUILDTOOL = /bin/make;
- WINDOWS_COMPILEROPTIONS = "";
- WINDOWS_INSTALLDIR = /usr/sbin;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_LINKEROPTIONS = "";
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-.\" 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 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.
-.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''.
-.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.
-They can get a
-.Pa gmon.out
-file with the warning that the data may be
-inconsistent if profiling is in progress.
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.2 .
+++ /dev/null
-/*
- * 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) 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. 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) 1983, 1992, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/sysctl.h>
-#include <sys/gmon.h>
-#include <errno.h>
-#include <kvm.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <nlist.h>
-#include <ctype.h>
-#include <paths.h>
-
-struct nlist nl[] = {
-#define N_GMONPARAM 0
- { "__gmonparam" },
-#define N_PROFHZ 1
- { "_profhz" },
- 0,
-};
-
-struct kvmvars {
- kvm_t *kd;
- struct gmonparam gpm;
-};
-
-int bflag, hflag, kflag, rflag, pflag;
-int debug = 0;
-void setprof __P((struct kvmvars *kvp, int state));
-void dumpstate __P((struct kvmvars *kvp));
-void reset __P((struct kvmvars *kvp));
-
-int
-main(int argc, char **argv)
-{
- extern char *optarg;
- extern int optind;
- int ch, mode, disp, accessmode;
- struct kvmvars kvmvars;
- char *system, *kmemf;
-
- seteuid(getuid());
- kmemf = NULL;
- system = NULL;
- while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {
- switch((char)ch) {
-
- case 'M':
- kmemf = optarg;
- kflag = 1;
- break;
-
- case 'N':
- system = optarg;
- break;
-
- case 'b':
- bflag = 1;
- break;
-
- case 'h':
- hflag = 1;
- break;
-
- case 'p':
- pflag = 1;
- break;
-
- case 'r':
- rflag = 1;
- break;
-
- default:
- (void)fprintf(stderr,
- "usage: kgmon [-bhrp] [-M core] [-N system]\n");
- exit(1);
- }
- }
- argc -= optind;
- argv += optind;
-
-#define BACKWARD_COMPATIBILITY
-#ifdef BACKWARD_COMPATIBILITY
- if (*argv) {
- system = *argv;
- if (*++argv) {
- kmemf = *argv;
- ++kflag;
- }
- }
-#endif
- if (system == NULL)
- system = _PATH_UNIX;
- accessmode = openfiles(system, kmemf, &kvmvars);
- mode = getprof(&kvmvars);
- if (hflag)
- disp = GMON_PROF_OFF;
- 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",
- disp == GMON_PROF_OFF ? "off" : "running");
- return (0);
-}
-
-/*
- * Check that profiling is enabled and open any ncessary files.
- */
-openfiles(system, kmemf, kvp)
- char *system;
- char *kmemf;
- struct kvmvars *kvp;
-{
- int mib[3], state, size, 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) {
- (void)fprintf(stderr,
- "kgmon: profiling not defined in kernel.\n");
- exit(20);
- }
- if (!(bflag || hflag || rflag ||
- (pflag && state == GMON_PROF_ON)))
- return (O_RDONLY);
- (void)seteuid(0);
- if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)
- return (O_RDWR);
- (void)seteuid(getuid());
- kern_readonly(state);
- return (O_RDONLY);
- }
- openmode = (bflag || hflag || pflag || rflag) ? 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) {
- (void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n",
- errbuf);
- exit(2);
- }
- kern_readonly(GMON_PROF_ON);
- }
- if (kvm_nlist(kvp->kd, nl) < 0) {
- (void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
- exit(3);
- }
- if (!nl[N_GMONPARAM].n_value) {
- (void)fprintf(stderr,
- "kgmon: profiling not defined in kernel.\n");
- exit(20);
- }
- return (openmode);
-}
-
-/*
- * Suppress options that require a writable kernel.
- */
-kern_readonly(mode)
- int mode;
-{
-
- (void)fprintf(stderr, "kgmon: kernel read-only: ");
- if (pflag && mode == GMON_PROF_ON)
- (void)fprintf(stderr, "data may be inconsistent\n");
- if (rflag)
- (void)fprintf(stderr, "-r supressed\n");
- if (bflag)
- (void)fprintf(stderr, "-b supressed\n");
- if (hflag)
- (void)fprintf(stderr, "-h supressed\n");
- rflag = bflag = hflag = 0;
-}
-
-/*
- * Get the state of kernel profiling.
- */
-getprof(kvp)
- struct kvmvars *kvp;
-{
- int mib[3], size;
-
- 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;
- }
- if (size != sizeof kvp->gpm) {
- (void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n",
- kflag ? kvm_geterr(kvp->kd) : strerror(errno));
- exit (4);
- }
- 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;
- int mib[3], sz, 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:
- (void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n",
- 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, addr;
- u_short *froms, *tickbuf;
- int mib[3], i;
- struct gmonhdr h;
- int fromindex, endfrom, toindex;
-
- setprof(kvp, GMON_PROF_OFF);
- fp = fopen("gmon.out", "w");
- if (fp == 0) {
- perror("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;
- h.profrate = getprofhz(kvp);
- 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) {
- fprintf(stderr, "kgmon: cannot allocate kcount space\n");
- exit (5);
- }
- 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) {
- (void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s",
- kvp->gpm.kcountsize, i,
- kflag ? kvm_geterr(kvp->kd) : strerror(errno));
- exit(6);
- }
- if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) {
- perror("kgmon: writing tocks to gmon.out");
- exit(7);
- }
- free(tickbuf);
-
- /*
- * Write out the arc info.
- */
- if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) {
- fprintf(stderr, "kgmon: cannot allocate froms space\n");
- exit (8);
- }
- 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) {
- (void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s",
- kvp->gpm.fromssize, i,
- kflag ? kvm_geterr(kvp->kd) : strerror(errno));
- exit(9);
- }
- if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) {
- fprintf(stderr, "kgmon: cannot allocate tos space\n");
- exit(10);
- }
- 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) {
- (void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s",
- kvp->gpm.tossize, i,
- kflag ? kvm_geterr(kvp->kd) : strerror(errno));
- exit(11);
- }
- if (debug)
- (void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n",
- 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)
- (void)fprintf(stderr,
- "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
- "kgmon", 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;
-{
- int mib[2], size, profrate;
- struct clockinfo clockrate;
-
- if (kflag) {
- profrate = 1;
- if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate,
- sizeof profrate) != sizeof profrate)
- (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
- 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)
- (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
- 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) {
- fprintf(stderr, "kgmon: cannot allocate zbuf space\n");
- exit(12);
- }
- bzero(zbuf, biggest);
- if (kflag) {
- if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
- kvp->gpm.kcountsize) != kvp->gpm.kcountsize) {
- (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
- kvm_geterr(kvp->kd));
- exit(13);
- }
- if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
- kvp->gpm.fromssize) != kvp->gpm.fromssize) {
- (void)fprintf(stderr, "kgmon: froms zero: %s\n",
- kvm_geterr(kvp->kd));
- exit(14);
- }
- if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
- kvp->gpm.tossize) != kvp->gpm.tossize) {
- (void)fprintf(stderr, "kgmon: tos zero: %s\n",
- kvm_geterr(kvp->kd));
- exit(15);
- }
- 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) {
- (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
- strerror(errno));
- exit(13);
- }
- mib[2] = GPROF_FROMS;
- if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) {
- (void)fprintf(stderr, "kgmon: froms zero: %s\n",
- strerror(errno));
- exit(14);
- }
- mib[2] = GPROF_TOS;
- if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) {
- (void)fprintf(stderr, "kgmon: tos zero: %s\n",
- strerror(errno));
- exit(15);
- }
- (void)seteuid(getuid());
- free(zbuf);
-}
+++ /dev/null
-#
-# 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 = ktrace
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-HFILES = ktrace.h
-
-CFILES = ktrace.c subr.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ktrace.1
-
-HEADER_PATHS = -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/bin
-WINDOWS_INSTALLDIR = /usr/bin
-PDO_UNIX_INSTALLDIR = /usr/bin
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-NEXTSTEP_PB_CFLAGS = -DMACH_USER_API
-WINDOWS_PB_CFLAGS = -DMACH_USER_API
-PDO_UNIX_PB_CFLAGS = -DMACH_USER_API
-
-
-NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
-
-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
+++ /dev/null
-install-man-page:
- install -d $(DSTROOT)/usr/share/man/man1
- install -c -m 444 ktrace.1 $(DSTROOT)/usr/share/man/man1/ktrace.1
-
+++ /dev/null
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-AFTER_INSTALL += install-man-page
-
+++ /dev/null
-{
- APPCLASS = NSApplication;
- FILESTABLE = {
- CLASSES = ();
- FRAMEWORKS = ();
- HEADERSEARCH = ();
- H_FILES = (ktrace.h);
- M_FILES = ();
- OTHER_LIBS = ();
- OTHER_LINKED = (ktrace.c, subr.c);
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ktrace.1);
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- LOCALIZABLE_FILES = {};
- NEXTSTEP_BUILDDIR = "/$(USER)/BUILD";
- NEXTSTEP_BUILDTOOL = /bin/gnumake;
- NEXTSTEP_COMPILEROPTIONS = "-DMACH_USER_API";
- NEXTSTEP_INSTALLDIR = /usr/bin;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_MAINNIB = ktrace;
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDTOOL = make;
- PDO_UNIX_COMPILEROPTIONS = "-DMACH_USER_API";
- PDO_UNIX_INSTALLDIR = /usr/bin;
- PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
- PDO_UNIX_MAINNIB = ktrace;
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = ktrace;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 2.8;
- WINDOWS_BUILDTOOL = make;
- WINDOWS_COMPILEROPTIONS = "-DMACH_USER_API";
- WINDOWS_INSTALLDIR = /usr/bin;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_MAINNIB = ktrace;
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-.\" 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.
-.\"
-.\" @(#)ktrace.1 8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/ktrace/ktrace.1,v 1.8.2.5 2001/08/16 13:16:53 ru Exp $
-.\"
-.Dd June 6, 1993
-.Dt KTRACE 1
-.Os
-.Sh NAME
-.Nm ktrace
-.Nd enable kernel process tracing
-.Sh SYNOPSIS
-.Nm
-.Op Fl aCcdi
-.Op Fl f Ar trfile
-.Op Fl g Ar pgrp | Fl p Ar pid
-.Op Fl t Ar trstr
-.Nm
-.Op Fl adi
-.Op Fl f Ar trfile
-.Op Fl t Ar trstr
-.Ar command
-.Sh DESCRIPTION
-The
-.Nm
-command enables kernel trace logging for the specified processes.
-Kernel trace data is logged to the file
-.Pa ktrace.out .
-The kernel operations that are traced include system calls, namei
-translations, signal processing, and
-.Tn I/O .
-.Pp
-Once tracing is enabled on a process, trace data will be logged until
-either the process exits or the trace point is cleared.
-A traced process can generate enormous amounts of log data quickly;
-It is strongly suggested that users memorize how to disable tracing before
-attempting to trace a process.
-The following command is sufficient to disable tracing on all user owned
-processes, and, if executed by root, all processes:
-.Pp
-.Dl \&$ ktrace -C
-.Pp
-The trace file is not human readable; use
-.Xr kdump 1
-to decode it.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl a
-Append to the trace file instead of recreating it.
-.It Fl C
-Disable tracing on all user owned processes, and, if executed by root, all
-processes in the system.
-.It Fl c
-Clear the trace points associated with the specified file or processes.
-.It Fl d
-Descendants; perform the operation for all current children of the
-designated processes.
-.It Fl f Ar file
-Log trace records to
-.Ar file
-instead of
-.Pa ktrace.out .
-.It Fl g Ar pgid
-Enable (disable) tracing on all processes in the process group (only one
-.Fl g
-flag is permitted).
-.It Fl i
-Inherit; pass the trace flags to all future children of the designated
-processes.
-.It Fl p Ar pid
-Enable (disable) tracing on the indicated process id (only one
-.Fl p
-flag is permitted).
-.It Fl t Ar trstr
-The string argument represents the kernel trace points, one per letter.
-The following table equates the letters with the tracepoints:
-.Pp
-.Bl -tag -width flag -compact
-.It Cm c
-trace system calls
-.It Cm n
-trace namei translations
-.It Cm i
-trace
-.Tn I/O
-.It Cm s
-trace signal processing
-.It Cm u
-userland traces
-.It Cm w
-context switches
-.El
-.It Ar command
-Execute
-.Ar command
-with the specified trace flags.
-.El
-.Pp
-The
-.Fl p ,
-.Fl g ,
-and
-.Ar command
-options are mutually exclusive.
-.Sh EXAMPLES
-# trace all kernel operations of process id 34
-.Dl $ ktrace -p 34
-.Pp
-# trace all kernel operations of processes in process group 15 and
-# pass the trace flags to all current and future children
-.Dl $ ktrace -idg 15
-.Pp
-# disable all tracing of process 65
-.Dl $ ktrace -cp 65
-.Pp
-# disable tracing signals on process 70 and all current children
-.Dl $ ktrace -t s -cdp 70
-.Pp
-# enable tracing of
-.Tn I/O
-on process 67
-.Dl $ ktrace -ti -p 67
-.Pp
-# run the command "w", tracing only system calls
-.Dl $ ktrace -tc w
-.Pp
-# disable all tracing to the file "tracedata"
-.Dl $ ktrace -c -f tracedata
-.Pp
-# disable tracing of all processes owned by the user
-.Dl $ ktrace -C
-.Sh SEE ALSO
-.Xr kdump 1
-.Sh BUGS
-Only works if
-.Ar file
-is a regular file.
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.4 .
+++ /dev/null
-/*
- * Copyright (c) 1999, 2000-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@
- */
-/*-
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-
-#ifndef lint
-__unused static char copyright[] =
-"@(#) Copyright (c) 1988, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-__unused static char sccsid[] = "@(#)ktrace.c 8.1 (Berkeley) 6/6/93";
-#endif
-__unused static const char rcsid[] =
- "$FreeBSD: src/usr.bin/ktrace/ktrace.c,v 1.12.2.3 2001/07/11 00:29:27 mikeh Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#include <sys/errno.h>
-#include <sys/uio.h>
-#include <sys/ktrace.h>
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "ktrace.h"
-
-void no_ktrace __P((int));
-void usage __P((void));
-int rpid(char *p);
-
-int
-main(int argc, char *argv[])
-{
- enum { NOTSET, CLEAR, CLEARALL } clear;
- int append;
- int ch;
- int fd;
- int inherit;
- int ops;
- int pid = 1; /* protected by pidset */
- int pidset;
- int trpoints;
- char *tracefile;
- mode_t omask;
- struct stat sb;
-
- clear = NOTSET;
- append = ops = pidset = inherit = 0;
- trpoints = DEF_POINTS;
- tracefile = DEF_TRACEFILE;
- while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != -1)
- switch((char)ch) {
- case 'a':
- append = 1;
- break;
- case 'C':
- clear = CLEARALL;
- pidset = 1;
- break;
- case 'c':
- clear = CLEAR;
- break;
- case 'd':
- ops |= KTRFLAG_DESCEND;
- break;
- case 'f':
- tracefile = optarg;
- break;
- case 'g':
- pid = -rpid(optarg);
- pidset = 1;
- break;
- case 'i':
- inherit = 1;
- break;
- case 'p':
- pid = rpid(optarg);
- pidset = 1;
- break;
- case 't':
- trpoints = getpoints(optarg);
- if (trpoints < 0) {
- warnx("unknown facility in %s", optarg);
- usage();
- }
- break;
- default:
- usage();
- }
- argv += optind;
- argc -= optind;
-
- if (pidset && *argv || !pidset && !*argv)
- usage();
-
- if (inherit)
- trpoints |= KTRFAC_INHERIT;
-
- (void)signal(SIGSYS, no_ktrace);
- if (clear != NOTSET) {
- if (clear == CLEARALL) {
- ops = KTROP_CLEAR | KTRFLAG_DESCEND;
- trpoints = ALL_POINTS;
- pid = 1;
- } else
- ops |= pidset ? KTROP_CLEAR : KTROP_CLEARFILE;
-
- if (ktrace(tracefile, ops, trpoints, pid) < 0)
- err(1, "%s", tracefile);
- exit(0);
- }
-
- omask = umask(S_IRWXG|S_IRWXO);
- if (append) {
- if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) < 0)
- err(1, "%s", tracefile);
- if (fstat(fd, &sb) != 0 || sb.st_uid != getuid())
- errx(1, "Refuse to append to %s not owned by you.",
- tracefile);
- } else {
- if (unlink(tracefile) == -1 && errno != ENOENT)
- err(1, "unlink %s", tracefile);
- if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY,
- DEFFILEMODE)) < 0)
- err(1, "%s", tracefile);
- }
- (void)umask(omask);
- (void)close(fd);
-
- if (*argv) {
- if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
- err(1, "%s", tracefile);
- execvp(argv[0], &argv[0]);
- err(1, "exec of '%s' failed", argv[0]);
- }
- else if (ktrace(tracefile, ops, trpoints, pid) < 0)
- err(1, "%s", tracefile);
- exit(0);
-}
-
-int
-rpid(char *p)
-{
- static int first;
-
- if (first++) {
- warnx("only one -g or -p flag is permitted.");
- usage();
- }
- if (!*p) {
- warnx("illegal process id.");
- usage();
- }
- return(atoi(p));
-}
-
-void
-usage(void)
-{
- (void)fprintf(stderr, "%s\n%s\n",
-"usage: ktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t cnisuw]",
-" ktrace [-adi] [-f trfile] [-t cnisuw] command");
- exit(1);
-}
-
-void
-no_ktrace(int sig)
-{
- (void)fprintf(stderr,
-"error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'options KTRACE'\n");
- exit(1);
-}
+++ /dev/null
-/*-
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ktrace.h 8.1 (Berkeley) 6/6/93
- */
-
-#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
- KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER)
-
-#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
-
-#define DEF_TRACEFILE "ktrace.out"
-
-/*
- * External function declarations
- */
-/* subr.c */
-int getpoints(char *s);
-void timevaladd(struct timeval *t1, struct timeval *t2);
-void timevalsub(struct timeval *t1, struct timeval *t2);
-void timevalfix(struct timeval *t1);
+++ /dev/null
-/*
- * Copyright (c) 1999, 2000-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@
- */
-/*-
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD: src/usr.bin/ktrace/subr.c,v 1.6 1999/08/28 01:02:34 peter Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/user.h>
-#include <sys/proc.h>
-#include <sys/time.h>
-#include <sys/ktrace.h>
-
-#include <stdio.h>
-
-#include "ktrace.h"
-
-int
-getpoints(char *s)
-{
- int facs = 0;
-
- while (*s) {
- switch(*s) {
- case 'c':
- facs |= KTRFAC_SYSCALL | KTRFAC_SYSRET;
- break;
- case 'n':
- facs |= KTRFAC_NAMEI;
- break;
- case 'i':
- facs |= KTRFAC_GENIO;
- break;
- case 's':
- facs |= KTRFAC_PSIG;
- break;
- case 'u':
- facs |= KTRFAC_USER;
- break;
- case 'w':
- facs |= KTRFAC_CSW;
- break;
- case '+':
- facs |= DEF_POINTS;
- break;
- default:
- return (-1);
- }
- s++;
- }
- return (facs);
-}
-
-void
-timevaladd(struct timeval *t1, struct timeval *t2)
-{
- t1->tv_sec += t2->tv_sec;
- t1->tv_usec += t2->tv_usec;
- timevalfix(t1);
-}
-
-void
-timevalsub(struct timeval *t1, struct timeval *t2)
-{
- t1->tv_sec -= t2->tv_sec;
- t1->tv_usec -= t2->tv_usec;
- timevalfix(t1);
-}
-
-void
-timevalfix(struct timeval *t1)
-{
- if (t1->tv_usec < 0) {
- t1->tv_sec--;
- t1->tv_usec += 1000000;
- }
- if (t1->tv_usec >= 1000000) {
- t1->tv_sec++;
- t1->tv_usec -= 1000000;
- }
-}
.Sh SYNOPSIS
.Nm latency
.Op Fl rt
-.Op Fl c Ar codefile
-.Op Fl l Ar logfile
+.Op Fl c Ar code_file
+.Op Fl l Ar log_file
.Op Fl st Ar threshold
.Op Fl it Ar threshold
.Op Fl s Ar sleep_in_usecs
.Sh DESCRIPTION
The
.Nm latency
-utility provides scheduling and interrupt latency statistics.
-It requires root privileges due to the kernel tracing facility it uses to
-operate.
+utility provides scheduling and interrupt-latency statistics.
+Due to the kernel tracing facility it uses to operate,
+the command requires root privileges.
.Pp
The arguments are as follows:
.Bl -tag -width Ds
-.It Fl rt
-Set real time scheduling policy.
-Default policy is timeshare.
-.It Fl c
+.\" ==========
+.It Fl c Ar code_file
When the
.Fl c
-option is specified, it takes a path to a
-.Ar codefile
+option is specified, it takes a path to a code file
that contains the mappings for the system calls.
-This option overrides the default location of the system call codefile which is
-found in /usr/share/misc/trace.codes.
-.It Fl l
-Specifies a
-.Ar logfile
-that is written to when either the interrupt or scheduling latency is exceeded.
-.It Fl st
-Set the scheduler latency threshold in microseconds.
-If latency exceeds this, and a logfile has been specified, a record of what
-occurred during this time is recorded.
-.It Fl it
-Set the interrupt latency threshold in microseconds.
-If latency exceeds this, and a logfile has been specified, a record of what
-occurred during this time is recorded.
-.It Fl s
-The
-.Fl s
-option sets the timer.
-It takes microseconds as an argument, the default timer is set to 1000
-microseconds.
-.It Fl d
-The
-.Fl d
-option sets the decrementer.
-It takes microseconds as an argument.
-The decrementer is set back to the system default on exit.
-.It Fl n
+This option overrides the default location of the system call code file,
+which is found in /usr/share/misc/trace.codes.
+.\" ==========
+.It Fl d Ar decrementer_in_usecs
+Sets the decrementer, using a value expressed in microseconds.
+On exit, the decrementer is set back to the system default value.
+.\" ==========
+.It Fl it Ar threshold
+Set the interrupt latency threshold,
+expressed in microseconds.
+If the latency exceeds this value,
+and a log file has been specified,
+a record of what occurred during this time is recorded.
+.\" ==========
+.It Fl l Ar log_file
+Specifies a log file that is written to when
+either the interrupt or scheduling latency is exceeded.
+.\" ==========
+.It Fl n Ar kernel
By default,
.Nm latency
acts on the default /mach_kernel.
This option allows you to specify an alternate booted kernel.
+.\" ==========
+.It Fl rt
+Sets the real-time scheduling policy.
+Default policy is timeshare.
+.\" ==========
+.It Fl s Ar sleep_in_usecs
+Sets the timer, taking an argument expressed in microseconds.
+The default timer is set to 1000 microseconds.
+.\" ==========
+.It Fl st Ar threshold
+Set the scheduler latency threshold in microseconds.
+If latency exceeds this, and a log file has been specified,
+a record of what occurred during this time is recorded.
.El
.Pp
The data columns displayed are as follows:
-.Bl -tag -width LAST_PATHNAME_WAITED_FOR -compact
-.Pp
+.Bl -tag -width LAST_PATHNAME_WAITED_FOR
.It SCHEDULER
The number of context switches that fall within the described delay.
.It INTERRUPTS
The threshold for interrupts is set to 1000 microseconds.
Latencies that exceed these thresholds will be logged in /var/tmp/latency.log.
.Sh SEE ALSO
-.Xr top 1 ,
.Xr fs_usage 1 ,
-.Xr sc_usage 1
+.Xr sc_usage 1 ,
+.Xr top 1
#include <mach/mach.h>
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
#include <signal.h>
#include <strings.h>
#include <nlist.h>
int total_threads = 0;
kd_threadmap *mapptr = 0;
-#define MAX_ENTRIES 1024
+#define MAX_ENTRIES 4096
struct ct {
int type;
char name[32];
#define INTERRUPT 0x01050000
#define DECR_TRAP 0x01090000
#define DECR_SET 0x01090004
-#define MACH_vmfault 0x01300000
+#define MACH_vmfault 0x01300008
#define MACH_sched 0x01400000
#define MACH_stkhandoff 0x01400008
#define VFS_LOOKUP 0x03010090
struct th_info *ti;
int cpunum;
char *p;
+ uint64_t user_addr;
cpunum = CPU_NUMBER(kd->timestamp);
if ((p = find_code(type))) {
if (type == INTERRUPT) {
fprintf(fp, "INTERRUPT %-8x %d %s\n", thread, cpunum, command);
- } else if (type == MACH_vmfault && kd->arg2 <= DBG_CACHE_HIT_FAULT) {
- fprintf(fp, "%-28.28s %-8.8s %-8x %-8x %d %s\n",
- p, fault_name[kd->arg2], kd->arg1,
+ } else if (type == MACH_vmfault && kd->arg4 <= DBG_CACHE_HIT_FAULT) {
+ user_addr = ((uint64_t)kd->arg1 << 32) | (uint32_t)kd->arg2;
+
+ fprintf(fp, "%-28.28s %-8.8s %-16qx %-8x %d %s\n",
+ p, fault_name[kd->arg4], user_addr,
thread, cpunum, command);
} else {
fprintf(fp, "%-28.28s %-8x %-8x %-8x %d %s\n",
return;
}
for (i = 0; i < MAX_ENTRIES; i++) {
- n = fscanf(fp, "%x%s\n", &code, name);
+ n = fscanf(fp, "%x%127s\n", &code, name);
if (n != 2)
break;
bzero(tmpstr, 1024);
/* Build the temporary nm file path */
- sprintf(tmp_nm_file, "/tmp/knm.out.%d", getpid());
+ strcpy(tmp_nm_file,"/tmp/knm.out.XXXXXX");
+ if (!mktemp(tmp_nm_file)) {
+ fprintf(stderr, "Error in mktemp call\n");
+ return;
+ }
/* Build the nm command and create a tmp file with the output*/
sprintf (tmpstr, "/usr/bin/nm -f -n -s __TEXT __text %s > %s",
PROJECTVERSION = 2.8
PROJECT_TYPE = Tool
+Embedded=$(shell tconf --test TARGET_OS_EMBEDDED)
+
HFILES = pathnames.h
CFILES = klogin.c login.c
NEXTSTEP_INSTALLDIR = /usr/bin
WINDOWS_INSTALLDIR = /usr/bin
PDO_UNIX_INSTALLDIR = /usr/bin
+ifeq "$(Embedded)" "NO"
LIBS = -lbsm -lpam -lpam_misc
+endif
DEBUG_LIBS = $(LIBS)
PROF_LIBS = $(LIBS)
CLEAN_ALL_SUBPROJECTS = YES
OTHER_GENERATED_OFILES = $(VERS_OFILE)
-OTHER_CFLAGS = -DUSE_PAM -no-cpp-precomp
+ifeq "$(shell tconf --test TARGET_OS_EMBEDDED)" "NO"
+OTHER_CFLAGS = -DUSE_PAM -DUSE_BSM -no-cpp-precomp
+endif
AFTER_INSTALL = after_install
.Nd log into the computer
.Sh SYNOPSIS
.Nm login
-.Op Fl fp
+.Op Fl pq
.Op Fl h Ar hostname
.Op Ar user
+.Nm login
+.Fl f
+.Op Fl lpq
+.Op Fl h Ar hostname
+.Op Ar user Op Ar prog Op Ar args...
.Sh DESCRIPTION
The
.Nm login
.Pp
The options are as follows:
.Bl -tag -width Ds
+.\" ==========
.It Fl f
The
.Fl f
requested.
This option may only be used by the super-user or when an already
logged in user is logging in as themselves.
+.Pp
+With the
+.Fl f
+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
It is used by various daemons such as
.Xr telnetd 8 .
This option may only be used by the super-user.
+.\" ==========
+.It Fl l
+Tells the program executed by
+.Nm login
+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
The
.Fl p
option disables this behavior.
+.\" ==========
+.It Fl q
+This forces quiet logins, as if a
+.Pa .hushlogin
+is present.
.El
.Pp
If the file
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, all of these messages are suppressed.
+exists in the user's home directory or
+.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
-then records an entry in the
-.Xr wtmp 5
-and
-.Xr utmp 5
-files and executes the user's command interpreter.
+then records an entry in
+.Xr utmpx 5
+and the like, and executes the user's command interpreter (or the program
+specified on the command line if
+.Fl f
+is specified).
.Pp
Login enters information into the environment (see
.Xr environ 7 )
message-of-the-day
.It Pa /etc/nologin
disallows logins
-.It Pa /var/run/utmp
+.It Pa /var/run/utmpx
current logins
-.It Pa /var/log/lastlog
-last login account records
-.It Pa /var/log/wtmp
-login account records
.It Pa /var/mail/user
system mailboxes
.It Pa \&.hushlogin
.Xr passwd 1 ,
.Xr rlogin 1 ,
.Xr getpass 3 ,
-.Xr utmp 5 ,
-.Xr environ 7 ,
+.Xr utmpx 5 ,
+.Xr environ 7
.Sh HISTORY
A
.Nm login
/*
- * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2004, 2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 <ttyent.h>
#include <tzfile.h>
#include <unistd.h>
+#ifdef USE_PAM
+#include <utmpx.h>
+#else /* !USE_PAM */
#include <utmp.h>
+#endif /* USE_PAM */
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <TargetConditionals.h>
+
+#ifdef USE_BSM
#include <bsm/libbsm.h>
#include <bsm/audit_uevents.h>
+#endif
#ifdef USE_PAM
#include <pam/pam_appl.h>
#include <pam/pam_misc.h>
#endif
+#include <mach/mach_types.h>
+
+#include <servers/bootstrap.h>
+
#include "pathnames.h"
void badlogin __P((char *));
void au_fail(char *, int);
+#ifndef USE_PAM
extern void login __P((struct utmp *));
+#endif /* !USE_PAM */
static void bail(int, int);
static void refused(const char *, const char *, int);
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
au_tid_t tid;
+#endif
int
main(argc, argv)
extern char **environ;
struct group *gr;
struct stat st;
+#ifndef USE_PAM
struct utmp utmp;
- int ask, ch, cnt, oflag = 0, fflag, pflag, quietlog, rootlogin = 0;
+#endif /* USE_PAM */
+ int ask, ch, cnt, oflag = 0, fflag, lflag, pflag;
+ int quietlog = 0, rootlogin = 0;
uid_t uid;
uid_t euid;
gid_t egid;
/*
* -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)
euid = geteuid();
egid = getegid();
- fflag = hflag = pflag = 0;
+ fflag = hflag = lflag = pflag = 0;
uid = getuid();
- while ((ch = getopt(argc, argv, "1fh:p")) != EOF)
+ while ((ch = getopt(argc, argv, "1fh:lpq")) != EOF)
switch (ch) {
case '1':
oflag = 1;
*p = 0;
hostname = optarg;
break;
+ case 'l':
+ lflag = 1;
+ break;
case 'p':
pflag = 1;
break;
+ case 'q':
+ quietlog = 1;
+ break;
case '?':
default:
if (!uid)
syslog(LOG_ERR, "invalid flag %c", ch);
(void)fprintf(stderr,
- "usage: login [-fp] [-h hostname] [username]\n");
+ "usage: login [-pq] [-h hostname] [username]\n");
+ (void)fprintf(stderr,
+ " login -f [-lpq] [-h hostname] [username [prog [arg ...]]]\n");
exit(1);
}
argc -= optind;
argv += optind;
if (*argv) {
- username = *argv;
+ username = *argv++;
ask = 0;
} else
ask = 1;
else
tty = ttyn;
+#ifdef USE_BSM
/* Set the terminal id */
audit_set_terminal_id(&tid);
if (fstat(STDIN_FILENO, &st) < 0) {
} 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: %s\n", pam_strerror(pamh, pam_err));
+ 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: %s\n", pam_strerror(pamh, pam_err));
+ 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: %s\n", pam_strerror(pamh, pam_err));
+ 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: %s\n", pam_strerror(pamh, pam_err));
+ 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_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
}
if( pam_err != PAM_SUCCESS ) {
- fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, pam_err));
+ fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err));
au_fail("PAM error", 1);
exit(1);
}
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: %s\n", pam_strerror(pamh, pam_err));
+ 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: %s\n", pam_strerror(pamh, pam_err));
+ fprintf(stderr, "login: PAM Error (line %d): %s\n", __LINE__, pam_strerror(pamh, pam_err));
au_fail("PAM error", 1);
exit(1);
}
endpwent();
+ if (!pwd) {
+ fprintf(stderr, "login: Unable to find user: %s\n", username);
+ exit(1);
+ }
+
/* if user not super-user, check for disabled logins */
if (!rootlogin)
checknologin();
setegid(pwd->pw_gid);
seteuid(rootlogin ? 0 : pwd->pw_uid);
- /* 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("/")) {
- 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);
+ 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("/"))
+ 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");
}
- printf("Logging in with home = \"/\".\n");
}
seteuid(euid);
setegid(egid);
- quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
+ if (!quietlog)
+ quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
/* 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)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
login(&utmp);
+#endif /* USE_PAM */
dolastlog(quietlog);
bail(SLEEP_EXIT, 1);
}
+#if 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) {
+ if (stat(_PATH_DEBUGSHELL, &st) == 0) {
+ pwd->pw_shell = strdup(_PATH_DEBUGSHELL);
+ }
+ }
+#endif
+
/* Destroy environment unless user has requested its preservation. */
if (!pflag) {
environ = malloc(sizeof(char *));
for( cnt = 0; pmenv && pmenv[cnt]; cnt++ )
putenv(pmenv[cnt]);
+ /* Ignore SIGHUP so that the parent's call to waitpid will
+ succeed and the tty ownership can be reset. */
+ (void)signal(SIGHUP, SIG_IGN);
+
pid = fork();
if ( pid < 0 ) {
err(1, "fork");
exit(0);
}
+ /* Restore the default SIGHUP handler for the child. */
+ (void)signal(SIGHUP, SIG_DFL);
+
#endif
if (tty[sizeof("tty")-1] == 'd')
(void)signal(SIGINT, SIG_DFL);
(void)signal(SIGTSTP, SIG_IGN);
- tbuf[0] = '-';
- (void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
- p + 1 : pwd->pw_shell);
-
if (setlogin(pwd->pw_name) < 0)
syslog(LOG_ERR, "setlogin() failure: %m");
else
(void) setuid(pwd->pw_uid);
- execlp(pwd->pw_shell, tbuf, 0);
- err(1, "%s", pwd->pw_shell);
+ /* Re-enable crash reporter */
+ do {
+ kern_return_t kr;
+ mach_port_t bp, ep, mts;
+ thread_state_flavor_t flavor = 0;
+
+#if defined(__ppc__)
+ flavor = PPC_THREAD_STATE64;
+#elif defined(__i386__)
+ flavor = x86_THREAD_STATE;
+#endif
+
+ mts = mach_task_self();
+
+ kr = task_get_bootstrap_port(mts, &bp);
+ if (kr != KERN_SUCCESS) {
+ syslog(LOG_ERR, "task_get_bootstrap_port() failure: %s (%d)",
+ bootstrap_strerror(kr), kr);
+ break;
+ }
+
+ const char* bs = "com.apple.ReportCrash";
+ kr = bootstrap_look_up(bp, (char*)bs, &ep);
+ if (kr != KERN_SUCCESS) {
+ syslog(LOG_ERR, "bootstrap_look_up(%s) failure: %s (%d)",
+ bs, bootstrap_strerror(kr), kr);
+ break;
+ }
+
+ kr = task_set_exception_ports(mts, EXC_MASK_CRASH, ep, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, flavor);
+ if (kr != KERN_SUCCESS) {
+ syslog(LOG_ERR, "task_set_exception_ports() failure: %d", kr);
+ break;
+ }
+ } while (0);
+
+ 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);
+ }
}
#ifdef KERBEROS
*/
void au_success()
{
+#ifdef USE_BSM
token_t *tok;
int aufd;
au_mask_t aumask;
fprintf(stderr, "login: Audit Record was not committed.\n");
exit(1);
}
+#endif
}
/*
*/
void au_fail(char *errmsg, int na)
{
+#ifdef USE_BSM
token_t *tok;
int aufd;
long au_cond;
fprintf(stderr, "login: Audit Error: au_close() was not committed\n");
exit(1);
}
+#endif
}
void
dolastlog(quiet)
int quiet;
{
+#ifdef USE_PAM
+ if (quiet)
+ return;
+ if (*lastlog.ll_line) {
+ (void)printf("Last login: %.*s ",
+ 24-5, (char *)ctime(&lastlog.ll_tv.tv_sec));
+ if (*lastlog.ll_host != '\0')
+ (void)printf("from %.*s\n",
+ (int)sizeof(lastlog.ll_host),
+ lastlog.ll_host);
+ else
+ (void)printf("on %.*s\n",
+ (int)sizeof(lastlog.ll_line),
+ lastlog.ll_line);
+ }
+#else /* !USE_PAM */
struct lastlog ll;
int fd;
(void)write(fd, (char *)&ll, sizeof(ll));
(void)close(fd);
}
+#endif /* USE_PAM */
}
void
void
bail(int sec, int eval)
{
-
+#ifdef USE_PAM
pam_cleanup();
+#endif
(void)sleep(sec);
exit(eval);
}
.Nm makekey
.Sh DESCRIPTION
.Nm Makekey
-encrypts a key and salt which it reads from the standard input
-and writes the result to the standard output.
-The key is expected to be
-ten bytes; the salt is expected to be two bytes.
+encrypts a key and salt which it reads from the standard input,
+writing the result to the standard output.
+The key and salt values are expected to be ten and two bytes,
+respectively, in length.
See
.Xr crypt 3
for more information on what characters the key and salt can contain
and how the encrypted value is calculated.
.Sh SEE ALSO
-.Xr login 1 ,
.Xr crypt 1 ,
+.Xr login 1 ,
.Xr crypt 3
.Sh HISTORY
A
-.Nm
+.Nm makekey
command appeared in Version 7 AT&T UNIX.
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
+__unused 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[] = "@(#)makekey.c 8.1 (Berkeley) 6/4/93";
+__unused static char sccsid[] = "@(#)makekey.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
#include <sys/types.h>
This action may only be done when the client is not running.
.SH "SEE ALSO"
.TP
-chmod(2), stat(2), exportfs(8), sticky(8)
+chmod(2), stat(2), sticky(8)
#include <string.h>
#include <unistd.h>
#include <ctype.h>
+#include <err.h>
#define BF_SZ 512 /* Size of write chunks */
char buff[BF_SZ];
int fd, bytes_written = BF_SZ;
quad_t i;
- mode_t mode;
+ mode_t mode = S_IRUSR | S_IWUSR;
- if ((fd = open(file_name, O_RDWR | O_CREAT | O_TRUNC )) == -1)
+ /* If superuser, then set sticky bit */
+ if (!geteuid()) mode |= S_ISVTX;
+
+ if ((fd = open(file_name, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1)
err(1, NULL);
}
}
+ if (fchmod(fd, mode)) /* Change permissions */
+ err_rm(file_name, NULL);
- mode = S_IRUSR | S_IWUSR;
- /* If superuser, then set sticky bit */
- if (! geteuid())
- mode |= S_ISVTX;
-
- if (fchmod(fd, mode)) /* Change permissions */
- err_rm(file_name, NULL);
-
- if ((close(fd)) == -1)
- err_rm(file_name, NULL);
+ if ((close(fd)) == -1)
+ err_rm(file_name, NULL);
if (verbose)
(void)fprintf(stderr, "%s %qd bytes\n", file_name, size);
--- /dev/null
+#
+# 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 = newgrp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = newgrp.c
+
+OTHERSRCS = Makefile Makefile.preamble Makefile.postamble newgrp.1
+
+NEXTSTEP_PB_CFLAGS += -D__FBSDID=__RCSID
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(NAME)/Build
+
+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
--- /dev/null
+INSTALL_AS_USER = root
+INSTALL_PERMISSIONS = 4555
+
+after_install:
+ mkdir -p "$(DSTROOT)/usr/share/man/man1"
+ install -c -m 644 newgrp.1 "$(DSTROOT)/usr/share/man/man1/newgrp.1"
--- /dev/null
+
+AFTER_INSTALL = after_install
--- /dev/null
+{
+ DYNAMIC_CODE_GEN = YES;
+ FILESTABLE = {
+ FRAMEWORKS = ();
+ H_FILES = ();
+ OTHER_LINKED = (newgrp.c);
+ OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, newgrp.1);
+ SUBPROJECTS = ();
+ };
+ LANGUAGE = English;
+ LOCALIZABLE_FILES = {};
+ MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
+ NEXTSTEP_BUILDDIR = "/tmp/$(NAME)/Build";
+ NEXTSTEP_BUILDTOOL = /bin/gnumake;
+ NEXTSTEP_INSTALLDIR = /usr/bin;
+ NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
+ NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
+ PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make;
+ PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
+ PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
+ PROJECTNAME = newgrp;
+ PROJECTTYPE = Tool;
+ PROJECTVERSION = 2.8;
+ WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make;
+ WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
+ WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
+}
--- /dev/null
+.\" Copyright (c) 2002 Tim J. Robbins.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.bin/newgrp/newgrp.1,v 1.2 2002/05/30 13:57:35 ru Exp $
+.\"
+.Dd May 23, 2002
+.Dt NEWGRP 1
+.Os
+.Sh NAME
+.Nm newgrp
+.Nd change to a new group
+.Sh SYNOPSIS
+.Nm newgrp
+.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.
+.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.
+.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.
+.Pp
+Otherwise, the real, effective, and supplementary group IDs
+are restored to those from the current user's password database entry.
+.Sh DIAGNOSTICS
+The
+.Nm newgrp
+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
+exits >0.
+Otherwise, the exit status of
+.Nm newgrp
+is the exit status of the shell.
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr groups 1 ,
+.Xr login 1 ,
+.Xr sh 1 ,
+.Xr su 1 ,
+.Xr umask 1 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Nm newgrp
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm newgrp
+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.
+Their use is discouraged.
--- /dev/null
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * newgrp -- change to a new group
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/newgrp/newgrp.c,v 1.2 2003/10/30 15:14:34 harti Exp $");
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <libgen.h>
+#include <limits.h>
+#ifndef __APPLE__
+#include <login_cap.h>
+#endif /* !__APPLE__ */
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __APPLE__
+#include <paths.h>
+#endif /* __APPLE__ */
+static void addgroup(const char *grpname);
+static void doshell(void);
+static int inarray(gid_t, const gid_t[], int);
+static void loginshell(void);
+static void restoregrps(void);
+static void usage(void);
+
+static struct passwd *pwd;
+static uid_t euid;
+
+extern char **environ;
+
+/* Manipulate effective user ID. */
+#define PRIV_START do { \
+ if (seteuid(euid) < 0) \
+ err(1, "seteuid"); \
+ } while (0)
+#define PRIV_END do { \
+ if (seteuid(getuid()) < 0) \
+ err(1, "seteuid"); \
+ } while (0)
+
+int
+main(int argc, char *argv[])
+{
+ int ch, login;
+
+ euid = geteuid();
+ if (seteuid(getuid()) < 0)
+ err(1, "seteuid");
+
+ if ((pwd = getpwuid(getuid())) == NULL)
+ errx(1, "unknown user");
+
+ login = 0;
+ while ((ch = getopt(argc, argv, "-l")) != -1) {
+ switch (ch) {
+ case '-': /* Obsolescent */
+ case 'l':
+ login = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 0:
+ restoregrps();
+ break;
+ case 1:
+ addgroup(*argv);
+ break;
+ default:
+ usage();
+ }
+
+ if (seteuid(euid) < 0)
+ err(1, "seteuid");
+ if (setuid(getuid()) < 0)
+ err(1, "setuid");
+
+ if (login)
+ loginshell();
+ else
+ doshell();
+
+ /*NOTREACHED*/
+ exit(1);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: newgrp [-l] [group]\n");
+ exit(1);
+}
+
+static void
+restoregrps(void)
+{
+ int initres, setres;
+
+ PRIV_START;
+ initres = initgroups(pwd->pw_name, pwd->pw_gid);
+ setres = setgid(pwd->pw_gid);
+ PRIV_END;
+
+ if (initres < 0)
+ warn("initgroups");
+ if (setres < 0)
+ warn("setgroups");
+}
+
+static void
+addgroup(const char *grpname)
+{
+ gid_t grps[NGROUPS_MAX];
+ long lgid;
+ int dbmember, i, ngrps;
+ gid_t egid;
+ struct group *grp;
+ char *ep, *pass;
+ char **p;
+
+ egid = getegid();
+
+ /* Try it as a group name, then a group id. */
+ if ((grp = getgrnam(grpname)) == NULL)
+ if ((lgid = strtol(grpname, &ep, 10)) <= 0 || *ep != '\0' ||
+ (grp = getgrgid((gid_t)lgid)) == NULL ) {
+ warnx("%s: bad group name", grpname);
+ return;
+ }
+
+ /*
+ * If the user is not a member of the requested group and the group
+ * has a password, prompt and check it.
+ */
+ dbmember = 0;
+ if (pwd->pw_gid == grp->gr_gid)
+ dbmember = 1;
+ for (p = grp->gr_mem; *p != NULL; p++)
+ if (strcmp(*p, pwd->pw_name) == 0) {
+ dbmember = 1;
+ break;
+ }
+ if (!dbmember && *grp->gr_passwd != '\0' && getuid() != 0) {
+ pass = getpass("Password:");
+ if (pass == NULL ||
+ strcmp(grp->gr_passwd, crypt(pass, grp->gr_passwd)) != 0) {
+ fprintf(stderr, "Sorry\n");
+ return;
+ }
+ }
+
+ if ((ngrps = getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) {
+ warn("getgroups");
+ return;
+ }
+
+ /* Remove requested gid from supp. list if it exists. */
+ if (grp->gr_gid != egid && inarray(grp->gr_gid, grps, ngrps)) {
+ for (i = 0; i < ngrps; i++)
+ if (grps[i] == grp->gr_gid)
+ break;
+ ngrps--;
+ memmove(&grps[i], &grps[i + 1], (ngrps - i) * sizeof(gid_t));
+ PRIV_START;
+ if (setgroups(ngrps, (const gid_t *)grps) < 0) {
+ PRIV_END;
+ warn("setgroups");
+ return;
+ }
+ PRIV_END;
+ }
+
+ PRIV_START;
+ if (setgid(grp->gr_gid)) {
+ PRIV_END;
+ warn("setgid");
+ return;
+ }
+ PRIV_END;
+ grps[0] = grp->gr_gid;
+
+ /* Add old effective gid to supp. list if it does not exist. */
+ if (egid != grp->gr_gid && !inarray(egid, grps, ngrps)) {
+ if (ngrps == NGROUPS_MAX)
+ warnx("too many groups");
+ else {
+ grps[ngrps++] = egid;
+ PRIV_START;
+ if (setgroups(ngrps, (const gid_t *)grps)) {
+ PRIV_END;
+ warn("setgroups");
+ return;
+ }
+ PRIV_END;
+ }
+ }
+
+}
+
+static int
+inarray(gid_t gid, const gid_t grps[], int ngrps)
+{
+ int i;
+
+ for (i = 0; i < ngrps; i++)
+ if (grps[i] == gid)
+ return (1);
+ return (0);
+}
+
+/*
+ * Set the environment to what would be expected if the user logged in
+ * again; this performs the same steps as su(1)'s -l option.
+ */
+static void
+loginshell(void)
+{
+ char *args[2], **cleanenv, *term, *ticket;
+ const char *shell;
+#ifndef __APPLE__
+ login_cap_t *lc;
+#endif /* !__APPLE__ */
+ shell = pwd->pw_shell;
+ if (*shell == '\0')
+ shell = _PATH_BSHELL;
+ if (chdir(pwd->pw_dir) < 0) {
+ warn("%s", pwd->pw_dir);
+ chdir("/");
+ }
+
+ term = getenv("TERM");
+ ticket = getenv("KRBTKFILE");
+
+ if ((cleanenv = calloc(20, sizeof(char *))) == NULL)
+ err(1, "calloc");
+ *cleanenv = NULL;
+ environ = cleanenv;
+#ifndef __APPLE__
+ lc = login_getpwclass(pwd);
+ setusercontext(lc, pwd, pwd->pw_uid,
+ LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV);
+ login_close(lc);
+#endif /* !__APPLE__ */
+ setenv("USER", pwd->pw_name, 1);
+ setenv("SHELL", shell, 1);
+ setenv("HOME", pwd->pw_dir, 1);
+ if (term != NULL)
+ setenv("TERM", term, 1);
+ if (ticket != NULL)
+ setenv("KRBTKFILE", ticket, 1);
+
+ if (asprintf(args, "-%s", basename(shell)) < 0)
+ err(1, "asprintf");
+ args[1] = NULL;
+
+ execv(shell, args);
+ err(1, "%s", shell);
+}
+
+static void
+doshell(void)
+{
+ const char *shell;
+
+ shell = pwd->pw_shell;
+ if (*shell == '\0')
+ shell = _PATH_BSHELL;
+ execl(shell, basename(shell), (char *)NULL);
+ err(1, "%s", shell);
+}
.Pa /etc/nologin.txt
exists,
.Nm nologin
-displays its contents to the user instead of the default message.
+displays its contents (instead of the default message) to the user.
.Sh SEE ALSO
.Xr login 1
.Sh HISTORY
value of the byte. The type for new variables is always binary
data.
.SH OPTIONS
+.\" ==========
.TP
-.B \-p
-Print all of the firmware variables.
+.BI \-d " name"
+Deletes the named firmware variable.
+.\" ==========
.TP
.BI \-f " filename"
Set firmware variables from a text file. The file must be a
-list name=value statements. If the last character of a line is
-\\, the value will be continued to the next line.
+list of "name value" statements. The first space on each line
+is taken to be the separator between "name" and "value". If
+the last character of a line is \\, the value extends to the next line.
+.\" ==========
.TP
-.BI \-d " name"
-Deletes the named firmware variable.
+.B \-x
+Use XML format for reading and writing variables.
+This option must be used before the
+.B \-p
+or
+.B \-f
+options, since arguments are processed in order.
+.TP
+.B \-p
+Print all of the firmware variables.
.SH EXAMPLES
.LP
.RS
static void FatalError(long exitValue, char *format, long item);
static void UsageMessage(char *message);
static void ParseFile(char *fileName);
+static void ParseXMLFile(char *fileName);
static void SetOrGetOFVariable(char *str);
static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef,
CFTypeRef *valueRef);
static void DeleteOFVariable(char *name);
static void PrintOFVariables(void);
static void PrintOFVariable(const void *key,const void *value,void *context);
+static void SetOFVariableFromFile(const void *key, const void *value, void *context);
+static void ClearOFVariables(void);
+static void ClearOFVariable(const void *key,const void *value,void *context);
static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value);
// Global Variables
static char *gToolName;
static io_registry_entry_t gOptionsRef;
+static bool gUseXML;
int main(int argc, char **argv)
case 'p' :
PrintOFVariables();
break;
-
+
+ case 'x' :
+ gUseXML = true;
+ break;
+
case 'f':
cnt++;
if (cnt < argc && *argv[cnt] != '-') {
}
break;
+ case 'c':
+ ClearOFVariables();
+ break;
+
default:
strcpy(errorMessage, "no such option as --");
errorMessage[strlen(errorMessage)-1] = *str;
{
Error("(usage: %s)", (long)message);
- printf("%s [-p] [-f filename] [-d name] name[=value] ...\n", gToolName);
+ printf("%s [-x] [-p] [-f filename] [-d name] name[=value] ...\n", gToolName);
+ printf("\t-x use XML format for printing or reading variables\n");
+ printf("\t (must appear before -p or -f)\n");
printf("\t-p print all firmware variables\n");
printf("\t-f set firmware variables from a text file\n");
printf("\t-d delete the named variable\n");
+ printf("\t-c delete all variables\n");
printf("\tname=value set named variable\n");
printf("\tname print variable\n");
printf("Note that arguments and options are executed in order.\n");
char name[kMaxNameSize];
char value[kMaxStringSize];
FILE *patches;
+
+ if (gUseXML) {
+ ParseXMLFile(fileName);
+ return;
+ }
patches = fopen(fileName, "r");
if (patches == 0) {
state = kFirstColumn;
while ((tc = getc(patches)) != EOF) {
+ if(ni==(kMaxNameSize-1))
+ FatalError(-1,"Name exceeded max length of %d",kMaxNameSize);
+ if(vi==(kMaxStringSize-1))
+ FatalError(-1,"Value exceeded max length of %d",kMaxStringSize);
switch (state) {
case kFirstColumn :
ni = 0;
}
+// ParseXMLFile(fileName)
+//
+// Open and parse the specified file in XML format,
+// and set variables appropriately.
+//
+static void ParseXMLFile(char *fileName)
+{
+ CFPropertyListRef plist;
+ CFURLRef fileURL = NULL;
+ CFStringRef filePath = NULL;
+ CFStringRef errorString = NULL;
+ CFDataRef data = NULL;
+ SInt32 errorCode = 0;
+
+ filePath = CFStringCreateWithCString(kCFAllocatorDefault, fileName, kCFStringEncodingUTF8);
+ if (filePath == NULL) {
+ FatalError(-1, "Could not create file path string", 0);
+ }
+
+ // Create a URL that specifies the file we will create to
+ // hold the XML data.
+ fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
+ filePath,
+ kCFURLPOSIXPathStyle,
+ false /* not a directory */ );
+ if (fileURL == NULL) {
+ FatalError(-1, "Could not create file path URL", 0);
+ }
+
+ CFRelease(filePath);
+
+ if (! CFURLCreateDataAndPropertiesFromResource(
+ kCFAllocatorDefault,
+ fileURL,
+ &data,
+ NULL,
+ NULL,
+ &errorCode) || data == NULL ) {
+ FatalError(-1, "Error reading XML file (%d)", errorCode);
+ }
+
+ CFRelease(fileURL);
+
+ plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
+ data,
+ kCFPropertyListImmutable,
+ &errorString);
+
+ CFRelease(data);
+
+ if (plist == NULL) {
+ FatalError(-1, "Error parsing XML file", 0);
+ }
+
+ if (errorString != NULL) {
+ FatalError(-1, "Error parsing XML file: %s", (long)CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8));
+ }
+
+ CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0);
+
+ CFRelease(plist);
+}
+
// SetOrGetOFVariable(str)
//
// Parse the input string, then set or get the specified
if (result != KERN_SUCCESS) {
FatalError(-1, "Error (%d) getting the firmware variables", result);
}
- CFDictionaryApplyFunction(dict, &PrintOFVariable, 0);
+
+ if (gUseXML) {
+ CFDataRef data;
+
+ data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict );
+ if (data == NULL) {
+ FatalError(-1, "Error (%d) converting variables to xml", result);
+ }
+
+ fwrite(CFDataGetBytePtr(data), sizeof(UInt8), CFDataGetLength(data), stdout);
+
+ CFRelease(data);
+
+ } else {
+
+ CFDictionaryApplyFunction(dict, &PrintOFVariable, 0);
+
+ }
CFRelease(dict);
}
-
// PrintOFVariable(key, value, context)
//
// Print the given firmware variable.
if (valueBuffer != 0) free(valueBuffer);
}
+// ClearOFVariables()
+//
+// Deletes all OF variables
+//
+static void ClearOFVariables(void)
+{
+ kern_return_t result;
+ CFMutableDictionaryRef dict;
+
+ result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0);
+ if (result != KERN_SUCCESS) {
+ FatalError(-1, "Error (%d) getting the firmware variables", result);
+ }
+ CFDictionaryApplyFunction(dict, &ClearOFVariable, 0);
+
+ CFRelease(dict);
+}
+
+static void ClearOFVariable(const void *key, const void *value, void *context)
+{
+ kern_return_t result;
+ result = IORegistryEntrySetCFProperty(gOptionsRef,
+ CFSTR(kIONVRAMDeletePropertyKey), key);
+ if (result != KERN_SUCCESS) {
+ FatalError(-1, "Error (%d) clearing firmware variables", result);
+ }
+}
// ConvertValueToCFTypeRef(typeID, value)
//
value[cnt2] = number;
} else value[cnt2] = value[cnt];
}
- valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, value,
+ valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value,
cnt2, kCFAllocatorDefault);
} else return 0;
return valueRef;
}
+static void SetOFVariableFromFile(const void *key, const void *value, void *context)
+{
+ kern_return_t result;
+
+ result = IORegistryEntrySetCFProperty(gOptionsRef, key, value);
+ if ( result != KERN_SUCCESS ) {
+ int nameLen;
+ char *nameBuffer;
+ char *nameString;
+
+ // Get the variable's name.
+ nameLen = CFStringGetLength(key) + 1;
+ nameBuffer = malloc(nameLen);
+ if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) )
+ nameString = nameBuffer;
+ else {
+ Error("Error (-1) Unable to convert property name to C string", 0);
+ nameString = "<UNPRINTABLE>";
+ }
+ FatalError(-1, "Error (-1) setting variable - '%s'", (long)nameString);
+ }
+}
HFILES = stringops.h
-CFILES = nis_passwd.c file_passwd.c netinfo_passwd.c ds_passwd.c passwd.c\
+CFILES = nis_passwd.c file_passwd.c od_passwd.c passwd.c\
stringops.c
OTHERSRCS = Makefile.preamble Makefile Makefile.postamble passwd.1
NEXTSTEP_INSTALLDIR = /usr/bin
WINDOWS_INSTALLDIR = /usr/bin
PDO_UNIX_INSTALLDIR = /usr/bin
-LIBS = /System/Library/Frameworks/DirectoryService.framework/Versions/A/DirectoryService
+LIBS =
DEBUG_LIBS = $(LIBS)
PROF_LIBS = $(LIBS)
+FRAMEWORK_PATHS = -F/System/Library/PrivateFrameworks
+FRAMEWORKS = -framework OpenDirectory -framework CoreFoundation
C_FILES = ();
H_FILES = (stringops.h);
OTHER_LIBS = ();
- OTHER_LINKED = (nis_passwd.c, file_passwd.c, netinfo_passwd.c, passwd.c, stringops.c);
+ OTHER_LINKED = (nis_passwd.c, file_passwd.c, passwd.c, stringops.c);
OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, passwd.1);
SUBPROJECTS = ();
};
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <string.h>
-#include <sys/dirent.h>
-
-#include <DirectoryService/DirServices.h>
-#include <DirectoryService/DirServicesConst.h>
-#include <DirectoryService/DirServicesTypes.h>
-#include <DirectoryService/DirServicesUtils.h>
-
-// password server can store 511 characters + a terminator.
-#define kMaxPassword 512
-
-//-------------------------------------------------------------------------------------
-// ds_getpasswd
-//-------------------------------------------------------------------------------------
-
-void
-ds_getpasswd(const char *loginUser, char *name, int isroot, int wasroot, int changePassOnSelf, char **old_clear, char **new_clear)
-{
- int tries, len;
- char *p;
- static char obuf[kMaxPassword];
- static char nbuf[kMaxPassword];
- char prompt[MAXNAMLEN + 16];
-
- printf("Changing password for %s.\n", name);
-
- p = "";
-
- if (isroot == 0)
- {
- if ( changePassOnSelf )
- {
- strcpy( prompt, "Old password:" );
- }
- else
- {
- snprintf( prompt, sizeof(prompt), "password for %s:", loginUser );
- }
-
- p = getpass( prompt );
- snprintf( obuf, sizeof(obuf), "%s", p );
- }
-
- if ( wasroot == 0 )
- {
- tries = 0;
- nbuf[0] = '\0';
- for (;;)
- {
- p = getpass("New password:");
- if (!*p)
- {
- printf("Password unchanged.\n");
- exit(0);
- }
-
- tries++;
- len = strlen(p);
-
- snprintf( nbuf, sizeof(nbuf), "%s", p );
- if (!strcmp(nbuf, getpass("Retype new password:"))) break;
-
- printf("Mismatch; try again, EOF to quit.\n");
- }
- }
-
- *old_clear = obuf;
- *new_clear = nbuf;
-}
-
-
-//-------------------------------------------------------------------------------------
-// ds_passwd
-//-------------------------------------------------------------------------------------
-
-int
-ds_passwd(char *uname, char *locn)
-{
- 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;
- char *old_clear = NULL;
- char *new_clear = NULL;
- int isroot = 0;
- int wasroot = 0;
- char *loginUser = NULL;
- int changePassOnSelf = 1;
- const char *errMsgStr = NULL;
- struct passwd *userRec = NULL;
-
- if (uname == NULL)
- return -1;
-
- /* getlogin() is the wrong thing to use here. Use getpwuid(getuid()); */
- /* sns 5 Jan 2005 */
-
- userRec = getpwuid( getuid() );
- if ( userRec != NULL ) {
- loginUser = userRec->pw_name;
- if ( loginUser != NULL )
- changePassOnSelf = (strcmp(loginUser, uname) == 0);
- }
-
- status = dsOpenDirService( &dsRef );
- if (status != eDSNoErr)
- return status;
-
- do
- {
- if ( tDataBuff == NULL )
- tDataBuff = dsDataBufferAllocate( dsRef, 4096 );
- if (tDataBuff == NULL) break;
-
- if ( locn != NULL )
- {
- nodeName = dsBuildFromPath( dsRef, locn, "/" );
- 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) break;
- if ( nodeCount < 1 ) {
- status = eDSNodeNotFound;
- break;
- }
-
- if ( isroot == 1 )
- {
- // we already tried SetPasswordAsRoot and it didn't work
- // get the old (current) password and try again
-
- // getpass
- isroot = 0;
- wasroot = 1;
- }
- else
- if ( getuid() == 0 )
- isroot = 1;
-
- ds_getpasswd( loginUser, uname, isroot, wasroot, changePassOnSelf, &old_clear, &new_clear );
-
- status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName );
- if (status != eDSNoErr) continue;
-
- status = dsOpenDirNode( dsRef, nodeName, &nodeRef );
- dsDataListDeallocate( dsRef, nodeName );
- free( nodeName );
- nodeName = NULL;
- if (status != eDSNoErr) continue;
-
- 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 ) break;
- if ( recCount == 0 ) {
- status = eDSAuthUnknownUser;
- break;
- }
-
- status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry );
- if ( status != eDSNoErr ) break;
-
- 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;
- }
- }
-
- if ( pUserLocation == NULL || pUserName == NULL ) {
- status = eDSAuthInvalidUserName;
- break;
- }
-
- pUserNode = dsBuildFromPath( dsRef, pUserLocation, "/" );
- status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef );
- if ( status != eDSNoErr ) break;
-
- pStepBuff = dsDataBufferAllocate( dsRef, 128 );
-
- if ( isroot )
- {
- pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswdAsRoot );
- 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;
-
- // new pw
- uiLen = strlen( new_clear );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
- uiCurr += uiLen;
-
- tDataBuff->fBufferLength = uiCurr;
-
- status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
- }
- else
- if ( changePassOnSelf )
- {
- pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthChangePasswd );
- 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;
-
- // old pw
- uiLen = strlen( old_clear );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen );
- uiCurr += uiLen;
-
- // new pw
- uiLen = strlen( new_clear );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
- uiCurr += uiLen;
-
- tDataBuff->fBufferLength = uiCurr;
-
- status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
- }
- else
- if ( loginUser != NULL )
- {
- pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswd );
- 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;
-
- // new pw
- uiLen = strlen( new_clear );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
- uiCurr += uiLen;
-
- // Authenticator name
- uiLen = strlen( loginUser );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), loginUser, uiLen );
- uiCurr += uiLen;
-
- // authenticator pw
- uiLen = strlen( old_clear );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
- uiCurr += sizeof( unsigned long );
- memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen );
- uiCurr += uiLen;
-
- tDataBuff->fBufferLength = uiCurr;
-
- status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
- }
- else
- {
- status = eDSAuthFailed;
- }
- }
- while ( isroot == 1 && status != eDSNoErr );
-
- /* old_clear and new_clear are statics (don't call free) */
- if (old_clear != NULL) {
- memset(old_clear, 0, strlen(old_clear));
- }
- if (new_clear != NULL) {
- memset(new_clear, 0, strlen(new_clear));
- }
- 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;
- switch( status )
- {
- case eDSAuthPasswordTooShort:
- errMsgStr = "The new password is too short.";
- break;
-
- case eDSAuthPasswordTooLong:
- errMsgStr = "The new password is too long.";
- break;
-
- case eDSAuthPasswordNeedsLetter:
- errMsgStr = "The new password must contain a letter.";
- break;
-
- case eDSAuthPasswordNeedsDigit:
- errMsgStr = "The new password must contain a number.";
- break;
-
- default:
- errMsgStr = "Sorry";
- }
- fprintf(stderr, "%s\n", errMsgStr);
- exit(1);
- }
-
- return status;
-}
-
-
-
-
-
-
-
-
-
-
-
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <string.h>
-#include <netinfo/ni.h>
-
-extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
-
-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;
- //int i, len; (unused)
-
- 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;
-}
-
-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_passwd(char *uname, char *locn)
-{
- char *oldpw;
- char *newpw;
- char *oc, *nc;
- void *d;
- int status, isroot;
- ni_id dir;
- ni_proplist pl;
- ni_property p;
- ni_namelist nl;
- int ni_uid, uid, secure, minlen;
- ni_index where;
-
- 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];
-
- status = ni_lookupprop(d, &dir, "uid", &nl);
- if (status != NI_OK)
- {
- ni_free(d);
- fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
- exit(1);
- }
-
- ni_uid = -2;
- if (nl.ni_namelist_len > 0) ni_uid = atoi(nl.ni_namelist_val[0]);
-
- /*
- * See if I'm uid 0 on the master host for the user's NetInfo domain.
- */
- isroot = is_root_on_master(d);
- uid = getuid();
- if ((isroot == 0) && (uid != ni_uid))
- {
- ni_free(d);
- fprintf(stderr, "Permission denied\n");
- exit(1);
- }
-
- /*
- * Lock onto the master server.
- */
- ni_needwrite(d, 1);
-
- /*
- * Get the new password
- */
- secure = secure_passwords();
- minlen = 5;
- if (secure == 1) minlen = 8;
- getpasswd(uname, isroot, minlen, 0, secure, oldpw, &newpw, &oc, &nc);
-
- /*
- * Authenticate if necessary
- */
- if (isroot == 0)
- {
- ni_setuser(d, uname);
- ni_setpassword(d, oc);
- }
-
- /*
- * Change the password in NetInfo.
- */
- status = ni_read(d, &dir, &pl);
- if (status != NI_OK)
- {
- ni_free(d);
- fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
- exit(1);
- }
-
- p.nip_name = "passwd";
- p.nip_val.ni_namelist_len = 1;
- p.nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
- p.nip_val.ni_namelist_val[0] = newpw;
-
- where = ni_proplist_match(pl, p.nip_name, NULL);
- if (where == NI_INDEX_NULL)
- status = ni_createprop(d, &dir, p, NI_INDEX_NULL);
- else
- status = ni_writeprop(d, &dir, where, p.nip_val);
-
- free(p.nip_val.ni_namelist_val);
-
- if (status != NI_OK)
- {
- ni_free(d);
- fprintf(stderr, "NetInfo write failed: %s\n", ni_error(status));
- exit(1);
- }
-
- ni_free(d);
- return (0);
-}
tv.tv_sec = 2;
tv.tv_usec = 0;
ans = clnt_call(cl, YPPASSWDPROC_UPDATE,
- xdr_yppasswd, &yppasswd, xdr_int, &ok, tv);
+ (xdrproc_t)xdr_yppasswd, &yppasswd, (xdrproc_t)xdr_int, &ok, tv);
if (ans != 0)
{
--- /dev/null
+/*
+ * Copyright (c) 1999-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@
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/sysctl.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenDirectory/OpenDirectory.h>
+#include <OpenDirectory/OpenDirectoryPriv.h>
+#include <DirectoryService/DirServicesTypes.h>
+
+extern char* progname;
+int master_mode;
+
+static int
+cfprintf(FILE* file, const char* format, ...) {
+ char* cstr;
+ int result = 0;
+ va_list args;
+ va_start(args, format);
+ CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull);
+ if (formatStr) {
+ CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args);
+ if (str) {
+ size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1;
+ va_end(args);
+ cstr = malloc(size);
+ if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) {
+ result = fprintf(file, "%s", cstr);
+ free(cstr);
+ }
+ CFRelease(str);
+ }
+ CFRelease(formatStr);
+ }
+ return result;
+}
+
+static void
+show_error(CFErrorRef error) {
+ if (error) {
+ CFStringRef desc = CFErrorCopyDescription(error);
+ if (desc) {
+ cfprintf(stderr, "%s: %@", progname, desc);
+ CFRelease(desc);
+ }
+ desc = CFErrorCopyFailureReason(error);
+ if (desc) cfprintf(stderr, " %@", desc);
+
+ desc = CFErrorCopyRecoverySuggestion(error);
+ if (desc) cfprintf(stderr, " %@", desc);
+
+ fprintf(stderr, "\n");
+ }
+}
+
+static int
+is_singleuser(void) {
+ uint32_t su = 0;
+ size_t susz = sizeof(su);
+ if (sysctlbyname("kern.singleuser", &su, &susz, NULL, 0) != 0) {
+ return 0;
+ } else {
+ return (int)su;
+ }
+}
+
+static int
+load_DirectoryServicesLocal() {
+ const char* launchctl = "/bin/launchctl";
+ const char* plist = "/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist";
+
+ pid_t pid = fork();
+ int status, res;
+ switch (pid) {
+ case -1: // ERROR
+ perror("launchctl");
+ return 0;
+ case 0: // CHILD
+ execl(launchctl, launchctl, "load", plist, NULL);
+ /* NOT REACHED */
+ perror("launchctl");
+ exit(1);
+ break;
+ default: // PARENT
+ do {
+ res = waitpid(pid, &status, 0);
+ } while (res == -1 && errno == EINTR);
+ if (res == -1) {
+ perror("launchctl");
+ return 0;
+ }
+ break;
+ }
+ return (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS));
+}
+
+int
+od_passwd(char* uname, char* locn, char* aname)
+{
+ int change_pass_on_self;
+ CFErrorRef error = NULL;
+ CFStringRef username = NULL;
+ CFStringRef location = NULL;
+ CFStringRef authname = NULL;
+ ODSessionRef session = NULL;
+ ODNodeRef node = NULL;
+ ODRecordRef rec = NULL;
+ CFStringRef oldpass = NULL;
+ CFStringRef newpass = NULL;
+
+ if (uname == NULL)
+ return -1;
+
+ /*
+ * If no explicit authorization name was specified (via -u)
+ * then default to the target user.
+ */
+ if (!aname) {
+ aname = strdup(uname);
+ }
+
+ master_mode = (getuid() == 0);
+ change_pass_on_self = (strcmp(aname, uname) == 0);
+
+ if (locn) {
+ location = CFStringCreateWithCString(NULL, locn, kCFStringEncodingUTF8);
+ }
+
+ if (aname) {
+ authname = CFStringCreateWithCString(NULL, aname, kCFStringEncodingUTF8);
+ }
+
+ if (uname) {
+ username = CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8);
+ if (!username) return -1;
+ }
+
+ /*
+ * Connect to DS server
+ */
+ session = ODSessionCreate(NULL, NULL, &error);
+ if ( !session && error && CFErrorGetCode(error) == eServerNotRunning ) {
+ /*
+ * In single-user mode, attempt to load the local DS daemon.
+ */
+ if (is_singleuser() && load_DirectoryServicesLocal()) {
+ CFTypeRef keys[] = { kODSessionLocalPath };
+ CFTypeRef vals[] = { CFSTR("/var/db/dslocal") };
+ CFDictionaryRef opts = CFDictionaryCreate(NULL, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (opts) {
+ session = ODSessionCreate(NULL, opts, &error);
+ CFRelease(opts);
+ }
+
+ if (!location) {
+ location = CFRetain(CFSTR("/Local/Default"));
+ }
+ } else {
+ show_error(error);
+ return -1;
+ }
+ }
+
+
+ /*
+ * Copy the record from the specified node, or perform a search.
+ */
+ if (location) {
+ node = ODNodeCreateWithName(NULL, session, location, &error);
+ } else {
+ node = ODNodeCreateWithNodeType(NULL, session, kODTypeAuthenticationSearchNode, &error);
+ }
+
+ if (session) CFRelease(session);
+
+ if (node) {
+ rec = ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), username, NULL, &error );
+ CFRelease(node);
+ }
+
+ if (!rec) {
+ if (error) {
+ show_error(error);
+ } else {
+ fprintf(stderr, "%s: Unknown user name '%s'.\n", progname, uname);
+ }
+ return -1;
+ }
+
+ /*
+ * Get the actual location.
+ */
+ CFArrayRef values = NULL;
+ values = ODRecordCopyValues(rec, CFSTR(kDSNAttrMetaNodeLocation), &error);
+ location = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : location;
+
+ printf("Changing password for %s.\n", uname);
+
+ /*
+ * Prompt for password if not super-user, or if changing a remote node.
+ */
+ int needs_auth = (!master_mode || CFStringCompareWithOptions(location, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo);
+
+ if (needs_auth) {
+ char prompt[BUFSIZ];
+ if (change_pass_on_self) {
+ strlcpy(prompt, "Old password:", sizeof(prompt));
+ } else {
+ snprintf(prompt, sizeof(prompt), "Password for %s:", aname);
+ }
+ char *p = getpass( prompt );
+ if (p) {
+ oldpass = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
+ memset(p, 0, strlen(p));
+ }
+ }
+
+ for (;;) {
+ char *p = getpass("New password:");
+ if (p && strlen(p) > 0) {
+ newpass = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
+ memset(p, 0, strlen(p));
+ } else {
+ printf("Password unchanged.\n");
+ exit(0);
+ }
+
+ p = getpass("Retype new password:");
+ if (p) {
+ CFStringRef verify = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
+ if (!verify || !CFEqual(newpass, verify)) {
+ if (verify) CFRelease(verify);
+ printf("Mismatch; try again, EOF to quit.\n");
+ } else {
+ CFRelease(verify);
+ break;
+ }
+ }
+ }
+
+ if (needs_auth) {
+ CFTypeRef values[] = { username, newpass, authname, oldpass };
+ CFArrayRef authItems = CFArrayCreate(NULL, values, 4, &kCFTypeArrayCallBacks);
+
+ ODRecordSetNodeCredentialsExtended(rec,
+ CFSTR(kDSStdRecordTypeUsers),
+ CFSTR(kDSStdAuthSetPasswd),
+ authItems,
+ NULL,
+ NULL,
+ &error);
+
+ CFRelease(authItems);
+ } else {
+ ODRecordChangePassword(rec, oldpass, newpass, &error);
+ }
+
+ if (error) {
+ show_error(error);
+ exit(1);
+ }
+
+ if (oldpass) CFRelease(oldpass);
+ if (newpass) CFRelease(newpass);
+
+#if 0
+ if ( status != eDSNoErr ) {
+ switch( status )
+ {
+ case eDSAuthPasswordTooShort:
+ errMsgStr = "The new password is too short.";
+ break;
+
+ case eDSAuthPasswordTooLong:
+ errMsgStr = "The new password is too long.";
+ break;
+
+ case eDSAuthPasswordNeedsLetter:
+ errMsgStr = "The new password must contain a letter.";
+ break;
+
+ case eDSAuthPasswordNeedsDigit:
+ errMsgStr = "The new password must contain a number.";
+ break;
+
+ default:
+ errMsgStr = "Sorry";
+ }
+ fprintf(stderr, "%s\n", errMsgStr);
+ exit(1);
+#endif
+ return 0;
+}
.Nm passwd
.Op Fl i Ar infosystem
.Op Fl l Ar location
+.Op Fl u Ar authname
.Op Ar name
.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 avoid typing errors.
+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.
.Pp
-The new password should be at least six characters long and not
-purely alphabetic.
+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
+(currently 128 characters),
+although some infosystems allow longer passwords.
+Numbers, upper-case letters, and meta characters
are encouraged.
.Pp
Once the password has been verified,
.Bl -tag -width flag
.It Fl i Ar infosystem
This option specifies where the password update should be applied.
-Under Mac OS X 10.3, supported infosystems are:
+Under Mac OS X 10.5, supported infosystems are:
.Bl -tag -width flag
.It Ar opendirectory
(default)
-A system conforming to opendirectory APIs and supporting updates (including LDAP, netinfo, etc).
+A system conforming to opendirectory APIs and supporting updates
+(including LDAP, etc).
If no -l option is specified, the search node is used.
-.It Ar netinfo
-The netinfo database containing the user's password.
-If no -l option is specified, the local netinfo database is assumed.
.It Ar file
The local flat-files (included for legacy configurations).
.It Ar nis
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 choosen infosystem.
-When changing only the local password,
-.Xr pwd_mkdb 8
-is used to update the password databases.
+This option causes the password to be updated in the given location
+of the chosen infosystem.
.Bl -tag -width flag
-.It for netinfo,
-location may be a domain name or server/tag
.It for file,
location may be a file name (/etc/master.passwd is the default)
.It for nis,
.It for opendirectory,
location may be a directory node name
.El
+.It Fl u Ar authname
+This option specifies the username to use when authenticating to
+the directory node.
.El
.Pp
-The super-user privilages are not required change a user's current password
+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
.Sh SEE ALSO
.Xr chpass 1 ,
.Xr login 1 ,
+.Xr dscl 1 ,
.Xr passwd 5 ,
.Xr pwd_mkdb 8 ,
-.Xr vipw 8 ,
-.Xr nicl 1
+.Xr vipw 8
.Rs
.%A Robert Morris
.%A Ken Thompson
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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@
*/
-#define INFO_NETINFO 0
+#include <TargetConditionals.h>
+
#define INFO_FILE 1
#define INFO_NIS 2
-#define INFO_DIRECTORYSERVICES 3
+#if !TARGET_OS_EMBEDDED
+#define INFO_OPEN_DIRECTORY 3
+#endif
#ifndef __SLICK__
#define _PASSWD_FILE "/etc/master.passwd"
#include <libc.h>
#include <ctype.h>
#include <string.h>
-#include <netinfo/ni.h>
#include "stringops.h"
#ifdef __SLICK__
#define _PASSWORD_LEN 8
#endif
+char* progname = "passwd";
+
static char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
extern int file_passwd(char *, char *);
-extern int netinfo_passwd(char *, char *);
extern int nis_passwd(char *, char *);
-extern int ds_passwd(char *, char *);
+#ifdef INFO_OPEN_DIRECTORY
+extern int od_passwd(char *, char *, char*);
+#endif
void
getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha,
void
usage()
{
- fprintf(stderr, "usage: passwd [-i infosystem] [-l location] [name]\n");
- fprintf(stderr, "supported infosystems are:\n");
- fprintf(stderr, " netinfo\n");
+ 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, "for netinfo, location may be a domain name or server/tag\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, " 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");
exit(1);
}
int
main(int argc, char *argv[])
{
- char *user, *locn;
- int i, infosystem;
+ char* user = NULL;
+ char* locn = NULL;
+ char* auth = NULL;
+ int infosystem, ch;
int free_user = 0;
- /* since DS works for most infosystems, make it the default */
- //infosystem = INFO_NETINFO;
- infosystem = INFO_DIRECTORYSERVICES;
- user = NULL;
- locn = NULL;
+#ifdef INFO_OPEN_DIRECTORY
+ /* since OpenDirectory works for most infosystems, make it the default */
+ infosystem = INFO_OPEN_DIRECTORY;
+#else
+ infosystem = INFO_FILE;
+#endif
- 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], "NetInfo")) infosystem = INFO_NETINFO;
- else if (!strcmp(argv[i], "netinfo")) infosystem = INFO_NETINFO;
- else 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]);
+ while ((ch = getopt(argc, argv, "i:l:u:")) != -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;
+#ifdef INFO_OPEN_DIRECTORY
+ } else if (!strcasecmp(optarg, "opendirectory")) {
+ infosystem = INFO_OPEN_DIRECTORY;
+#endif
+ } else {
+ fprintf(stderr, "%s: Unknown info system \'%s\'.\n",
+ progname, optarg);
usage();
}
- }
+ break;
+ case 'l':
+ locn = optarg;
+ break;
+ case 'u':
+ auth = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ argc -= optind;
+ argv += optind;
- else if (!strcmp(argv[i], "-l"))
- {
- if (++i >= argc)
- {
- fprintf(stderr, "no argument for -l option\n");
- usage();
- }
- locn = argv[i];
- }
- else if (user == NULL) user = argv[i];
- else usage();
+ if (argc > 1) {
+ usage();
+ } else if (argc == 1) {
+ user = argv[0];
}
if (user == NULL)
switch (infosystem)
{
- case INFO_NETINFO:
- netinfo_passwd(user, locn);
- break;
case INFO_FILE:
file_passwd(user, locn);
break;
case INFO_NIS:
nis_passwd(user, locn);
break;
- case INFO_DIRECTORYSERVICES:
- ds_passwd(user, locn);
+#ifdef INFO_OPEN_DIRECTORY
+ case INFO_OPEN_DIRECTORY:
+ od_passwd(user, locn, auth);
break;
+#endif
}
if (free_user == 1)
+++ /dev/null
-#
-# 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 = pt_chown
-
-PROJECTVERSION = 1.1
-PROJECT_TYPE = Tool
-
-CFILES = pt_chown.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/libexec
-WINDOWS_INSTALLDIR = /usr/libexec
-PDO_UNIX_INSTALLDIR = /usr/libexec
-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
+++ /dev/null
-after_install:
- chmod 4511 $(DSTROOT)/usr/libexec/pt_chown
+++ /dev/null
-OTHER_CFLAGS = -D__FBSDID=__RCSID
+++ /dev/null
-{
- FILESTABLE = {
- FRAMEWORKS = ();
- OTHER_LINKED = (pt_chown.c);
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist);
- PRECOMPILED_HEADERS = ();
- PROJECT_HEADERS = ();
- PUBLIC_HEADERS = ();
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- LOCALIZABLE_FILES = {};
- NEXTSTEP_BUILDDIR = "";
- NEXTSTEP_BUILDTOOL = /bin/make;
- NEXTSTEP_COMPILEROPTIONS = "";
- NEXTSTEP_INSTALLDIR = /usr/libexec;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_LINKEROPTIONS = "";
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDDIR = "";
- PDO_UNIX_BUILDTOOL = /bin/make;
- PDO_UNIX_COMPILEROPTIONS = "";
- PDO_UNIX_INSTALLDIR = /usr/libexec;
- PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
- PDO_UNIX_LINKEROPTIONS = "";
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = pt_chown;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 1.1;
- WINDOWS_BUILDDIR = "";
- WINDOWS_BUILDTOOL = /bin/make;
- WINDOWS_COMPILEROPTIONS = "";
- WINDOWS_INSTALLDIR = /usr/libexec;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_LINKEROPTIONS = "";
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-/*
- * Copyright (c) 2002 The FreeBSD Project, Inc.
- * All rights reserved.
- *
- * This software includes code contributed to the FreeBSD Project
- * by Ryan Younce of North Carolina State University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the FreeBSD Project nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/libexec/pt_chown/pt_chown.c,v 1.1 2003/01/02 20:44:41 jmallett Exp $");
-#endif /* not lint */
-
-#include <sys/stat.h>
-
-#include <grp.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-/*
- * pt_chown
- * Utility support routine for grantpt(3).
- *
- * According to IEEE Std 1003.1-2001, grantpt(3) changes ownership and
- * permission bits of a slave pseudo-terminal device associated with a
- * master.
- *
- * Since doing this if we are not the owner of the slave (which would
- * rarely happen) cannot be done by conventional methods, grantpt(3)
- * has to rely on this support program, which is setuid root, to change
- * the slave's owner, group, and permission mode attributes. It's
- * a rather undesirable approach, but Digital Unix and Solaris also seem
- * to rely on this approach to pull this off.
- *
- * This program hangs around long enough to do just these things upon
- * its standard input (which is set up by grantpt(3) to be the master's
- * descriptor, the one passed to it). The rationale behind this
- * approach not allowing somebody to modify ownership of another active
- * pseudo terminal is:
- *
- * 1) This program only operates on its standard input. If STDIN_FILENO
- * is not open or is not a pseudo-terminal master, no action is
- * taken and the program exits (ptsname() is called for a non-NULL
- * return).
- * 2) Only one active file description for a pseudo-terminal master
- * can exist at a time (attempting to open an active PTY returns with
- * EIO - I/O Error). Thus, if the pseudo-terminal is already in
- * use by somebody else, it could not have been opened to begin
- * with, and thus this program would be useless in such situations.
- */
-int
-main(int argc, char *argv[])
-{
- int retcode;
- char *slave;
- gid_t gid;
- struct group *grp;
-
- retcode = EX_OK;
-
- if ((slave = ptsname(STDIN_FILENO)) == NULL)
- retcode = EX_USAGE;
- else {
- gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1;
- if (chown(slave, getuid(), gid) == 0 &&
- chmod(slave, S_IRUSR | S_IWUSR | S_IWGRP) == 0)
- retcode = 0;
- else
- retcode = EX_NOPERM;
- }
-
- /*
- * grantpt(3) checks the retcode for being either zero or
- * nonzero. Any nonzero return results in errno being set
- * to EACCES.
- */
- exit(retcode);
-}
.Op Fl u Ar username
.Ar file
.Sh DESCRIPTION
-.Nm
+.Nm pwd_mkdb
creates
.Xr db 3
style secure and insecure databases for the specified file.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.\" ==========
.It Fl c
Check if the password file is in the correct format.
Do not change, add, or remove any files.
-.It Fl p
-Create a Version 7 style password file and install it into
-.Pa /etc/passwd .
-.It Fl s
-Only update the secure version of the database.
-This is most commonly used in conjunction with the
-.Fl u
-flag during a password change.
-Because the insecure database doesn't contain the password there
-is no reason to update it if the only change is in the password field.
-Cannot be used in conjunction with the
-.Fl p
-flag.
+.\" ==========
.It Fl d Ar directory
Operate in a base directory other than the default of
.Pa /etc .
for instance in a
.Xr chroot 8
jail.
+.\" ==========
+.It Fl p
+Create a Version 7 style password file and install it into
+.Pa /etc/passwd .
+.\" ==========
+.It Fl s
+Only update the secure version of the database.
+This is most commonly used in conjunction with the
+.Fl u
+flag during a password change.
+Because the insecure database doesn't contain the password there
+is no reason to update it if the only change is in the password field.
+Cannot be used in conjunction with the
+.Fl p
+flag.
+.\" ==========
.It Fl u Ar username
Only update the record for the specified user.
Utilities that operate on a single user can use this option to avoid the
This option must never be used if the line number of the user's record in
.Pa /etc/master.passwd
has changed.
+.\" ==========
.It Ar file
The absolute path to a file in
.Ar master.passwd
The databases are used by the C library password routines (see
.Xr getpwent 3 ) .
.Pp
-.Nm
+.Nm pwd_mkdb
exits zero on success, non-zero on failure.
.Sh FILES
.Bl -tag -width /etc/master.passwd -compact
not be surprised by the changes in functionality.
.Sh BUGS
Because of the necessity for atomic update of the password files,
-.Nm
+.Nm pwd_mkdb
uses
.Xr rename 2
to install them.
directory.
.Pp
There are the obvious races with multiple people running
-.Nm
+.Nm pwd_mkdb
on different password files at the same time.
The front-ends to
.Nm pwd_mkdb ,
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static const char copyright[] =
+__unused static const char copyright[] =
"@(#) Copyright (c) 1991, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#if 0
static const char sccsid[] = "from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
#else
-static const char rcsid[] = "$OpenBSD: pwd_mkdb.c,v 1.36 2003/06/08 21:14:55 millert Exp $";
+__unused static const char rcsid[] = "$OpenBSD: pwd_mkdb.c,v 1.36 2003/06/08 21:14:55 millert Exp $";
#endif
#endif /* not lint */
#include <unistd.h>
#include <util.h>
#include <sys/param.h>
+#include "pw_scan.h"
#define INSECURE 1
#define SECURE 2
.Dt REBOOT 8
.Os
.Sh NAME
-.Nm reboot ,
-.Nm halt
+.Nm halt ,
+.Nm reboot
.Nd stopping and restarting the system
.Sh SYNOPSIS
.Nm halt
.Op Fl lnqu
-.Nm
+.Nm reboot
.Op Fl lnq
.Sh DESCRIPTION
The
.Nm halt
and
-.Nm
-utilities flush the file system cache to disk, send all running processes
-a
+.Nm reboot
+utilities flush the file system cache to disk,
+send all running processes a
.Dv SIGTERM
(and subsequently a
.Dv SIGKILL )
.It Fl l
The halt or reboot is
.Em not
-logged to the system log.
+recorded in the system log.
This option is intended for applications such as
.Xr shutdown 8 ,
that call
-.Nm
+.Nm reboot
or
.Nm halt
and log this themselves.
utility is used when the system needs to be halted or restarted, giving
users advance warning of their impending doom and cleanly terminating
specific programs.
+.Sh SIGTERM TO SIGKILL INTERVAL
+The
+.Dv SIGKILL
+will follow the
+.Dv SIGTERM
+by an intentionally indeterminate period of time.
+Programs are expected to take only enough time to flush all dirty data and exit.
+Developers are encouraged to file a bug with the OS vendor, should they encounter an issue with this functionality.
.Sh SEE ALSO
.Xr wtmp 5 ,
.Xr shutdown 8 ,
.Xr sync 8
.Sh HISTORY
A
-.Nm
+.Nm reboot
utility appeared in
.At v6 .
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
+ * Portions copyright (c) 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
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with 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
+ * 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.
*
#include <mach/mach_port.h> // allocate
#include <mach/mach.h> // task_self, etc
#include <servers/bootstrap.h> // bootstrap
+#include <reboot2.h>
#endif
void usage(void);
main(int argc, char *argv[])
{
struct passwd *pw;
- int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag, uflag, sverrno;
- u_int pageins;
- char *kernel, *p;
+ int ch, howto, kflag, lflag, nflag, qflag, uflag;
+ char *p;
const char *user;
+#ifndef __APPLE__
+ int i, fd, pflag, sverrno;
+ u_int pageins;
+ char *kernel;
+#endif
if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
dohalt = 1;
if (!nflag)
sync();
+#ifndef __APPLE__
/* Just stop init -- if we fail, we'll restart it. */
if (kill(1, SIGTSTP) == -1)
err(1, "SIGTSTP init");
+#endif
/* Ignore the SIGHUP we get when our parent shell dies. */
(void)signal(SIGHUP, SIG_IGN);
}
#endif
+#ifdef __APPLE__
+ // launchd(8) handles reboot. This call returns NULL on success.
+ exit(reboot2(howto) == NULL ? EXIT_SUCCESS : EXIT_FAILURE);
+#else /* __APPLE__ */
reboot(howto);
/* FALLTHROUGH */
-#ifndef __APPLE__
restart:
-#endif
sverrno = errno;
errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
strerror(sverrno));
/* NOTREACHED */
+#endif /* __APPLE__ */
}
void
}
#ifdef __APPLE__
-// XX another copy of this routine is in shutdown.c; it would be nice to share
+// XX this routine is also in shutdown.tproj; it would be nice to share
-#define LCK_MAXTRIES 10
-#define LCK_DELAY 30
+#define WAITFORLOCK 1
/*
* contact kextd to lock for reboot
*/
int
reserve_reboot()
{
- int rval = ELAST+1;
+ int rval = ELAST + 1;
kern_return_t macherr = KERN_FAILURE;
- mach_port_t tport, bsport, kxport, myport = MACH_PORT_NULL;
- int busyStatus, nretries = LCK_MAXTRIES;
- dev_path_t busyDev = "<unknown>";
+ mach_port_t kxport, tport = MACH_PORT_NULL, myport = MACH_PORT_NULL;
+ int busyStatus = ELAST + 1;
+ mountpoint_t busyVol;
- // find kextd
- tport = mach_task_self();
- if (tport == MACH_PORT_NULL) goto finish;
- macherr = task_get_bootstrap_port(tport, &bsport);
- if (macherr) goto finish;
- macherr = bootstrap_look_up(bsport, KEXTD_SERVER_NAME, &kxport);
+ macherr = bootstrap_look_up(bootstrap_port, KEXTD_SERVER_NAME, &kxport);
if (macherr) goto finish;
// allocate a port to pass to kextd (in case we die)
+ tport = mach_task_self();
+ if (tport == MACH_PORT_NULL) goto finish;
macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
if (macherr) goto finish;
- // loop trying to lock for reboot (i.e. no volumes are busy)
- do {
- nretries--;
- macherr = kextmanager_lock_reboot(kxport, myport, busyDev, &busyStatus);
- if (macherr) goto finish;
-
- if (busyStatus == EBUSY) {
- if (*busyDev) {
- warnx("%s is busy updating; delaying reboot (%d retries left)",
- busyDev, nretries);
- } else
- warnx("kextd still starting up");
- if (nretries) sleep(LCK_DELAY); // don't sleep the last time
- }
- } while (busyStatus == EBUSY && nretries > 0);
+ // try to lock for reboot
+ macherr = kextmanager_lock_reboot(kxport, myport, !WAITFORLOCK, busyVol,
+ &busyStatus);
+ if (macherr) goto finish;
- rval = busyStatus;
+ if (busyStatus == EBUSY) {
+ warnx("%s is busy updating; waiting for lock", busyVol);
+ macherr = kextmanager_lock_reboot(kxport, myport, WAITFORLOCK,
+ busyVol, &busyStatus);
+ if (macherr) goto finish;
+ }
-finish:
- if (macherr == BOOTSTRAP_UNKNOWN_SERVICE) {
- mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
+ if (busyStatus == EALREADY) {
+ // reboot already in progress
rval = 0;
- } else if (macherr) {
- warnx("couldn't lock kext manager for reboot: %s",
- mach_error_string(macherr));
- rval = ELAST + 1;
+ } else {
+ rval = busyStatus;
}
- if (rval && myport != MACH_PORT_NULL) {
+
+finish:
+ // in general, we want to err on the side of allowing the reboot
+ if (macherr) {
+ if (macherr != BOOTSTRAP_UNKNOWN_SERVICE)
+ warnx("WARNING: couldn't lock kext manager for reboot: %s",
+ mach_error_string(macherr));
+ rval = 0;
+ }
+ // unless we got the lock, clean up our port
+ if (busyStatus != 0 && myport != MACH_PORT_NULL)
mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
- }
return rval;
}
.Nm sa
.Nd print system accounting statistics
.Sh SYNOPSIS
-.Nm
+.Nm sa
.Op Fl abcdDfijkKlmnqrstu
.Op Fl v Ar cutoff
.Op Ar
.Sh DESCRIPTION
The
-.Nm
+.Nm sa
utility reports on, cleans up,
and generally maintains system
accounting files.
.Pp
The
-.Nm
+.Nm sa
utility is able to condense the information in
.Pa /var/account/acct
into the summary files
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
+.Nm sa
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
+.Nm sa
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
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
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 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
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
The VM system does not record the CPU storage integral.
.Sh CAVEATS
While the behavior of the options in this version of
-.Nm
+.Nm sa
was modeled after the original version, there are some intentional
differences and undoubtedly some unintentional ones as well. In
particular, the
option now understands more options than it used to.
.Pp
The formats of the summary files created by this version of
-.Nm
+.Nm sa
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).
.Op Ar t n \" [t n]
.Sh DESCRIPTION \" Section Header - required - don't modify
The
-.Nm
+.Nm sa1
command is a shell script used to invoke the system
activity data collector,
.Nm sadc .
.Ar dd
represents the current day of the month.
.Pp \" Inserts a space
-.Nm
+.Nm sa1
is intended to be started by cron.
.Sh EXAMPLE CRON ENTRY
.Bd -literal
.El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
-.Xr sa2 8 ,
-.Xr sadc 8 ,
-.Xr sar 1 ,
-.Xr iostat 8 ,
-.Xr vm_stat 1 ,
+.Xr crontab 1 ,
+.Xr fs_usage 1 ,
.Xr netstat 1 ,
-.Xr top 1 ,
+.Xr sar 1 ,
.Xr sc_usage 1 ,
-.Xr fs_usage 1 ,
-.Xr crontab 1 ,
-.Xr crontab 5
+.Xr top 1 ,
+.Xr vm_stat 1 ,
+.Xr crontab 5 ,
+.Xr iostat 8 ,
+.Xr sa2 8 ,
+.Xr sadc 8
.Op Fl s Ar time \" [-s time]
.Sh DESCRIPTION \" Section Header - required - don't modify
The
-.Nm
+.Nm sa2
command is a shell script used to invoke the system
activity reporter
.Nm sar
.Ar dd
represents the current day of the month.
The
-.Nm
+.Nm sa2
options are the same as those documented in
.Nm sar(1) .
.Pp \" Inserts a space
When
-.Nm
+.Nm sa2
runs, it will also remove data and report files,
found in /var/log/sa, that are more than one week old.
.Pp
The
-.Nm
+.Nm sa2
command is intended to be started by cron.
.Pp
.Sh EXAMPLE CRON ENTRY
.El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
-.Xr sa1 8 ,
-.Xr sadc 8 ,
-.Xr sar 1 ,
-.Xr iostat 8 ,
-.Xr vm_stat 1 ,
+.Xr crontab 1 ,
+.Xr fs_usage 1 ,
.Xr netstat 1 ,
-.Xr top 1 ,
+.Xr sar 1 ,
.Xr sc_usage 1 ,
-.Xr fs_usage 1 ,
-.Xr crontab 1 ,
-.Xr crontab 5
+.Xr top 1 ,
+.Xr vm_stat 1 ,
+.Xr crontab 5 ,
+.Xr iostat 8 ,
+.Xr sa1 8 ,
+.Xr sadc 8
.Op Ar ofile \" [ofile]
.Sh DESCRIPTION \" Section Header - required - don't modify
The
-.Nm
+.Nm sadc
tool is used to collect cumulative system activity data.
The sample system data is collected at intervals
.Ar t
.Ar ofile
file does not exist, it is created, otherwise it is truncated.
.Pp \" Inserts a space
-.Nm
+.Nm sadc
is intended to be used as the engine behind the
.Nm sar(1)
command, and is not typically invoked on the command line.
Two shell scripts,
.Nm sa1
and
-.Nm sa2
+.Nm sa2 ,
are provided to drive the typical sampling, saving, and
reporting process.
.Pp
.El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
-.Xr sa1 8 ,
-.Xr sa2 8 ,
-.Xr sar 1 ,
-.Xr iostat 8 ,
-.Xr vm_stat 1 ,
+.Xr fs_usage 1 ,
.Xr netstat 1 ,
-.Xr top 1 ,
+.Xr sar 1 ,
.Xr sc_usage 1 ,
-.Xr fs_usage 1
-.\" .Sh BUGS \" Document known, unremedied bugs
+.Xr top 1 ,
+.Xr vm_stat 1 ,
+.Xr iostat 8 ,
+.Xr sa1 8 ,
+.Xr sa2 8
#include <err.h>
#include <fcntl.h>
#include <errno.h>
-#include <kvm.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <sys/param.h>
.Os "Mac OS X"
.Sh NAME \" Section Header - required - don't modify
.Nm sar
-.\" The following lines are read in generating the apropos(man -k) database. Use only key
-.\" words here as the database is built based on the words here and in the .ND line.
-.\" Use .Nm macro to designate other names for the documented program.
.Nd system activity reporter
.Sh SYNOPSIS \" Section Header - required - don't modify
-.Nm
+.Nm sar
.Op Fl dgpu \" [-dgpu]
.Op Fl n Ar mode \" [-n mode]
.Op Fl o Ar filename \" [-o filename]
t \" t
.Op Ar n \" [ n ]
-.Nm
+.Nm sar
.Op Fl dgpu \" [-dgpu]
.Op Fl n Ar mode \" [-n mode]
.Op Fl e Ar time \" [-e time]
.Op Fl s Ar time \" [-s time]
.Sh DESCRIPTION \" Section Header - required - don't modify
The
-.Nm
+.Nm sar
command is used to sample and report various cumulative statistic counters
-maintained by the operating system. It can be invoked in two different ways.
+maintained by the operating system.
+It can be invoked in two different ways.
.Pp
In the first usage instance,
.Ar n
.Ar n
is not specified, only one sample will be captured.
When the -o option is specified,
-.Nm
+.Nm sar
will write the binary sampling data to the output file specified by
.Ar filename .
.Pp
-In the second usage instance, there is no on-going sample interval to specify.
-This is because the sampling input comes from a previously recorded, binary activity file.
-The binary activity file can be specified using the -f
-.Ar filename
+In the second usage instance,
+there is no on-going sample interval to specify.
+This is because the sampling input comes
+from a previously recorded, binary activity file.
+The binary activity file can be specified using the
+.Fl f Ar filename
option.
-When the -f option isn't used,
-.Nm
+When the
+.Fl f
+option isn't used,
+.Nm sar
attempts to open a default binary activity file,
/var/log/sa/sadd, where
.Ar dd
represents the current day of the month.
-The starting and ending time of the report can be restricted using the -e
-and -s options. Here, the
+.Pp
+The starting and ending time of the report can be restricted using the
+.Fl e
+and
+.Fl s
+options. Here, the
.Ar time
field is specified in the form hh[:mm[:ss]].
-Finally, the -i option can be used to select the sampling interval.
+.Pp
+Finally, the
+.Fl i
+option can be used to select the sampling interval.
Only records at least
.Ar seconds
apart will be reported.
-When the -i option is not used, all of the previously recorded
-interval samples are reported.
+When the
+.Fl i
+option is not used,
+all of the previously recorded interval samples are reported.
.Pp
-Due to the nature of on-going sample collection, the data is reported in a
-verbose mode when more than one sampling option is specified.
-Column headers are printed at the beginning of the report and averages are
-printed when the
-.Nm
+Due to the nature of on-going sample collection,
+the data is reported in a verbose mode
+when more than one sampling option is specified.
+Column headers are printed at the beginning of the report;
+averages are printed when the
+.Nm sar
command terminates.
.Sh OPTIONS
The following options restrict the sample set that
-.Nm
+.Nm sar
reports.
.Pp \" Inserts a space
.Bl -tag -width -indent \" Differs from above in tag removed
.El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
-.Xr sa1 8 ,
-.Xr sa2 8 ,
-.Xr sadc 8 ,
-.Xr iostat 8 ,
-.Xr vm_stat 1 ,
+.Xr fs_usage 1 ,
.Xr netstat 1 ,
-.Xr top 1 ,
.Xr sc_usage 1 ,
-.Xr fs_usage 1
+.Xr top 1 ,
+.Xr vm_stat 1 ,
+.Xr iostat 8 ,
+.Xr sa1 8 ,
+.Xr sa2 8 ,
+.Xr sadc 8
.\" .Sh BUGS \" Document known, unremedied bugs
#if 0
int efd;
#endif
+ int fdlimit = getdtablesize();
/* This is the child */
/* Close all file descriptors except the one we need */
- for (i=0; i <= KERN_MAXFILESPERPROC; i++) {
+ for (i=0; i < fdlimit; i++) {
if ((i != fd[0]) && (i != fd[1]))
(void)close(i);
}
+= cur_cpuload.cpu_ticks[CPU_STATE_USER];
time += cur_cpuload.cpu_ticks[CPU_STATE_USER];
+
+ cur_cpuload.cpu_ticks[CPU_STATE_NICE]
+ -= prev_cpuload.cpu_ticks[CPU_STATE_NICE];
+
+ prev_cpuload.cpu_ticks[CPU_STATE_NICE]
+ += cur_cpuload.cpu_ticks[CPU_STATE_NICE];
+
+ time += cur_cpuload.cpu_ticks[CPU_STATE_NICE];
cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
-= prev_cpuload.cpu_ticks[CPU_STATE_SYSTEM];
avg_cpuload.cpu_ticks[CPU_STATE_USER] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER]
/ (time ? time : 1));
+ avg_cpuload.cpu_ticks[CPU_STATE_NICE] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE]
+ / (time ? time : 1));
+
avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (time ? time : 1));
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER]
/ (time ? time : 1)));
+ fprintf(stdout, "%4.0f ",
+ rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE]
+ / (time ? time : 1)));
+
fprintf(stdout, "%4.0f ",
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (time ? time : 1)));
(int)avg_cpuload.cpu_ticks[CPU_STATE_USER]
/ (avg_counter ? avg_counter : 1));
+ fprintf(stdout, "%4d ",
+ (int)avg_cpuload.cpu_ticks[CPU_STATE_NICE]
+ / (avg_counter ? avg_counter : 1));
+
fprintf(stdout, "%4d ",
(int)avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (avg_counter ? avg_counter : 1));
switch (type)
{
case SAR_CPU:
- fprintf (stdout, "\n%s %%usr %%sys %%idle\n", p);
+ fprintf (stdout, "\n%s %%usr %%nice %%sys %%idle\n", p);
break;
case SAR_VMSTAT:
# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
# passed to ld/libtool (defaults to nothing)
+ifeq "$(shell tconf --test TARGET_OS_EMBEDDED)" "YES"
+OPTIMIZE_BUILD_CFLAGS = -O
+endif
# Library and Framework projects only:
# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int max_sc = 0;
int bsc_base = 0;
int msc_base = 0;
+int mach_idle = 0;
int mach_sched = 0;
int mach_stkhandoff = 0;
int vfs_lookup = 0;
/* Count Mach message MSG_ codes */
for (msgcode_cnt=0;;) {
- n = fscanf(fp, "%x%s\n", &code, &name[0]);
+ n = fscanf(fp, "%x%55s\n", &code, &name[0]);
if (n != 2)
break;
if (strncmp ("MSG_", &name[0], 4) == 0)
return;
for (;;) {
- n = fscanf(fp, "%x%s\n", &code, &name[0]);
+ n = fscanf(fp, "%x%55s\n", &code, &name[0]);
if (n != 2)
break;
mach_stkhandoff = code;
continue;
}
+ if (strcmp("MACH_IDLE", &name[0]) == 0) {
+ mach_idle = code;
+ continue;
+ }
if (strcmp("VFS_LOOKUP", &name[0]) == 0) {
vfs_lookup = code;
continue;
} else if (baseid == bsc_base)
code = (debugid >> 2) & 0x1ff;
- else if (baseid == msc_base)
+ else if (baseid == msc_base)
code = 512 + ((debugid >> 2) & 0x1ff);
+ else if (type == mach_idle) {
+ if (debugid & DBG_FUNC_START) {
+ switched_out = find_thread(kd[i].arg5);
+ switched_in = 0;
+ }
+ else
+ if (debugid & DBG_FUNC_END) {
+ switched_in = find_thread(kd[i].arg5);
+ switched_out = 0;
+ }
+
+ if (in_idle) {
+ itime_usecs += ((double)now - idle_start) / divisor;
+ delta_itime_usecs += ((double)now - idle_start) / divisor;
+ in_idle = 0;
+ } else if (in_other) {
+ otime_usecs += ((double)now - other_start) / divisor;
+ delta_otime_usecs += ((double)now - other_start) / divisor;
+ in_other = 0;
+ }
+ if ( !switched_in) {
+ /*
+ * not one of the target proc's threads
+ */
+ if (now_collect_cpu_time) {
+ in_idle = 1;
+ idle_start = (double)now;
+ }
+ }
+ else {
+ if (now_collect_cpu_time) {
+ in_idle = 0;
+ in_other = 1;
+ other_start = (double)now;
+ }
+ }
+ if ( !switched_in && !switched_out)
+ continue;
+
+ }
else if (type == mach_sched || type == mach_stkhandoff) {
- switched_out = find_thread(kd[i].arg5);
+ switched_out = find_thread(kd[i].arg5);
switched_in = find_thread(kd[i].arg2);
if (in_idle) {
}
if ( !switched_in) {
/*
- * not one of the target proc's threads
- */
+ * not one of the target proc's threads
+ */
if (now_collect_cpu_time) {
- if (kd[i].arg4 == 0) {
- in_idle = 1;
- idle_start = (double)now;
- } else {
in_other = 1;
- other_start = (double)now;
+ other_start = (double)now;
}
- }
}
if ( !switched_in && !switched_out)
continue;
se = &sc_tab[code];
scalls++;
} else {
- se = &faults[kd[i].arg2];
+ se = &faults[kd[i].arg4];
total_faults++;
}
if (se->total_count == 0)
-991
+1271
0x1f000000 DYLD_initialize
0x1f010000 DYLD_CALL_image_init_routine
0x1f010004 DYLD_CALL_dependent_init_routine
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
0xff002ee0 MSG_processor_start
0xff002ee4 MSG_processor_exit
0xff002ee8 MSG_processor_info
0xff25abd4 MSG_semaphore_wait_signal
0xff25abd8 MSG_semaphore_timedwait_signal
0xffbebdcc MSG_clock_alarm_reply
-0x1300000 MACH_vmfault
+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
0x1400000 MACH_SCHED
0x1400004 MACH_STKATTACH
0x1400008 MACH_STKHANDOFF
0x1400018 MACH_MKRUNNABLE
0x140001c MACH_PROMOTE
0x1400020 MACH_DEMOTE
+0x1400024 MACH_IDLE
0x1500000 MACH_MSGID_INVALID
0x1090000 DecrTrap
0x1090004 DecrSet
+0x1090008 TimerCallIntr
+0x109000c pmsStep
+0x1090010 clock_deadline
0x10c0000 MACH_SysCall
0x10c0004 MSC_kern_invalid_#1
0x10c0008 MSC_kern_invalid_#2
0x40c00fc BSC_#63
0x40c0100 BSC_obs_getpagesize
0x40c0104 BSC_msync
+0x40e0104 BSC_msync_extended_info
0x40c0108 BSC_vfork
0x40c010c BSC_obs_vread
0x40c0110 BSC_obs_vwrite
0x40c025c BSC_getpgid
0x40c0260 BSC_setprivexec
0x40c0264 BSC_pread
-0x40e0264 BSC_pread_extended
+0x40e0264 BSC_pread_extended_info
0x40c0268 BSC_pwrite
-0x40e0268 BSC_pwrite_extended
+0x40e0268 BSC_pwrite_extended_info
0x40c026c BSC_nfssvc
0x40c0270 BSC_getdirentries
0x40c0274 BSC_statfs
0x40c030c BSC_setrlimit
0x40c0310 BSC_getdirentries
0x40c0314 BSC_mmap
+0x40e0314 BSC_mmap_extended_info
+0x40f0314 BSC_mmap_extended_info2
0x40c0318 BSC__syscall
0x40c031c BSC_lseek
0x40c0320 BSC_truncate
0x40c04d0 BSC_#308
0x40c04d4 BSC_#309
0x40c04d8 BSC_getsid
-0x40c04dc BSC_#311
+0x40c04dc BSC_settid_with_pid
0x40c04e0 BSC_#312
0x40c04e4 BSC_aio_fsync
0x40c04e8 BSC_aio_return
0x40c04f8 BSC_aio_read
0x40c04fc BSC_aio_write
0x40c0500 BSC_lio_listio
-0x40c0504 BSC_#321
-0x40c0508 BSC_#322
+0x40c0504 BSC__pthread_cond_wait
+0x40c0508 BSC_iopolicysys
0x40c050c BSC_#323
0x40c0510 BSC_mlockall
0x40c0514 BSC_munlockall
0x40c0534 BSC_pthread_canceled
0x40c0538 BSC_semwait_signal
0x40c053c BSC_utrace
-0x40c0540 BSC_#336
-0x40c0544 BSC_#337
-0x40c0548 BSC_#338
-0x40c054c BSC_#339
-0x40c0550 BSC_#340
-0x40c0554 BSC_#341
-0x40c0558 BSC_#342
-0x40c055c BSC_#343
+0x40c0540 BSC_proc_info
+0x40c0544 BSC_sendfile
+0x40c0548 BSC_stat64
+0x40c054c BSC_fstat64
+0x40c0550 BSC_lstat64
+0x40c0554 BSC_stat64_extended
+0x40c0558 BSC_lstat64_extended
+0x40c055c BSC_fstat64_extended
0x40c0560 BSC_#344
0x40c0564 BSC_#345
0x40c0568 BSC_#346
0x40c05bc BSC_#367
0x40c05c0 BSC_#368
0x40c05c4 BSC_#369
+0x40c05c8 BSC_#370
+0x40c05cc BSC_#371
+0x40c05d0 BSC_#372
+0x40c05d4 BSC_#373
+0x40c05d8 BSC_#374
+0x40c05dc BSC_#375
+0x40c05e0 BSC_#376
+0x40c05e4 BSC_#377
+0x40c05e8 BSC_#378
+0x40c05ec BSC_#379
+0x40c05f0 BSC_mac_execve
+0x40c05f4 BSC_mac_syscall
+0x40c05f8 BSC_mac_get_file
+0x40c06fc BSC_mac_set_file
+0x40c0600 BSC_mac_get_link
+0x40c0604 BSC_mac_set_link
+0x40c0608 BSC_mac_get_proc
+0x40c060c BSC_mac_set_proc
+0x40c0610 BSC_mac_get_fd
+0x40c0614 BSC_mac_set_fd
+0x40c0618 BSC_mac_get_pid
+0x40c061c BSC_mac_get_lcid
+0x40c0620 BSC_mac_get_lctx
+0x40c0624 BSC_mac_set_lctx
+0x40c0628 BSC_setlcid
+0x40c062c BSC_getlcid
+0x40c0630 BSC_read_nocancel
+0x40c0634 BSC_write_nocancel
+0x40c0638 BSC_open_nocancel
+0x40c063c BSC_close_nocancel
+0x40c0640 BSC_wait4_nocancel
+0x40c0644 BSC_recvmsg_nocancel
+0x40c0648 BSC_sendmsg_nocancel
+0x40c064c BSC_recvfrom_nocancel
+0x40c0650 BSC_accept_nocancel
+0x40c0654 BSC_msync_nocancel
+0x40c0658 BSC_fcntl_nocancel
+0x40c065c BSC_select_nocancel
+0x40c0660 BSC_fsync_nocancel
+0x40c0664 BSC_connect_nocancel
+0x40c0668 BSC_sigsuspend_nocancel
+0x40c066c BSC_readv_nocancel
+0x40c0670 BSC_writev_nocancel
+0x40c0674 BSC_sendto_nocancel
+0x40c0678 BSC_pread_nocancel
+0x40c067c BSC_pwrite_nocancel
+0x40c0680 BSC_waitid_nocancel
+0x40c0684 BSC_poll_nocancel
+0x40c0688 BSC_msgsnd_nocancel
+0x40c068c BSC_msgrcv_nocancel
+0x40c0690 BSC_sem_wait_nocancel
+0x40c0694 BSC_aio_suspend_nocancel
+0x40c0698 BSC_sigwait_nocancel
+0x40c069c BSC_semwait_signal_nocancel
0x5020018 IES_action
0x502001c IES_filter
0x5030010 TES_action
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
0x7000004 TRACE_DATA_NEWTHREAD
0x7010004 TRACE_STRING_NEWTHREAD
0x7010008 TRACE_STRING_EXEC
0x8000000 USER_TEST
+0x21800000 SMB_smbd_idle
+0x21800004 SMB_syscall_opendir
+0x21800008 SMB_syscall_readdir
+0x2180000c SMB_syscall_seekdir
+0x21800010 SMB_syscall_telldir
+0x21800014 SMB_syscall_rewinddir
+0x21800018 SMB_syscall_mkdir
+0x2180001c SMB_syscall_rmdir
+0x21800020 SMB_syscall_closedir
+0x21800024 SMB_syscall_open
+0x21800028 SMB_syscall_close
+0x2180002c SMB_syscall_read
+0x21800030 SMB_syscall_pread
+0x21800034 SMB_syscall_write
+0x21800038 SMB_syscall_pwrite
+0x2180003c SMB_syscall_lseek
+0x21800040 SMB_syscall_sendfile
+0x21800044 SMB_syscall_rename
+0x21800048 SMB_syscall_fsync
+0x2180004c SMB_syscall_stat
+0x21800050 SMB_syscall_fstat
+0x21800054 SMB_syscall_lstat
+0x21800058 SMB_syscall_unlink
+0x2180005c SMB_syscall_chmod
+0x21800060 SMB_syscall_fchmod
+0x21800064 SMB_syscall_chown
+0x21800068 SMB_syscall_fchown
+0x2180006c SMB_syscall_chdir
+0x21800070 SMB_syscall_getwd
+0x21800074 SMB_syscall_utime
+0x21800078 SMB_syscall_ftruncate
+0x2180007c SMB_syscall_fcntl_lock
+0x21800080 SMB_syscall_kernel_flock
+0x21800084 SMB_syscall_fcntl_getlock
+0x21800088 SMB_syscall_readlink
+0x2180008c SMB_syscall_symlink
+0x21800090 SMB_syscall_link
+0x21800094 SMB_syscall_mknod
+0x21800098 SMB_syscall_realpath
+0x2180009c SMB_syscall_get_quota
+0x218000a0 SMB_syscall_set_quota
+0x218000a4 SMB_smbmkdir
+0x218000a8 SMB_smbrmdir
+0x218000ac SMB_smbopen
+0x218000b0 SMB_smbcreate
+0x218000b4 SMB_smbclose
+0x218000b8 SMB_smbflush
+0x218000bc SMB_smbunlink
+0x218000c0 SMB_smbmv
+0x218000c4 SMB_smbgetatr
+0x218000c8 SMB_smbsetatr
+0x218000cc SMB_smbread
+0x218000d0 SMB_smbwrite
+0x218000d4 SMB_smblock
+0x218000d8 SMB_smbunlock
+0x218000dc SMB_smbctemp
+0x218000e0 SMB_smbmknew
+0x218000e4 SMB_smbcheckpath
+0x218000e8 SMB_smbexit
+0x218000ec SMB_smblseek
+0x218000f0 SMB_smblockread
+0x218000f4 SMB_smbwriteunlock
+0x218000f8 SMB_smbreadbraw
+0x218000fc SMB_smbreadbmpx
+0x21800100 SMB_smbreadbs
+0x21800104 SMB_smbwritebraw
+0x21800108 SMB_smbwritebmpx
+0x2180010c SMB_smbwritebs
+0x21800110 SMB_smbwritec
+0x21800114 SMB_smbsetattre
+0x21800118 SMB_smbgetattre
+0x2180011c SMB_smblockingx
+0x21800120 SMB_smbtrans
+0x21800124 SMB_smbtranss
+0x21800128 SMB_smbioctl
+0x2180012c SMB_smbioctls
+0x21800130 SMB_smbcopy
+0x21800134 SMB_smbmove
+0x21800138 SMB_smbecho
+0x2180013c SMB_smbwriteclose
+0x21800140 SMB_smbopenx
+0x21800144 SMB_smbreadx
+0x21800148 SMB_smbwritex
+0x2180014c SMB_smbtrans2
+0x21800150 SMB_smbtranss2
+0x21800154 SMB_smbfindclose
+0x21800158 SMB_smbfindnclose
+0x2180015c SMB_smbtcon
+0x21800160 SMB_smbtdis
+0x21800164 SMB_smbnegprot
+0x21800168 SMB_smbsesssetupx
+0x2180016c SMB_smbulogoffx
+0x21800170 SMB_smbtconx
+0x21800174 SMB_smbdskattr
+0x21800178 SMB_smbsearch
+0x2180017c SMB_smbffirst
+0x21800180 SMB_smbfunique
+0x21800184 SMB_smbfclose
+0x21800188 SMB_smbnttrans
+0x2180018c SMB_smbnttranss
+0x21800190 SMB_smbntcreatex
+0x21800194 SMB_smbntcancel
+0x21800198 SMB_smbntrename
+0x2180019c SMB_smbsplopen
+0x218001a0 SMB_smbsplwr
+0x218001a4 SMB_smbsplclose
+0x218001a8 SMB_smbsplretq
+0x218001ac SMB_smbsends
+0x218001b0 SMB_smbsendb
+0x218001b4 SMB_smbfwdname
+0x218001b8 SMB_smbcancelf
+0x218001bc SMB_smbgetmac
+0x218001c0 SMB_smbsendstrt
+0x218001c4 SMB_smbsendend
+0x218001c8 SMB_smbsendtxt
+0x218001cc SMB_smbinvalid
+0x218001d0 SMB_pathworks_setdir
+0x218001d4 SMB_trans2_open
+0x218001d8 SMB_trans2_findfirst
+0x218001dc SMB_trans2_findnext
+0x218001e0 SMB_trans2_qfsinfo
+0x218001e4 SMB_trans2_setfsinfo
+0x218001e8 SMB_trans2_qpathinfo
+0x218001ec SMB_trans2_setpathinfo
+0x218001f0 SMB_trans2_qfileinfo
+0x218001f4 SMB_trans2_setfileinfo
+0x218001f8 SMB_trans2_fsctl
+0x218001fc SMB_trans2_ioctl
+0x21800200 SMB_trans2_findnotifyfirst
+0x21800204 SMB_trans2_findnotifynext
+0x21800208 SMB_trans2_mkdir
+0x2180020c SMB_trans2_session_setup
+0x21800210 SMB_trans2_get_dfs_referral
+0x21800214 SMB_trans2_report_dfs_inconsistancy
+0x21800218 SMB_nt_transact_create
+0x2180021c SMB_nt_transact_ioctl
+0x21800220 SMB_nt_transact_set_security_desc
+0x21800224 SMB_nt_transact_notify_change
+0x21800228 SMB_nt_transact_rename
+0x2180022c SMB_nt_transact_query_security_desc
+0x21800230 SMB_nt_transact_get_user_quota
+0x21800234 SMB_nt_transact_set_user_quota
+0x21800238 SMB_get_nt_acl
+0x2180023c SMB_fget_nt_acl
+0x21800240 SMB_set_nt_acl
+0x21800244 SMB_fset_nt_acl
+0x21800248 SMB_chmod_acl
+0x2180024c SMB_fchmod_acl
+0x21800250 SMB_name_release
+0x21800254 SMB_name_refresh
+0x21800258 SMB_name_registration
+0x2180025c SMB_node_status
+0x21800260 SMB_name_query
+0x21800264 SMB_host_announce
+0x21800268 SMB_workgroup_announce
+0x2180026c SMB_local_master_announce
+0x21800270 SMB_master_browser_announce
+0x21800274 SMB_lm_host_announce
+0x21800278 SMB_get_backup_list
+0x2180027c SMB_reset_browser
+0x21800280 SMB_announce_request
+0x21800284 SMB_lm_announce_request
+0x21800288 SMB_domain_logon
+0x2180028c SMB_sync_browse_lists
+0x21800290 SMB_run_elections
+0x21800294 SMB_election
DEBUG_LIBS = $(LIBS)
PROF_LIBS = $(LIBS)
+FRAMEWORKS = -framework IOKit
{
APPCLASS = NSApplication;
FILESTABLE = {
- FRAMEWORKS = ();
+ FRAMEWORKS = (IOKit.framework);
H_FILES = (pathnames.h);
M_FILES = ();
OTHER_LIBS = (bsm);
.Nm shutdown
.Nd "close down the system at a given time"
.Sh SYNOPSIS
-.Nm
+.Nm shutdown
.Op Fl
.Oo
.Fl h
.Op Fl u
|
-.Fl r | Fl k
+.Fl r | Fl s | Fl k
.Oc
.Oo
.Fl o
.Op Ar warning-message ...
.Sh DESCRIPTION
The
-.Nm
+.Nm shutdown
utility provides an automated shutdown procedure for super-users
to nicely notify users when the system is shutting down,
saving them from system administrators, hackers, and gurus, who
.It Fl h
The system is halted at the specified
.Ar time .
-.It Fl r
-The system is rebooted at the specified
-.Ar time .
.It Fl k
Kick everybody off.
The
option
does not actually halt the system, but leaves the
system multi-user with logins disabled (for all but super-user).
-.It Fl o
-If
-.Fl h
-or
-.Fl r
-is specified,
-.Nm
-will execute
-.Xr halt 8
-or
-.Xr reboot 8
-instead of sending signal to
-.Xr init 8 .
.It Fl n
If the
.Fl o
or
.Xr reboot 8 .
This option should probably not be used.
+.It Fl o
+If
+.Fl h
+or
+.Fl r
+is specified,
+.Nm shutdown
+will execute
+.Xr halt 8
+or
+.Xr reboot 8
+instead of sending a signal to
+.Xr launchd 8 .
+.It Fl r
+The system is rebooted at the specified
+.Ar time .
+.It Fl s
+The system is put to sleep at the specified
+.Ar time .
.It Fl u
The system is halted up until the point of removing system power, but waits
before removing power for 5 minutes so that an external UPS
.It Ar time
.Ar Time
is the time at which
-.Nm
+.Nm shutdown
will bring the system down and
may be the word
.Ar now
.Pp
At intervals, becoming more frequent as apocalypse approaches
and starting at ten hours before shutdown, warning messages are displayed
-on the terminals of all users logged in. Five minutes before
-shutdown, or immediately if shutdown is in less than 5 minutes,
-logins are disabled by creating
-.Pa /var/run/nologin
-and copying the
-warning message there. If this file exists when a user attempts to
-log in,
-.Xr login 1
-prints its contents and exits. The file is
-removed just before
-.Nm
-exits.
+on the terminals of all users logged in.
.Pp
At shutdown time a message is written to the system log, containing the
time of shutdown, the person who initiated the shutdown and the reason.
Corresponding signal is then sent to
-.Xr init 8
+.Xr launchd 8
to respectively halt, reboot or bring the system down to single-user state
(depending on the above options).
-The time of the shutdown and the warning message
-are placed in
-.Pa /var/run/nologin
-and should be used to
-inform the users about when the system will be back up
-and why it is going down (or anything else).
.Pp
A scheduled shutdown can be canceled by killing the
-.Nm
+.Nm shutdown
process (a
.Dv SIGTERM
should suffice).
+.Sh SIGTERM TO SIGKILL INTERVAL
+Upon shutdown, all running processes are sent a SIGTERM followed by a SIGKILL.
The
-.Pa /var/run/nologin
-file that
-.Nm
-created will be removed automatically.
-.Sh FILES
-.Bl -tag -width /var/run/nologin -compact
-.It Pa /var/run/nologin
-tells login not to let anyone log in
-.El
+.Dv SIGKILL
+will follow the
+.Dv SIGTERM
+by an intentionally indeterminate period of time.
+Programs are expected to take only enough time to flush all dirty data and exit.
+Developers are encouraged to file a bug with the OS vendor, should they encounter an issue with this functionality.
.Sh SEE ALSO
.Xr kill 1 ,
.Xr login 1 ,
.Xr wall 1 ,
-.Xr nologin 5 ,
.Xr halt 8 ,
-.Xr init 8 ,
+.Xr launchd 8 ,
.Xr reboot 8
.Sh BACKWARD COMPATIBILITY
The hours and minutes in the second time format may be separated by
a colon (``:'') for backward compatibility.
.Sh HISTORY
The
-.Nm
+.Nm shutdown
utility appeared in
.Bx 4.0 .
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
+ * Portions copyright (c) 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
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with 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
+ * 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.
*
* SUCH DAMAGE.
*/
+#if 0
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1988, 1990, 1993\n\
#endif /* not lint */
#ifndef lint
-#if 0
static char sccsid[] = "@(#)shutdown.c 8.4 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD: src/sbin/shutdown/shutdown.c,v 1.23 2002/03/21 13:20:48 imp Exp $";
#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+#ifndef __APPLE__
+__FBSDID("$FreeBSD: src/sbin/shutdown/shutdown.c,v 1.28 2005/01/25 08:40:51 delphij Exp $");
+#endif
#include <sys/param.h>
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
+#include <paths.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
+#ifdef __APPLE__
#include <errno.h>
+#include <util.h>
#include <bsm/libbsm.h>
#include <bsm/audit_uevents.h>
-#ifdef __APPLE__
#include "kextmanager.h"
#include <IOKit/kext/kextmanager_types.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
#include <mach/mach_port.h> // allocate
#include <mach/mach.h> // task_self, etc
#include <servers/bootstrap.h> // bootstrap
-#endif
+#include <reboot2.h>
#include "pathnames.h"
-
-#ifdef __APPLE__
-#define __unused
-#endif
+#endif /* __APPLE__ */
#ifdef DEBUG
#undef _PATH_NOLOGIN
#undef S
static time_t offset, shuttime;
-static int dohalt, dopower, doreboot, doups, killflg, mbuflen, oflag = 1;
+#ifdef __APPLE__
+static int dohalt, doreboot, doups, killflg, mbuflen, oflag;
+#else
+static int dohalt, dopower, doreboot, killflg, mbuflen, oflag;
+#endif
static char mbuf[BUFSIZ];
static const char *nosync, *whom;
+#ifdef __APPLE__
+static int dosleep;
+#endif
void badtime(void);
#ifdef __APPLE__
void timeout(int);
void timewarn(int);
void usage(const char *);
-int audit_shutdown(int);
#ifdef __APPLE__
+int audit_shutdown(int);
int reserve_reboot(void);
#endif
+extern const char **environ;
+
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char **argv)
{
char *p, *endp;
struct passwd *pw;
#ifndef __APPLE__
while ((ch = getopt(argc, argv, "-hknopr")) != -1)
#else
- while ((ch = getopt(argc, argv, "-hknoru")) != -1)
+ while ((ch = getopt(argc, argv, "-hknorsu")) != -1)
#endif
switch (ch) {
case '-':
break;
case 'k':
killflg = 1;
- oflag = 0;
break;
case 'n':
nosync = "-n";
case 'r':
doreboot = 1;
break;
+#ifdef __APPLE__
+ case 's':
+ dosleep = 1;
+ break;
+#endif
case '?':
default:
usage((char *)NULL);
if (oflag && !(dohalt || dopower || doreboot))
usage("-o requires -h, -p or -r");
-#else
- if (killflg + doreboot + dohalt > 1)
- usage("incompatible switches -h, -k, and -r");
- if (oflag && !(dohalt || doreboot))
- usage("-o requires -h or -r");
+ if (nosync != NULL && !oflag)
+ usage("-n requires -o");
+#else /* !__APPLE__ */
+ if (killflg + doreboot + dohalt + dosleep > 1)
+ usage("incompatible switches -h, -k, -r, and -s");
+
+ if (!(dohalt || doreboot || dosleep || killflg))
+ usage("-h, -r, -s, or -k is required");
if (doups && !dohalt)
usage("-u requires -h");
-#endif
-
- if (nosync != NULL && !oflag)
- usage("-n requires -o");
+#endif /* !__APPLE__ */
getoffset(*argv++);
(void)putc('\n', stdout);
#else
(void)setpriority(PRIO_PROCESS, 0, PRIO_MIN);
+#ifdef __APPLE__
+ if (offset) {
+#else
{
+#endif
int forkpid;
forkpid = fork();
audit_shutdown(1);
err(1, "fork");
}
- if (forkpid) {
+ if (forkpid)
errx(0, "[pid %d]", forkpid);
- }
}
audit_shutdown(0);
setsid();
};
void
-timewarn(timeleft)
- int timeleft;
+timewarn(int timeleft)
{
static int first;
static char hostname[MAXHOSTNAMELEN + 1];
FILE *pf;
char wcmd[MAXPATHLEN + 4];
- extern const char **environ;
+
+ /* wall is sometimes missing, e.g. on install media */
+ if (access(_PATH_WALL, X_OK) == -1) return;
if (!first++)
(void)gethostname(hostname, sizeof(hostname));
}
void
-timeout(signo)
- int signo __unused;
+timeout(int signo __unused)
{
longjmp(alarmbuf, 1);
}
die_you_gravy_sucking_pig_dog()
#endif
{
+#ifndef __APPLE__
char *empty_environ[] = { NULL };
-
-#ifdef __APPLE__
+#else
if ((errno = reserve_reboot()))
err(1, "couldn't lock for reboot");
#endif
#ifndef __APPLE__
doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" :
#else
- doreboot ? "reboot" : dohalt ? "halt" :
+ doreboot ? "reboot" : dohalt ? "halt" : dosleep ? "sleep" :
#endif
- "shutdown", doups?"with UPS delay":"", whom, mbuf);
+ "shutdown", doups?" with UPS delay":"", whom, mbuf);
#ifndef __APPLE__
(void)sleep(2);
#endif
#ifndef __APPLE__
else if (dopower)
(void)printf("power-down");
-#endif
if (nosync != NULL)
(void)printf(" no sync");
+#else
+ else if (dosleep)
+ (void)printf("sleep");
+#endif
(void)printf("\nkill -HUP 1\n");
#else
#ifdef __APPLE__
- {
- int ws = 0;
- int fp = fork();
- if (fp == 0)
- execl(_PATH_BSHELL, _PATH_BSHELL, "/etc/rc.shutdown", NULL);
- else if (fp > 0)
- waitpid(fp, &ws, 0);
+ if (dosleep) {
+ mach_port_t mp;
+ io_connect_t fb;
+ kern_return_t kr = IOMasterPort(bootstrap_port, &mp);
+ if (kr == kIOReturnSuccess) {
+ fb = IOPMFindPowerManagement(mp);
+ if (fb != IO_OBJECT_NULL) {
+ IOReturn err = IOPMSleepSystem(fb);
+ if (err != kIOReturnSuccess) {
+ fprintf(stderr, "shutdown: sleep failed (0x%08x)\n", err);
+ kr = -1;
+ }
+ }
+ }
+ exit((kr == kIOReturnSuccess) ? 0 : 1);
+ } else {
+ int howto = 0;
+
+ logwtmp("~", "shutdown", "");
+
+ 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);
}
-#endif
+ /* NOT-REACHED */
+
+#else /* __APPLE__ */
if (!oflag) {
(void)kill(1, doreboot ? SIGINT : /* reboot */
dohalt ? SIGUSR1 : /* halt */
-#ifndef __APPLE__
dopower ? SIGUSR2 : /* power-down */
-#endif
SIGTERM); /* single-user */
} else {
if (doreboot) {
warn(_PATH_REBOOT);
}
else if (dohalt) {
- char *halt_args;
- if(doups) {
- halt_args = "-lu";
- } else {
- halt_args = "-l";
- }
- execle(_PATH_HALT, "halt", halt_args, nosync,
+ execle(_PATH_HALT, "halt", "-l", nosync,
(char *)NULL, empty_environ);
syslog(LOG_ERR, "shutdown: can't exec %s: %m.",
_PATH_HALT);
warn(_PATH_HALT);
}
-#ifndef __APPLE__
else if (dopower) {
execle(_PATH_HALT, "halt", "-l", "-p", nosync,
(char *)NULL, empty_environ);
_PATH_HALT);
warn(_PATH_HALT);
}
-#endif
(void)kill(1, SIGTERM); /* to single-user */
}
+#endif /* __APPLE__ */
#endif
finish(0);
}
#define ATOI2(p) (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
void
-getoffset(timearg)
- char *timearg;
+getoffset(char *timearg)
{
struct tm *lt;
char *p;
(void)write(logfd, mbuf, strlen(mbuf));
(void)close(logfd);
}
-#endif
+#endif /* !__APPLE__ */
}
void
-finish(signo)
- int signo __unused;
+finish(int signo __unused)
{
#ifndef __APPLE__
if (!killflg)
}
void
-usage(cp)
- const char *cp;
+usage(const char *cp)
{
if (cp != NULL)
warnx("%s", cp);
(void)fprintf(stderr,
- "usage: shutdown [-] [-h [-u] | -r | -k] [-o [-n]]"
+#ifdef __APPLE__
+ "usage: shutdown [-] [-h [-u] [-n] | -r [-n] | -s | -k]"
+#else
+ "usage: shutdown [-] [-h | -p | -r | -k] [-o [-n]]"
+#endif
" time [warning-message ...]\n");
exit(1);
}
+#ifdef __APPLE__
/*
* The following tokens are included in the audit record for shutdown
* header
}
-#ifdef __APPLE__
-// XX copied from reboot.c; would be nice to share the code
+// XX copied from reboot.tproj/reboot.c; it would be nice to share the code
-#define LCK_MAXTRIES 10
-#define LCK_DELAY 30
+#define WAITFORLOCK 1
/*
* contact kextd to lock for reboot
*/
int
reserve_reboot()
{
- int rval = ELAST+1;
- kern_return_t macherr = KERN_FAILURE;
- mach_port_t tport, bsport, kxport, myport = MACH_PORT_NULL;
- int busyStatus, nretries = LCK_MAXTRIES;
- dev_path_t busyDev = "<unknown>";
-
- // find kextd
- tport = mach_task_self();
- if (tport == MACH_PORT_NULL) goto finish;
- macherr = task_get_bootstrap_port(tport, &bsport);
- if (macherr) goto finish;
- macherr = bootstrap_look_up(bsport, KEXTD_SERVER_NAME, &kxport);
- if (macherr) goto finish;
-
- // allocate a port to pass to kextd (in case we die)
- macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
- if (macherr) goto finish;
-
- // loop trying to lock for reboot (i.e. no volumes are busy)
- do {
- nretries--;
- macherr = kextmanager_lock_reboot(kxport, myport, busyDev, &busyStatus);
- if (macherr) goto finish;
-
- if (busyStatus == EBUSY) {
- if (*busyDev) {
- warnx("%s is busy updating; delaying reboot (%d retries left)",
- busyDev, nretries);
- } else
- warnx("kextd still starting up");
- if (nretries) sleep(LCK_DELAY); // don't sleep the last time
- }
- } while (busyStatus == EBUSY && nretries > 0);
-
- rval = busyStatus;
+ int rval = ELAST + 1;
+ kern_return_t macherr = KERN_FAILURE;
+ mach_port_t kxport, tport = MACH_PORT_NULL, myport = MACH_PORT_NULL;
+ int busyStatus = ELAST + 1;
+ mountpoint_t busyVol;
+
+ macherr = bootstrap_look_up(bootstrap_port, KEXTD_SERVER_NAME, &kxport);
+ if (macherr) goto finish;
+
+ // allocate a port to pass to kextd (in case we die)
+ tport = mach_task_self();
+ if (tport == MACH_PORT_NULL) goto finish;
+ macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
+ if (macherr) goto finish;
+
+ // try to lock for reboot
+ macherr = kextmanager_lock_reboot(kxport, myport, !WAITFORLOCK, busyVol,
+ &busyStatus);
+ if (macherr) goto finish;
+
+ if (busyStatus == EBUSY) {
+ warnx("%s is busy updating; waiting for lock", busyVol);
+ macherr = kextmanager_lock_reboot(kxport, myport, WAITFORLOCK,
+ busyVol, &busyStatus);
+ if (macherr) goto finish;
+ }
+
+ if (busyStatus == EALREADY) {
+ // reboot already in progress
+ rval = 0;
+ } else {
+ rval = busyStatus;
+ }
finish:
- if (macherr == BOOTSTRAP_UNKNOWN_SERVICE) {
- mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
- rval = 0;
- } else if (macherr) {
- warnx("couldn't lock kext manager for reboot: %s",
- mach_error_string(macherr));
- rval = ELAST + 1;
- }
- if (rval && myport != MACH_PORT_NULL) {
- mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
- }
-
- return rval;
+ // in general, we want to err on the side of allowing the reboot
+ if (macherr) {
+ if (macherr != BOOTSTRAP_UNKNOWN_SERVICE)
+ warnx("WARNING: couldn't lock kext manager for reboot: %s",
+ mach_error_string(macherr));
+ rval = 0;
+ }
+ // unless we got the lock, clean up our port
+ if (busyStatus != 0 && myport != MACH_PORT_NULL)
+ mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
+
+ return rval;
}
-#endif
+#endif /* __APPLE__ */
.Xr sync 2
function call.
.Sh SEE ALSO
-.Xr sync 2 ,
.Xr fsync 2 ,
+.Xr sync 2 ,
.Xr halt 8 ,
.Xr reboot 8 ,
.Xr update 8
* SUCH DAMAGE.
*/
+#include <stdlib.h>
+#include <unistd.h>
+
+int
main()
{
sync();
CFILES = sysctl.c
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sysctl.8
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sysctl.8 sysctl.conf.5
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
after_install:
mkdir -p "$(DSTROOT)/usr/share/man/man8"
install -c -m 644 sysctl.8 "$(DSTROOT)/usr/share/man/man8/sysctl.8"
+ mkdir -p "$(DSTROOT)/usr/share/man/man5"
+ install -c -m 644 sysctl.conf.5 "$(DSTROOT)/usr/share/man/man5/sysctl.conf.5"
.Pp
The following options are available:
.Bl -tag -width indent
+.\" ==========
.It Fl A
List all MIB variables including opaque variables (which are normally suppressed).
The format and length are printed, as well as a hex dump of the first sixteen bytes of the value.
+.\" ==========
.It Fl a
List all the currently available non-opaque values.
This option is ignored if one or more variable names are specified on
the command line.
+.\" ==========
.It Fl b
Force the value of the variable(s) to be output in raw, binary format.
No names are printed and no terminating newlines are output.
This is mostly useful with a single variable.
+.\" ==========
.It Fl n
Show only variable values, not their names.
This option is useful for setting shell variables.
use:
.Pp
.Dl "set psize=`sysctl -n hw.pagesize`"
-.It Fl X
-Same as
-.Fl A
-but prints a hex dump of the entire value instead of just the first few bytes.
+.\" ==========
.It Fl w Ar name=value
Used to set values. The MIB name (
.Ar name
) followed by an equal sign and the new value (
.Ar value
) to be used.
+.\" ==========
+.It Fl X
+Same as
+.Fl A ,
+but prints a hex dump of the entire value
+instead of just the first few bytes.
.El
.Pp
If just a MIB style name is given,
.It hw.byteorder integer no
.It hw.physmem integer no
.It hw.usermem integer no
+.It hw.memsize integer no
.It hw.pagesize integer no
.It user.cs_path string no
.It user.bc_base_max integer no
.Bd -literal -offset indent
sysctl debug
.Ed
+.Pp
In addition,
.Nm sysctl
can extract information about the filesystems that have been compiled
.Bd -literal -offset indent
sysctl vfs
.Ed
+.Pp
By default, only filesystems that are actively being used are listed.
Use of the
.Fl A
.Sh EXAMPLES
.Pp
For example, to retrieve the maximum number of processes allowed
-in the system, one would use the follow request:
-.Bd -literal -offset indent -compact
+in the system, one would use the request:
+.Bd -literal -offset indent
sysctl kern.maxproc
.Ed
.Pp
To set the maximum number of processes allowed
-in the system to 1000, one would use the follow request:
-.Bd -literal -offset indent -compact
+in the system to 1000, one would use the request:
+.Bd -literal -offset inden
sysctl -w kern.maxproc=1000
.Ed
.Pp
Information about the system clock rate may be obtained with:
-.Bd -literal -offset indent -compact
+.Bd -literal -offset indent
sysctl kern.clockrate
.Ed
.Pp
Information about the load average history may be obtained with:
-.Bd -literal -offset indent -compact
+.Bd -literal -offset indent
sysctl vm.loadavg
.Ed
.Pp
Information about the system's swap space usage may be obtained with:
-.Bd -literal -offset indent -compact
+.Bd -literal -offset indent
sysctl vm.swapusage
.Ed
.Sh FILES
/*
- * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
setting values where the format is specified as unsigned integer.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
+__unused 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[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95";
+__unused static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95";
#endif /* not lint */
#include <sys/param.h>
static int Aflag, aflag, bflag, nflag, wflag, Xflag;
static int foundSome = 0;
+static int invalid_name_used = 0;
void listall(char *prefix, struct list *lp);
void old_parse(char *string, int flags);
usage();
for (; *argv != NULL; ++argv)
parse(*argv, 1);
- exit(0);
+ exit(invalid_name_used ? 1 : 0);
}
/*
useUnsignedInt = 1;
break;
- case CTL_VM:
+ case CTL_VM: break;
+#if 0 /* XXX Handled by the new sysctl mechanism */
switch (mib[1]) {
case VM_LOADAVG: { /* XXX this is bogus */
double loads[3];
fprintf(stderr,
"Use vmstat or systat to view %s information\n", string);
return;
+#endif
case CTL_DEBUG:
mib[2] = CTL_DEBUG_VALUE;
switch (type) {
case CTLTYPE_INT:
if (useUnsignedInt) {
- uintval = strtoul(newval, 0, 0);
+ uintval = strtoul(newval, NULL, 0);
+ if ((uintval == 0) && (errno == EINVAL)) {
+ fprintf(stderr, "invalid argument: %s\n",
+ (char *)newval);
+ return;
+ }
newval = &uintval;
newsize = sizeof uintval;
} else {
- intval = atoi(newval);
- newval = &intval;
- newsize = sizeof intval;
+ intval = strtol(newval, NULL, 0);
+ if ((intval == 0) && (errno == EINVAL)) {
+ fprintf(stderr, "invalid argument: %s\n",
+ (char *)newval);
+ return;
+ }
+ newval = &intval;
+ newsize = sizeof intval;
}
break;
case CTLTYPE_QUAD:
- sscanf(newval, "%qd", &quadval);
+ quadval = strtoq(newval, NULL, 0);
+ if ((quadval == 0) && (errno == EINVAL)) {
+ fprintf(stderr, "invalid argument: %s\n",
+ (char *)newval);
+ return;
+ }
newval = &quadval;
newsize = sizeof quadval;
break;
if (flags == 0)
return;
switch (errno) {
- case EOPNOTSUPP:
+ case ENOTSUP:
fprintf(stderr, "%s: value is not available\n", string);
return;
case ENOTDIR:
fprintf(stdout, "%s = %s\n", string,
ctime((time_t *) &btp->tv_sec));
else
- fprintf(stdout, "%d\n", btp->tv_sec);
+ fprintf(stdout, "%ld\n", btp->tv_sec);
return;
}
if (special & CONSDEV) {
for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
mib[3] = cnt;
if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
- if (errno == EOPNOTSUPP)
+ if (errno == ENOTSUP)
continue;
perror("vfsinit");
free(vfsname);
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;
return (-1);
}
for (i = 0; i < namelist->size; i++)
if (i == namelist->size) {
fprintf(stderr, "%s level name %s in %s is invalid\n",
level, name, string);
+ invalid_name_used = 1;
return (-1);
}
return (i);
case CTLTYPE_INT:
if ((*fmt == 'I') && (*(fmt + 1) == 'U')) {
uintval = (unsigned int) strtoul (newval, NULL, 0);
+ if ((uintval == 0) &&
+ (errno == EINVAL)) {
+ errx(1, "invalid argument: %s",
+ newval);
+ return;
+ }
newval = &uintval;
newsize = sizeof uintval;
} else {
intval = (int) strtol(newval, NULL, 0);
+ if ((intval == 0) &&
+ (errno == EINVAL)) {
+ errx(1, "invalid argument: %s",
+ newval);
+ return;
+ }
newval = &intval;
newsize = sizeof intval;
}
break;
case CTLTYPE_QUAD:
quadval = strtoq(newval, NULL, 0);
+ if ((quadval == 0) && (errno == EINVAL)) {
+ errx(1, "invalid argument %s", newval);
+ return;
+ }
newval = &quadval;
newsize = sizeof quadval;
break;
if (!i && !bflag)
putchar('\n');
switch (errno) {
- case EOPNOTSUPP:
+ case ENOTSUP:
errx(1, "%s: value is not available",
string);
case ENOTDIR:
return (0);
}
+static int
+S_xswusage(int l2, void *p)
+{
+ struct xsw_usage *xsu = (struct xsw_usage *)p;
+
+ if(l2 != sizeof (*xsu))
+ err(1, "S_xswusage %d != %d", l2, sizeof *xsu);
+
+ fprintf(stdout,
+ "total = %.2fM used = %.2fM free = %.2fM %s",
+ ((double) xsu->xsu_total) / (1024.0 * 1024.0),
+ ((double) xsu->xsu_used) / (1024.0 * 1024.0),
+ ((double) xsu->xsu_avail) / (1024.0 * 1024.0),
+ xsu->xsu_encrypted ? "(encrypted)" : "");
+ return 0;
+}
+
static int
T_dev_t(int l2, void *p)
{
if (!nflag)
printf("%s: ", name);
fmt++;
- val = "";
+ val = (unsigned char *)"";
while (len >= sizeof(int)) {
if(*fmt == 'U')
printf("%s%u", val, *(unsigned int *)p);
else
printf("%s%d", val, *(int *)p);
- val = " ";
+ val = (unsigned char *)" ";
len -= sizeof (int);
p += sizeof (int);
}
if (!nflag)
printf("%s: ", name);
fmt++;
- val = "";
+ val = (unsigned char *)"";
while (len >= sizeof(long)) {
if(*fmt == 'U')
printf("%s%lu", val, *(unsigned long *)p);
else
printf("%s%ld", val, *(long *)p);
- val = " ";
+ val = (unsigned char *)" ";
len -= sizeof (long);
p += sizeof (long);
}
if (!nflag)
printf("%s: ", name);
fmt++;
- val = "";
+ val = (unsigned char *)"";
while (len >= sizeof(long long)) {
if(*fmt == 'U')
printf("%s%llu", val, *(unsigned long long *)p);
else
printf("%s%lld", val, *(long long *)p);
- val = " ";
+ val = (unsigned char *)" ";
len -= sizeof (long long);
p += sizeof (long long);
}
if (!strcmp(fmt, "S,clockinfo")) func = S_clockinfo;
else if (!strcmp(fmt, "S,timeval")) func = S_timeval;
else if (!strcmp(fmt, "S,loadavg")) func = S_loadavg;
+ else if (!strcmp(fmt, "S,xsw_usage")) func = S_xswusage;
else if (!strcmp(fmt, "T,dev_t")) func = T_dev_t;
if (func) {
if (!nflag)
--- /dev/null
+.\" Modified August 3, 2007
+.\" Portions Copyright (c) 2007 Apple Inc.
+.\" Copyright (c) 1999 Chris Costello <chris@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/share/man/man5/sysctl.conf.5,v 1.16 2004/07/03 18:29:23 ru Exp $
+.\"
+.Dd August 3, 2007
+.Dt SYSCTL.CONF 5
+.Os
+.Sh NAME
+.Nm sysctl.conf
+.Nd kernel state defaults
+.Sh DESCRIPTION
+The
+.Pa /etc/sysctl.conf
+file is read in when the system goes into multi-user mode to set default
+settings for the kernel.
+The
+.Pa /etc/sysctl.conf
+is in the format of the
+.Xr sysctl 8
+command, i.e.\&
+.Bd -literal -offset indent
+sysctl_mib=value
+.Ed
+.Pp
+Comments are denoted by a
+.Dq #
+at the beginning of a line.
+.Sh FILES
+.Bl -tag -width /etc/sysctl.conf -compact
+.It Pa /etc/sysctl.conf
+Initial settings for
+.Xr sysctl 8 .
+.El
+.Sh EXAMPLES
+To disable coredumps, you may use a configuration like:
+.Bd -literal -offset indent
+# Disable coredumps.
+kern.coredump=0
+.Ed
+.Sh SEE ALSO
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+file appeared in
+.Fx 4.0 .
+.Sh BUGS
+If loadable kernel modules are used to introduce additional kernel
+functionality and sysctls to manage that functionality,
+.Nm
+may be processed too early in the boot process to set those sysctls.
PROJECTVERSION = 2.8
PROJECT_TYPE = Tool
-CFILES = update.c disk_power.c power_mgmt.c
-HFILES = disk_power.h power_mgmt.h
+CFILES = update.c
+HFILES =
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble update.8
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble update.8 \
+ com.apple.update.plist update.sb
-FRAMEWORKS = -framework CoreFoundation -framework IOKit
+FRAMEWORKS =
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
CODE_GEN_STYLE = DYNAMIC
# target runs. Such rules should be specified with the '::' syntax rather than
# a single colon.
-after_install:
+install-man-page:
mkdir -p "$(DSTROOT)/usr/share/man/man8"
install -c -m 644 update.8 "$(DSTROOT)/usr/share/man/man8/update.8"
+
+LAUNCHD_PLIST_DIR = $(DSTROOT)/System/Library/LaunchDaemons
+LAUNCHD_PLIST = com.apple.update.plist
+SANDBOX = "$(DSTROOT)/usr/share/sandbox"
+
+install-launchd-plist:
+ install -d $(LAUNCHD_PLIST_DIR)
+ install -c -m 644 $(LAUNCHD_PLIST) $(LAUNCHD_PLIST_DIR)/$(LAUNCHD_PLIST)
+
+install-sb:
+ install -d $(SANDBOX)
+ install -c -m 644 update.sb $(SANDBOX)
# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
OTHER_GENERATED_OFILES = $(VERS_OFILE)
-AFTER_INSTALL = after_install
+AFTER_INSTALL = install-man-page install-launchd-plist install-sb
{
DOCICONFILES = ();
FILESTABLE = {
- C_FILES = (update.c disk_power.c power_mgmt.c);
- H_FILES = (disk_power.h power_mgmt.h);
+ C_FILES = (update.c);
+ H_FILES = ();
OTHER_LIBS = ();
OTHER_LINKED = ();
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, update.8);
+ OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, update.8, com.apple.update.plist);
PRECOMPILED_HEADERS = ();
PROJECT_HEADERS = ();
PUBLIC_HEADERS = ();
SUBPROJECTS = ();
- FRAMEWORKS = (CoreFoundation.framework, IOKit.framework);
+ FRAMEWORKS = ();
};
GENERATEMAIN = YES;
LANGUAGE = English;
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.update</string>
+ <key>OnDemand</key>
+ <false/>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/sbin/update</string>
+ </array>
+</dict>
+</plist>
+++ /dev/null
-#include <IOKit/IOKitLib.h>
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <IOKit/pwr_mgt/IOPM.h>
-
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include "disk_power.h"
-
-int PowerStateSummary( IOATAPowerState powerState );
-
-/*
--- PowerStateString()
-*/
-
-char * PowerStateString( IOATAPowerState x, int opt_summary )
-{
- char * result;
-
- if ( opt_summary )
- {
- switch ( PowerStateSummary( x ) )
- {
- case -1:
- result = "ON";
- break;
- case 0: // This is the only value where the two scales collide.
- result = "OFF";
- break;
- default:
- fprintf(stderr, "ERROR: %s: unknown IOATAPowerState %d\n", __FUNCTION__, (int)x);
- result = "UNKNOWN";
- break;
- }
- }
- else
- {
- switch ( x )
- {
- case kIOATAPowerStateSystemSleep: // This is the only value where the two scales collide.
- result = "SystemSleep";
- break;
- case kIOATAPowerStateSleep:
- result = "Sleep";
- break;
- case kIOATAPowerStateStandby:
- result = "Standby";
- break;
- case kIOATAPowerStateIdle:
- result = "Idle";
- break;
- case kIOATAPowerStateActive:
- result = "Active";
- break;
- default:
- fprintf(stderr, "ERROR: %s: unknown IOATAPowerState %d\n", __FUNCTION__, (int)x);
- result = "UNKNOWN";
- break;
- }
- }
-
- return result;
-
-} // PowerStateString()
-
-/*
--- PowerStatesMax()
-*/
-
-IOATAPowerState PowerStatesMax( IOATAPowerStates * powerStates )
-{
- IOATAPowerState driverDesire = powerStates->driverDesire;
- IOATAPowerState deviceDesire = powerStates->deviceDesire;
- IOATAPowerState userDesire = powerStates->userDesire;
-
- IOATAPowerState maxState = 0;
-
- if ( driverDesire > maxState ) maxState = driverDesire;
-
- if ( deviceDesire > maxState ) maxState = deviceDesire;
-
- if ( userDesire > maxState ) maxState = userDesire;
-
- return maxState;
-
-} // PowerStatesMax()
-
-/*
--- PowerStateSummary()
-*/
-
-/* Returns
--- -1 == ON
--- 0 == OFF
--- Can be used together with the positive values denoting IOATAPowerState's.
--- But you have to be careful not to confuse with OFF == 0 == kIOATAPowerStateSystemSleep.
-*/
-
-int PowerStateSummary( IOATAPowerState powerState )
-{
- int result;
-
- // Summarizing twice does nothing. Idempotent.
- if ( powerState <= 0 )
- result = powerState;
- else
-#if 1
- if ( 0 <= powerState && powerState <= kIOATAPowerStateSleep )
- result = 0;
- else
- result = -1;
-#else
- if ( 0 <= powerState && powerState <= kIOATAPowerStateStandby ) // Spun down.
- result = 0; // OFF
- else
- if ( kIOATAPowerStateIdle <= powerState && powerState <= kIOATAPowerStateActive ) // Spun up.
- result = -1; // ON
- else
- {
- fprintf(stderr, "ERROR: %s(%d): unexpected value.\n", __FUNCTION__, powerState);
- exit(-1);
- }
-#endif
-
- return result;
-
-} // PowerStateSummary()
-
-/*
--- GetATADeviceInfo()
-*/
-
-// Fairly often this returns -11, meaning that it was unable to locate a matching device.
-// If this happens, just wait awhile and try again.
-//
-// See GetATADeviceInfoWithRetry()
-//
-
-int GetATADeviceInfo( DiskDevice * device )
-{
- int result;
-
- IOATAPowerStates * powerStates = & device->powerStates;
-
- kern_return_t kr;
- mach_port_t masterPort;
- io_registry_entry_t service;
- io_iterator_t iterator;
-
- kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
- assert(KERN_SUCCESS==kr);
-
- /* look for drives */
- IOServiceGetMatchingServices(masterPort, IOServiceMatching ( "ATADeviceNub" ), & iterator );
- if ( ! iterator )
- {
- result = -10;
- goto Return;
- }
-
- while (( service = IOIteratorNext( iterator ) ))
- {
- CFStringRef str = nil;
- CFMutableDictionaryRef properties = nil;
- CFDictionaryRef physCharacteristics = nil;
- io_iterator_t child_iterator;
- io_registry_entry_t child;
-
- // Device Model
-
- char deviceModel[ 256 ];
- bzero( deviceModel, sizeof deviceModel );
-
- str = IORegistryEntryCreateCFProperty( service, CFSTR("device model"), kCFAllocatorDefault, kNilOptions );
- if ( str )
- {
- CFStringGetCString( str, deviceModel, sizeof deviceModel, kCFStringEncodingMacRoman );
- CFRelease( str );
- }
-
- // Device Interconnect & Device Location
-
- char deviceInterconnect[ 256 ];
- bzero(deviceInterconnect, sizeof deviceInterconnect );
- char deviceLocation[ 256 ];
- bzero(deviceLocation, sizeof deviceLocation );
-
- IORegistryEntryCreateCFProperties( service, & properties, kCFAllocatorDefault, kNilOptions );
- if ( properties )
- {
- physCharacteristics = CFDictionaryGetValue( properties, CFSTR("Protocol Characteristics") );
- if ( physCharacteristics )
- {
- // device interconnect
- str = CFDictionaryGetValue( physCharacteristics, CFSTR("Physical Interconnect") );
- if ( str )
- {
- CFStringGetCString( str, deviceInterconnect, sizeof deviceInterconnect, kCFStringEncodingMacRoman );
- }
-
- // device location
- str = CFDictionaryGetValue( physCharacteristics, CFSTR("Physical Interconnect Location") );
- if ( str )
- {
- CFStringGetCString( str, deviceLocation, sizeof deviceLocation, kCFStringEncodingMacRoman );
- }
- }
-
- CFRelease( properties );
- }
-
- IORegistryEntryGetChildIterator( service, kIOServicePlane, & child_iterator );
- while (( child = IOIteratorNext( child_iterator ) ))
- {
- int driverDesire, deviceDesire, userDesire;
-
- // fill in interconnect info if we don't already have it
- if ( 0 == strlen(deviceInterconnect) )
- {
- str = IORegistryEntryCreateCFProperty( child, CFSTR("Physical Interconnect"), kCFAllocatorDefault, kNilOptions );
- if ( str )
- {
- CFStringGetCString( str, deviceInterconnect, sizeof deviceInterconnect, kCFStringEncodingMacRoman );
- CFRelease( str );
- }
- }
-
- if ( 0 == strlen( deviceLocation ) )
- {
- str = IORegistryEntryCreateCFProperty( child, CFSTR("Physical Interconnect Location"), kCFAllocatorDefault, kNilOptions );
- if ( str )
- {
- CFStringGetCString( str, deviceLocation, sizeof deviceLocation , kCFStringEncodingMacRoman );
- CFRelease( str );
- }
- }
-
- // Device Type
-
- char deviceType[ 256 ];
- bzero( deviceType, sizeof deviceType );
-
- // Power State
-
- char powerState[ 256 ];
- bzero( powerState, sizeof powerState );
-
- // find out what type of device this is - ATAPI will be added as SCSI devices
- str = IORegistryEntryCreateCFProperty( service, CFSTR("ata device type"), kCFAllocatorDefault, kNilOptions );
- if ( str )
- {
- CFStringGetCString( str, deviceType, sizeof deviceType, kCFStringEncodingMacRoman );
- CFRelease( str );
-
- if ( 0 == strcmp( deviceType, "ata" ) ) // regular ATA disks (not ATAPI)
- {
- IORegistryEntryCreateCFProperties( child, & properties, kCFAllocatorDefault, kNilOptions );
- if ( properties )
- {
- str = CFDictionaryGetValue( properties, CFSTR("Power Management private data") );
- if ( str )
- {
- CFStringGetCString( str, powerState, sizeof powerState, kCFStringEncodingMacRoman );
- }
- CFRelease( properties );
- }
- }
- }
-
- if ( 3 == sscanf ( powerState,
- "{ this object = %*x, interested driver = %*x, driverDesire = %d, deviceDesire = %d, ourDesiredPowerState = %d, previousRequest = %*d }",
- & driverDesire, & deviceDesire, & userDesire
- )
- )
- {
- device->timestamp = time( NULL );
-
- device->name = strdup( deviceModel ); // copy of the original
- device->location = strdup( deviceLocation ); // copy of the original
- device->interconnect = strdup( deviceInterconnect ); // copy of the original
-
- powerStates->driverDesire = driverDesire;
- powerStates->deviceDesire = deviceDesire;
- powerStates->userDesire = userDesire;
-
- IOObjectRelease( child_iterator );
- IOObjectRelease( iterator );
-
- result = 0;
- goto Return;
- }
-
- } // while (child...)
-
- IOObjectRelease( child_iterator );
-
- } // while (service...)
-
- IOObjectRelease( iterator );
-
- result = -11;
- goto Return;
-
-Return:
- return result;
-
-} // GetATADeviceInfo()
-
-
-/*
--- GetATADeviceInfoWithRetry()
-*/
-
-// Devices are often momentarily busy, e.g., when spinning up. Retry up to 10 times, 1 second apart.
-
-int GetATADeviceInfoWithRetry( DiskDevice * diskDevice )
-{
- int err;
-
- int retryNumber;
-
- for ( retryNumber = 0; retryNumber < 10; retryNumber++ )
- {
- err = GetATADeviceInfo( diskDevice );
- if ( noErr == err )
- {
- goto Return;
- }
-#if 0
- char errorStringBuffer[ 256 ];
- char * errorString = errorStringBuffer;
- errorString += sprintf_timestamp_now( errorString );
- errorString += sprintf(errorString, ": WARNING: %s: sleeping and retrying...\n", __FUNCTION__);
- fputs( errorStringBuffer, stderr );
- fflush(stdout);
-#endif
- sleep(1);
- }
-
- // Failure.
- goto Return;
-
-Return:
- return err;
-
-} // GetATADeviceInfoWithRetry()
-
+++ /dev/null
-#ifndef __SPINDOWN_H__
-
-#define __SPINDOWN_H__
-
-#include <libkern/OSTypes.h>
-#include <IOKit/storage/ata/IOATAStorageDefines.h>
-#include <stdio.h>
-#include <time.h>
-
-/* IOATAPowerStates */
-
-struct IOATAPowerStates
-{
- IOATAPowerState driverDesire;
- IOATAPowerState deviceDesire;
- IOATAPowerState userDesire;
-};
-
-typedef struct IOATAPowerStates IOATAPowerStates;
-
-/* DiskDevice: see GetATADeviceInfo(), GetATADeviceInfoWithRetry() */
-
-struct DiskDevice
-{
- time_t timestamp;
- char * name;
- char * location;
- char * interconnect;
- IOATAPowerStates powerStates;
-};
-
-typedef struct DiskDevice DiskDevice;
-
-/* Devices */
-
-
-/* PowerStatesMax()
--- Returns the max-of-three power state "desires" from the given IOATAPowerStates.
-*/
-IOATAPowerState PowerStatesMax( IOATAPowerStates * powerStates );
-
-/* PowerStateString()
--- Returns human-readable string name for the given IOATAPowerState.
--- Returns pointer to a static, const string.
-*/
-char * PowerStateString( IOATAPowerState x, int opt_summary );
-
-/* Routines for printing fs_usage-compatible timestamps: HH:MM:SS.000
-*/
-int sprintf_timestamp( char * str, time_t t );
-int sprintf_timestamp_now( char * str );
-char * timestampStr_static( time_t t ); /* Returns pointer to a static, const string. */
-
-#if 0
-/* Routines for printing time intervals: HH:MM:SS
-*/
-int sprintf_interval( char * str, time_t interval );
-char * intervalStr_static( time_t interval ); /* Returns pointer to a static, const string. */
-#endif
-
-/* GetATADeviceInfoWithRetry()
--- This invokes GetATADeviceInfo() repeatedly at one second intervals until it returns without error.
--- Gives up after 10 tries, so it is possible that this could return an error.
-*/
-int GetATADeviceInfoWithRetry( DiskDevice * diskDevice );
-
-/*
---
-*/
-
-#endif /* __SPINDOWN_H__ */
+++ /dev/null
-
-#include "disk_power.h"
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <IOKit/pwr_mgt/IOPM.h>
-
-#include <CoreFoundation/CFNumber.h>
-
-/*
---
-*/
-
-int on_battery_power( void )
-{
- int result = 0; // Assume we're not running on battery power.
- kern_return_t kr;
- mach_port_t master_device_port;
-
- CFArrayRef cfarray = NULL;
-
- kr = IOMasterPort( bootstrap_port, & master_device_port);
- if ( KERN_SUCCESS != kr)
- {
- fprintf(stderr,"ERROR: IOMasterPort() failed\n");
- goto Return;
- }
-
- kr = IOPMCopyBatteryInfo( master_device_port, & cfarray );
- if ( kIOReturnSuccess != kr )
- {
- // This case handles desktop machines in addition to error cases.
- result = 0;
- goto Return;
- }
-
- {
- CFDictionaryRef dict;
- CFNumberRef cfnum;
- int flags;
-
- dict = CFArrayGetValueAtIndex( cfarray, 0 );
- cfnum = CFDictionaryGetValue( dict, CFSTR(kIOBatteryFlagsKey) );
-
- if ( CFNumberGetTypeID() != CFGetTypeID( cfnum ) )
- {
- fprintf(stderr, "ERROR: on_battery_power(): battery flags not a CFNumber!!!\n");
- result = 0;
- goto Return;
- }
-
- CFNumberGetValue( cfnum, kCFNumberLongType, & flags );
-
-#if 0
- printf( "BatteryFlags = %#08x\n", flags );
-
- printf( "BatteryChargerConnect : %s\n", ( 0 != ( flags & kIOBatteryChargerConnect ) ) ? "TRUE" : "FALSE" );
- printf( "BatteryCharge : %s\n", ( 0 != ( flags & kIOBatteryCharge ) ) ? "TRUE" : "FALSE" );
- printf( "BatteryInstalled : %s\n", ( 0 != ( flags & kIOBatteryInstalled ) ) ? "TRUE" : "FALSE" );
-#endif
-
- result = ( 0 == ( flags & kIOPMACInstalled ) );
- }
-
-Return:
- if (cfarray)
- CFRelease(cfarray);
- return result;
-
-} // on_battery_power()
-
-/*
---
-*/
-
-int is_disk_awake( void )
-{
- int result = 1; // Go ahead and sync by default.
- int err;
- DiskDevice diskDevice;
- IOATAPowerState powerState;
-
- bzero(&diskDevice, sizeof(diskDevice));
-
- err = GetATADeviceInfoWithRetry( & diskDevice );
- if ( err )
- {
- result = 1; // Go ahead and sync.
- goto Return;
- }
-
- powerState = PowerStatesMax( & diskDevice.powerStates );
-
-// printf( "%s: power state = %s\n", __FUNCTION__, PowerStateString( powerState, /* opt_summary = */ 0 ) );
-
- result = ( powerState >= kIOATAPowerStateStandby );
-
-Return:
- if (diskDevice.name)
- free(diskDevice.name);
- if (diskDevice.location)
- free(diskDevice.location);
- if (diskDevice.interconnect)
- free(diskDevice.interconnect);
-
-// printf( "%s => %s\n", __FUNCTION__, result ? "TRUE" : "FALSE" );
- return result;
-
-} // is_disk_awake()
-
-/*
---
-*/
-
+++ /dev/null
-int on_battery_power( void );
-int is_disk_awake( void );
\ No newline at end of file
.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 commonly invoked at startup time by
-.Xr rc 8
+is invoked at startup time by
+.Xr launchd 8
when the system goes multi-user.
.Sh SEE ALSO
.Xr sync 2 ,
.Xr fsck 8 ,
-.Xr init 8 ,
-.Xr rc 8 ,
+.Xr launchd 8 ,
.Xr sync 8
.Sh BUGS
It is possible on some systems that a
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2007 Apple 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.
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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) 1987, 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1987, 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)update.c 8.1 (Berkeley) 6/6/93";
-#endif /* not lint */
-
-#include <stdlib.h>
+#include <sandbox.h>
#include <stdio.h>
#include <unistd.h>
-#include <getopt.h>
-
-#include "power_mgmt.h"
-#include "disk_power.h"
-extern char *optarg;
-
-static void usage(const char *argv0) __attribute__((noreturn));
-static int parsetime(const char *arg);
-
-int main(int argc, char *const argv[])
+int
+main(void)
{
- int normal_intr = 30;
- int save_pwr_intr = 30;
- int on_bat, disk_up, last_sync = 0, current_sync_interval = 0;
-
- if (argc > 3)
- usage(argv[0]);
- if (argc > 2)
- save_pwr_intr = parsetime(argv[2]);
- if (argc > 1)
- normal_intr = parsetime(argv[1]);
-
- if (normal_intr == -1 || save_pwr_intr == -1)
- usage(argv[0]);
-
- if (normal_intr > save_pwr_intr)
- normal_intr = save_pwr_intr;
-
- daemon(0, 0);
+ 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 (;;) {
- if (last_sync >= current_sync_interval) {
- sync();
- last_sync = 0;
- }
sleep(30);
- last_sync += 30;
-
- on_bat = on_battery_power();
- disk_up = is_disk_awake();
-
- current_sync_interval = normal_intr;
- if (on_bat && !disk_up)
- current_sync_interval = save_pwr_intr;
-
+ sync();
}
-}
-
-static int parsetime(const char *arg)
-{
- char *q = NULL;
- int r;
-
- r = strtol(arg, &q, 10);
-
- if (r < 1)
- return -1;
- if (arg == q)
- return -1;
-
- switch (*q) {
- case 'h':
- r *= 60;
- case 'm':
- r *= 60;
- case 's':
- case '\0':
- break;
- default:
- return -1;
- }
-
- return r;
-}
-
-static void usage(const char *argv0)
-{
- fprintf(stderr, "usage: %s [normal_interval [power_saving_interval]]\n", argv0);
- exit(EXIT_FAILURE);
+ return 0;
}
--- /dev/null
+;; 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)
+++ /dev/null
-#
-# 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 = utmp_update
-
-PROJECTVERSION = 1.1
-PROJECT_TYPE = Tool
-
-CFILES = utmp_update.c
-
-OTHERSRCS = Makefile Makefile.postamble
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/libexec
-WINDOWS_INSTALLDIR = /usr/libexec
-PDO_UNIX_INSTALLDIR = /usr/libexec
-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
+++ /dev/null
-after_install:
- chmod 4511 $(DSTROOT)/usr/libexec/utmp_update
+++ /dev/null
-{
- FILESTABLE = {
- FRAMEWORKS = ();
- OTHER_LINKED = (utmp_update.c);
- OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble);
- PRECOMPILED_HEADERS = ();
- PROJECT_HEADERS = ();
- PUBLIC_HEADERS = ();
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- LOCALIZABLE_FILES = {};
- NEXTSTEP_BUILDDIR = "";
- NEXTSTEP_BUILDTOOL = /bin/make;
- NEXTSTEP_COMPILEROPTIONS = "";
- NEXTSTEP_INSTALLDIR = /usr/libexec;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_LINKEROPTIONS = "";
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDDIR = "";
- PDO_UNIX_BUILDTOOL = /bin/make;
- PDO_UNIX_COMPILEROPTIONS = "";
- PDO_UNIX_INSTALLDIR = /usr/libexec;
- PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
- PDO_UNIX_LINKEROPTIONS = "";
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = utmp_update;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 1.1;
- WINDOWS_BUILDDIR = "";
- WINDOWS_BUILDTOOL = /bin/make;
- WINDOWS_COMPILEROPTIONS = "";
- WINDOWS_INSTALLDIR = /usr/libexec;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_LINKEROPTIONS = "";
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-/* $NetBSD: utmp_update.c,v 1.6 2003/02/26 18:16:50 christos Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <sys/cdefs.h>
-
-__RCSID("$NetBSD: utmp_update.c,v 1.6 2003/02/26 18:16:50 christos Exp $");
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <stdio.h>
-#include <vis.h>
-#include <err.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <utmpx.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <paths.h>
-
-int main(int, char *[]);
-
-int
-main(int argc, char *argv[])
-{
- struct utmpx *utx;
- size_t len;
- struct passwd *pwd;
- struct stat st;
- int fd;
- uid_t euid, ruid;
- char tty[MAXPATHLEN];
-
- euid = geteuid();
- ruid = getuid();
- if (seteuid(ruid) == -1)
- err(1, "seteuid");
-
- if (argc != 2) {
- (void)fprintf(stderr, "Usage: %s <vis-utmpx-entry>\n",
- getprogname());
- exit(1);
- }
-
- len = strlen(argv[1]);
-
- // arg string can't be greater the 4x the size of struct utmpx
- // nor less that the size of struct utmpx
- if (len > sizeof(*utx) * 4 || len < sizeof(*utx))
- errx(1, "Bad argument");
-
- // need an extra byte because strunvis will null terminate
- if ((utx = malloc(len + 1)) == NULL)
- err(1, NULL);
-
- if (strunvis((char *)utx, argv[1]) != sizeof(*utx))
- errx(1, "Decoding error");
-
- switch (utx->ut_type) {
- case USER_PROCESS:
- case DEAD_PROCESS:
- break;
- default:
- errx(1, "Invalid utmpx type %d", (int)utx->ut_type);
- }
-
- if (ruid != 0) {
- if ((pwd = getpwuid(ruid)) == NULL)
- errx(1, "User %lu does not exist in password database",
- (long)ruid);
-
- if (strcmp(pwd->pw_name, utx->ut_user) != 0)
- errx(1, "Current user `%s' does not match "
- "`%s' in utmpx entry", pwd->pw_name, utx->ut_user);
- }
-
- (void)snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, utx->ut_line);
- fd = open(tty, O_RDONLY, 0);
- if (fd != -1) {
- if (fstat(fd, &st) == -1)
- err(1, "Cannot stat `%s'", tty);
- if (ruid != 0 && st.st_uid != ruid)
- errx(1, "%s: Is not owned by you", tty);
- if (!isatty(fd))
- errx(1, "%s: Not a tty device", tty);
- (void)close(fd);
- if (access(tty, W_OK|R_OK) == -1)
- err(1, "%s", tty);
- } else {
- struct utmpx utold, *utoldp;
- /*
- * A daemon like ftpd that does not use a tty line?
- * We only allow it to kill its own existing entries
- */
- if (utx->ut_type != DEAD_PROCESS)
- err(1, "Cannot open `%s'", tty);
-
- (void)memcpy(utold.ut_line, utx->ut_line, sizeof(utx->ut_line));
- if ((utoldp = getutxline(&utold)) == NULL)
- err(1, "Cannot find existing entry for `%s'",
- utx->ut_line);
- if (utoldp->ut_pid != getppid())
- err(1, "Cannot modify entry for `%s'", tty);
- }
-
- (void)seteuid(euid);
- if (pututxline(utx) == NULL)
- err(1, "Cannot update utmp entry");
-
- return 0;
-}
--- /dev/null
+#
+# 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 = vifs
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = vifs.c
+
+OTHERSRCS = Makefile Makefile.postamble vifs.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 $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
--- /dev/null
+after_install::
+ mkdir -p $(DSTROOT)/usr/share/man/man8
+ cp vifs.8 $(DSTROOT)/usr/share/man/man8/
--- /dev/null
+{
+ DOCICONFILES = ();
+ FILESTABLE = {
+ C_FILES = (vifs.c);
+ H_FILES = ();
+ OTHER_LIBS = ();
+ OTHER_LINKED = ();
+ OTHER_SOURCES = (Makefile, vifs.8);
+ PRECOMPILED_HEADERS = ();
+ PROJECT_HEADERS = ();
+ PUBLIC_HEADERS = ();
+ SUBPROJECTS = ();
+ };
+ GENERATEMAIN = YES;
+ LANGUAGE = English;
+ LOCALIZABLE_FILES = {};
+ NEXTSTEP_BUILDDIR = "";
+ NEXTSTEP_BUILDTOOL = /bin/make;
+ NEXTSTEP_COMPILEROPTIONS = "";
+ NEXTSTEP_INSTALLDIR = /usr/sbin;
+ NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
+ NEXTSTEP_LINKEROPTIONS = "";
+ NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
+ PDO_UNIX_BUILDDIR = "";
+ PDO_UNIX_BUILDTOOL = /bin/make;
+ PDO_UNIX_COMPILEROPTIONS = "";
+ PDO_UNIX_INSTALLDIR = /usr/sbin;
+ PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac";
+ PDO_UNIX_LINKEROPTIONS = "";
+ PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
+ PROJECTNAME = vifs;
+ PROJECTTYPE = Tool;
+ PROJECTVERSION = 2.8;
+ WINDOWS_BUILDDIR = "";
+ WINDOWS_BUILDTOOL = /bin/make;
+ WINDOWS_COMPILEROPTIONS = "";
+ WINDOWS_INSTALLDIR = /usr/sbin;
+ WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
+ WINDOWS_LINKEROPTIONS = "";
+ WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
+}
--- /dev/null
+.\"
+.\" (c) 2005 Apple Computer, Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd November 18, 2005
+.Dt VIFS 8
+.Os
+.Sh NAME
+.Nm vifs
+.Nd safely edit fstab
+.Sh SYNOPSIS
+.Nm vifs
+.Sh DESCRIPTION
+The
+.Nm vifs
+utility simply locks the fstab file before invoking an editor on it.
+This is important to facilitate the modification of fstab by automated tools
+and system management software.
+.Pp
+Always use
+.Nm vifs
+to edit fstab, instead of invoking an editor directly.
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr fstab 5
+.Sh HISTORY
+The
+.Nm vifs
+utility originates from Mac OSX 10.5.
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <fstab.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <unistd.h>
+#include <signal.h>
+
+char *warning = "\
+#\n\
+# Warning - this file should only be modified with vifs(8)\n\
+#\n\
+# Failure to do so is unsupported and may be destructive.\n\
+#\n";
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ int fd, x;
+ uid_t euid;
+ pid_t editpid;
+ char *p, *editor;
+
+ if (argc != 1) {
+ printf("usage: vifs\n");
+ exit(1);
+ }
+
+ euid = geteuid();
+ if (euid != 0)
+ errx(1, "need to run as root");
+
+ /* examine the existing fstab, try to create it if needed */
+ if (stat(_PATH_FSTAB, &sb) < 0) {
+ if (errno == ENOENT) {
+ fd = open(_PATH_FSTAB, O_CREAT | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd < 0)
+ errx(1, "error creating %s", _PATH_FSTAB);
+ write(fd, warning, strlen(warning));
+ close(fd);
+ } else {
+ errx(1, "could not stat %s", _PATH_FSTAB);
+ }
+ }
+
+ /* prepare the file for the editor */
+ fd = open(_PATH_FSTAB, O_RDONLY, 0);
+ if (fd < 0)
+ errx(1, "error opening %s", _PATH_FSTAB);
+
+ x = fcntl(fd, F_SETFD, 1);
+ if (x < 0)
+ errx(1, "error setting close on exit");
+
+ x = flock(fd, LOCK_EX | LOCK_NB);
+ if (x != 0)
+ errx(1, "file is busy");
+
+ /* obtain and invoke the editor */
+ editor = getenv("EDITOR");
+ if (editor == NULL)
+ editor = _PATH_VI;
+ p = strrchr(editor, '/');
+ if (p != NULL)
+ ++p;
+ else
+ p = editor;
+
+ editpid = vfork();
+ if (editpid == 0) {
+ execlp(editor, p, _PATH_FSTAB, NULL);
+ _exit(1);
+ }
+
+ for ( ; ; ) {
+ editpid = waitpid(editpid, (int *)&x, WUNTRACED);
+ if (editpid == -1)
+ errx(1, "editing error");
+ else if (WIFSTOPPED(x))
+ raise(WSTOPSIG(x));
+ else if (WIFEXITED(x) && WEXITSTATUS(x) == 0)
+ break;
+ else
+ errx(1, "editing error");
+ }
+
+ /* let process death clean up locks and file descriptors */
+ return 0;
+}
# a single colon.
after_install::
- $(MKDIR) -p $(DSTROOT)/usr/share/man/man8
+ $(MKDIRS) $(DSTROOT)/usr/share/man/man8
$(CP) vipw.8 $(DSTROOT)/usr/share/man/man8/
*/
#ifndef lint
-static char sccsid[] = "@(#)pw_util.c 8.4 (Berkeley) 4/28/95";
+#include <sys/cdefs.h>
+__unused static char sccsid[] = "@(#)pw_util.c 8.4 (Berkeley) 4/28/95";
#endif /* not lint */
/*
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
+__unused static char copyright[] =
"@(#) Copyright (c) 1987, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)vipw.c 8.3 (Berkeley) 4/2/94";
+__unused static char sccsid[] = "@(#)vipw.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
#include <sys/types.h>
.\"
.Dd August 13, 1997
.Dt VM_STAT 1
-.Os Mac OS X
+.Os "Mac OS X"
.Sh NAME
.Nm vm_stat
.Nd show Mach virtual memory statistics
count of 1 displays the values per second). However, the first line
of output following each banner displays the system-wide totals for
each statistic. The following values are displayed:
-.Bl -tag -width indent -compact
+.Bl -tag -width indent
.It Pages free
the total number of free pages in the system.
.It Pages active
int delay;
char *pgmname;
mach_port_t myHost;
-int pageSize = 4096; /* set to 4k default */
+vm_size_t pageSize = 4096; /* set to 4k default */
void usage(void);
void banner(void);
void
get_stats(struct vm_statistics *stat)
{
- int count = HOST_VM_INFO_COUNT;
+ unsigned int count = HOST_VM_INFO_COUNT;
if (host_statistics(myHost, HOST_VM_INFO, (host_info_t)stat, &count) != KERN_SUCCESS) {
fprintf(stderr, "%s: failed to get statistics.\n", pgmname);
exit(EXIT_FAILURE);
.Nm zdump
.Nd timezone dumper
.Sh SYNOPSIS
-.Nm
+.Nm zdump
.Op Fl -version
.Op Fl v
-.Op Fl c Ar cutoffyear
-.Op Ar zonename ...
+.Op Fl c Ar cutoff_year
+.Op Ar zone_name ...
.Sh DESCRIPTION
The
-.Nm
+.Nm zdump
utility prints the current time in each
-.Ar zonename
+.Ar zone_name
named on the command line.
.Pp
The following options are available:
.Bl -tag -width indent
-.It Fl -version
-Output version information and exit.
+.\" ===========
+.It Fl c Ar cutoff_year
+Cut off the verbose output near the start of the given year.
+.\" ===========
.It Fl v
For each
-.Ar zonename
+.Ar zone_name
on the command line,
print the time at the lowest possible time value,
the time one day after the lowest possible time value,
if the given time is Daylight Saving Time or
.Em isdst=0
otherwise.
-.It Fl c Ar cutoffyear
-Cut off the verbose output near the start of the given year.
+.\" ===========
+.It Fl -version
+Output version information and exit.
.El
.Sh "SEE ALSO"
.Xr ctime 3 ,
CFILES = ialloc.c scheck.c zic.c
-OTHERSRCS = HACK Makefile.preamble Makefile Makefile.postamble\
- datfiles zic.8
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble zic.8
MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
DATA= $(YDATA) $(NDATA) $(SDATA) leapseconds # yearistype.sh
USNO= usno1988 usno1989
+Embedded=$(shell tconf --test TARGET_OS_EMBEDDED)
+
+# Embedded zic is probably not built with the same architecture as
+# the build host, so we can't use the recently built copy.
+ifeq "$(Embedded)" "YES"
+ZIC=/usr/sbin/zic
+else
ZIC=${DSTROOT}/usr/sbin/zic
+endif
${YEARISTYPECOPY}:
cp ${YEARISTYPE} ${YEARISTYPECOPY}
# ftp://elsie.nci.nih.gov/pub/tzdata*.tar.gz
# the tzdata*.tar.gz file is automatically unpacked and a version file created
+# /usr/local/share/tz/tzdata*.tar.gz is installed by the TimeZoneData project
DATFILES = ${OFILE_DIR}/datfiles
-TARBALL = $(shell echo `pwd`/datfiles/tzdata*)
+TARBALL = $(shell echo /usr/local/share/tz/tzdata*)
DATVERS = $(shell basename ${TARBALL} | sed -e 's,\..*,,' -e 's/^tzdata//')
VERSIONFILE = ${ZONEINFO}/+VERSION
chmod -R og-w ${ZONEINFO}
install -c -m 444 ${DATFILES}/zone.tab ${ZONEINFO}
install -c -m 444 ${DATFILES}/iso3166.tab ${ZONEINFO}
+ifeq "$(Embedded)" "YES"
+ -mkdir -p ${DSTROOT}/private/var/db
+ -rm -f ${DSTROOT}/private/var/db/localtime
+ ln -fs /usr/share/zoneinfo/${LOCALTIME} ${DSTROOT}/private/var/db/localtime
+else
-mkdir -p ${DSTROOT}/private/etc
-rm -f ${DSTROOT}/private/etc/localtime
ln -fs /usr/share/zoneinfo/${LOCALTIME} ${DSTROOT}/private/etc/localtime
+endif
mkdir -p ${DSTROOT}/usr/share/man/man8
install -c -m 444 zic.8 ${DSTROOT}/usr/share/man/man8
echo ${DATVERS} > ${VERSIONFILE}
FRAMEWORKS = ();
H_FILES = (private.h, tzfile.h);
OTHER_LINKED = (ialloc.c, scheck.c, zic.c);
- OTHER_SOURCES = (HACK, Makefile.preamble, Makefile, Makefile.postamble, datfiles, zic.8);
+ OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, zic.8);
SUBPROJECTS = ();
};
LANGUAGE = English;
+++ /dev/null
-@(#)Theory 7.13
-
-
------ Outline -----
-
- Time and date functions
- Names of time zone regions
- Time zone abbreviations
- Calendrical issues
-
-
------ Time and date functions -----
-
-These time and date functions are upwards compatible with POSIX.1,
-an international standard for Unix-like systems.
-As of this writing, the current edition of POSIX.1 is:
-
- Information technology --Portable Operating System Interface (POSIX (R))
- -- Part 1: System Application Program Interface (API) [C Language]
- ISO/IEC 9945-1:1996
- ANSI/IEEE Std 1003.1, 1996 Edition
- 1996-07-12
-
-POSIX.1 has the following properties and limitations.
-
-* In POSIX.1, time display in a process is controlled by the
- environment variable TZ. Unfortunately, the POSIX.1 TZ string takes
- a form that is hard to describe and is error-prone in practice.
- Also, POSIX.1 TZ strings can't deal with other (for example, Israeli)
- daylight saving time rules, or situations where more than two
- time zone abbreviations are used in an area.
-
- The POSIX.1 TZ string takes the following form:
-
- stdoffset[dst[offset],date[/time],date[/time]]
-
- where:
-
- std and dst
- are 3 or more characters specifying the standard
- and daylight saving time (DST) zone names.
- offset
- is of the form `[-]hh:[mm[:ss]]' and specifies the
- offset west of UTC. The default DST offset is one hour
- ahead of standard time.
- date[/time],date[/time]
- specifies the beginning and end of DST. If this is absent,
- the system supplies its own rules for DST, and these can
- differ from year to year; typically US DST rules are used.
- time
- takes the form `hh:[mm[:ss]]' and defaults to 02:00.
- date
- takes one of the following forms:
- Jn (1<=n<=365)
- origin-1 day number not counting February 29
- n (0<=n<=365)
- origin-0 day number counting February 29 if present
- Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12)
- for the dth day of week n of month m of the year,
- where week 1 is the first week in which day d appears,
- and `5' stands for the last week in which day d appears
- (which may be either the 4th or 5th week).
-
-* In POSIX.1, when a TZ value like "EST5EDT" is parsed,
- typically the current US DST rules are used,
- but this means that the US DST rules are compiled into each program
- that does time conversion. This means that when US time conversion
- rules change (as in the United States in 1987), all programs that
- do time conversion must be recompiled to ensure proper results.
-
-* In POSIX.1, there's no tamper-proof way for a process to learn the
- system's best idea of local wall clock. (This is important for
- applications that an administrator wants used only at certain times--
- without regard to whether the user has fiddled the "TZ" environment
- variable. While an administrator can "do everything in UTC" to get
- around the problem, doing so is inconvenient and precludes handling
- daylight saving time shifts--as might be required to limit phone
- calls to off-peak hours.)
-
-* POSIX.1 requires that systems ignore leap seconds.
-
-These are the extensions that have been made to the POSIX.1 functions:
-
-* The "TZ" environment variable is used in generating the name of a file
- from which time zone information is read (or is interpreted a la
- POSIX); "TZ" is no longer constrained to be a three-letter time zone
- name followed by a number of hours and an optional three-letter
- daylight time zone name. The daylight saving time rules to be used
- for a particular time zone are encoded in the time zone file;
- the format of the file allows U.S., Australian, and other rules to be
- encoded, and allows for situations where more than two time zone
- abbreviations are used.
-
- It was recognized that allowing the "TZ" environment variable to
- take on values such as "America/New_York" might cause "old" programs
- (that expect "TZ" to have a certain form) to operate incorrectly;
- consideration was given to using some other environment variable
- (for example, "TIMEZONE") to hold the string used to generate the
- time zone information file name. In the end, however, it was decided
- to continue using "TZ": it is widely used for time zone purposes;
- separately maintaining both "TZ" and "TIMEZONE" seemed a nuisance;
- and systems where "new" forms of "TZ" might cause problems can simply
- use TZ values such as "EST5EDT" which can be used both by
- "new" programs (a la POSIX) and "old" programs (as zone names and
- offsets).
-
-* To handle places where more than two time zone abbreviations are used,
- the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst]
- (where "tmp" is the value the function returns) to the time zone
- abbreviation to be used. This differs from POSIX.1, where the elements
- of tzname are only changed as a result of calls to tzset.
-
-* Since the "TZ" environment variable can now be used to control time
- conversion, the "daylight" and "timezone" variables are no longer
- needed. (These variables are defined and set by "tzset"; however, their
- values will not be used by "localtime.")
-
-* The "localtime" function has been set up to deliver correct results
- for near-minimum or near-maximum time_t values. (A comment in the
- source code tells how to get compatibly wrong results).
-
-* A function "tzsetwall" has been added to arrange for the system's
- best approximation to local wall clock time to be delivered by
- subsequent calls to "localtime." Source code for portable
- applications that "must" run on local wall clock time should call
- "tzsetwall();" if such code is moved to "old" systems that don't
- provide tzsetwall, you won't be able to generate an executable program.
- (These time zone functions also arrange for local wall clock time to be
- used if tzset is called--directly or indirectly--and there's no "TZ"
- environment variable; portable applications should not, however, rely
- on this behavior since it's not the way SVR2 systems behave.)
-
-* These functions can account for leap seconds, thanks to Bradley White
- (bww@k.cs.cmu.edu).
-
-Points of interest to folks with other systems:
-
-* This package is already part of many POSIX-compliant hosts,
- including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun.
- On such hosts, the primary use of this package
- is to update obsolete time zone rule tables.
- To do this, you may need to compile the time zone compiler
- `zic' supplied with this package instead of using the system `zic',
- since the format of zic's input changed slightly in late 1994,
- and many vendors still do not support the new input format.
-
-* The Unix Version 7 "timezone" function is not present in this package;
- it's impossible to reliably map timezone's arguments (a "minutes west
- of GMT" value and a "daylight saving time in effect" flag) to a
- time zone abbreviation, and we refuse to guess.
- Programs that in the past used the timezone function may now examine
- tzname[localtime(&clock)->tm_isdst] to learn the correct time
- zone abbreviation to use. Alternatively, use
- localtime(&clock)->tm_zone if this has been enabled.
-
-* The 4.2BSD gettimeofday function is not used in this package.
- This formerly let users obtain the current UTC offset and DST flag,
- but this functionality was removed in later versions of BSD.
-
-* In SVR2, time conversion fails for near-minimum or near-maximum
- time_t values when doing conversions for places that don't use UTC.
- This package takes care to do these conversions correctly.
-
-The functions that are conditionally compiled if STD_INSPIRED is defined
-should, at this point, be looked on primarily as food for thought. They are
-not in any sense "standard compatible"--some are not, in fact, specified in
-*any* standard. They do, however, represent responses of various authors to
-standardization proposals.
-
-Other time conversion proposals, in particular the one developed by folks at
-Hewlett Packard, offer a wider selection of functions that provide capabilities
-beyond those provided here. The absence of such functions from this package
-is not meant to discourage the development, standardization, or use of such
-functions. Rather, their absence reflects the decision to make this package
-contain valid extensions to POSIX.1, to ensure its broad
-acceptability. If more powerful time conversion functions can be standardized,
-so much the better.
-
-
------ Names of time zone rule files -----
-
-The time zone rule file naming conventions attempt to strike a balance
-among the following goals:
-
- * Uniquely identify every national region where clocks have all
- agreed since 1970. This is essential for the intended use: static
- clocks keeping local civil time.
-
- * Indicate to humans as to where that region is. This simplifes use.
-
- * Be robust in the presence of political changes. This reduces the
- number of updates and backward-compatibility hacks. For example,
- names of countries are ordinarily not used, to avoid
- incompatibilities when countries change their name
- (e.g. Zaire->Congo) or when locations change countries
- (e.g. Hong Kong from UK colony to China).
-
- * Be portable to a wide variety of implementations.
- This promotes use of the technology.
-
- * Use a consistent naming convention over the entire world.
- This simplifies both use and maintenance.
-
-This naming convention is not intended for use by inexperienced users
-to select TZ values by themselves (though they can of course examine
-and reuse existing settings). Distributors should provide
-documentation and/or a simple selection interface that explains the
-names; see the 'tzselect' program supplied with this distribution for
-one example.
-
-Names normally have the form AREA/LOCATION, where AREA is the name
-of a continent or ocean, and LOCATION is the name of a specific
-location within that region. North and South America share the same
-area, `America'. Typical names are `Africa/Cairo', `America/New_York',
-and `Pacific/Honolulu'.
-
-Here are the general rules used for choosing location names,
-in decreasing order of importance:
-
- Use only valid POSIX file name components (i.e., the parts of
- names other than `/'). Within a file name component,
- use only ASCII letters, `.', `-' and `_'. Do not use
- digits, as that might create an ambiguity with POSIX
- TZ strings. A file name component must not exceed 14
- characters or start with `-'. E.g., prefer `Brunei'
- to `Bandar_Seri_Begawan'.
- Include at least one location per time zone rule set per country.
- One such location is enough. Use ISO 3166 (see the file
- iso3166.tab) to help decide whether something is a country.
- If all the clocks in a country's region have agreed since 1970,
- don't bother to include more than one location
- even if subregions' clocks disagreed before 1970.
- Otherwise these tables would become annoyingly large.
- If a name is ambiguous, use a less ambiguous alternative;
- e.g. many cities are named San Jose and Georgetown, so
- prefer `Costa_Rica' to `San_Jose' and `Guyana' to `Georgetown'.
- Keep locations compact. Use cities or small islands, not countries
- or regions, so that any future time zone changes do not split
- locations into different time zones. E.g. prefer `Paris'
- to `France', since France has had multiple time zones.
- Use mainstream English spelling, e.g. prefer `Rome' to `Roma', and
- prefer `Athens' to the true name (which uses Greek letters).
- The POSIX file name restrictions encourage this rule.
- Use the most populous among locations in a country's time zone,
- e.g. prefer `Shanghai' to `Beijing'. Among locations with
- similar populations, pick the best-known location,
- e.g. prefer `Rome' to `Milan'.
- Use the singular form, e.g. prefer `Canary' to `Canaries'.
- Omit common suffixes like `_Islands' and `_City', unless that
- would lead to ambiguity. E.g. prefer `Cayman' to
- `Cayman_Islands' and `Guatemala' to `Guatemala_City',
- but prefer `Mexico_City' to `Mexico' because the country
- of Mexico has several time zones.
- Use `_' to represent a space.
- Omit `.' from abbreviations in names, e.g. prefer `St_Helena'
- to `St._Helena'.
- Do not change established names if they only marginally
- violate the above rules. For example, don't change
- the existing name `Rome' to `Milan' merely because
- Milan's population has grown to be somewhat greater
- than Rome's.
- If a name is changed, put its old spelling in the `backward' file.
-
-The file `zone.tab' lists the geographical locations used to name
-time zone rule files.
-
-Older versions of this package used a different naming scheme,
-and these older names are still supported.
-See the file `backward' for most of these older names
-(e.g. `US/Eastern' instead of `America/New_York').
-The other old-fashioned names still supported are
-`WET', `CET', `MET', `EET' (see the file `europe'),
-and `Factory' (see the file `factory').
-
-
------ Time zone abbreviations -----
-
-When this package is installed, it generates time zone abbreviations
-like `EST' to be compatible with human tradition and POSIX.1.
-Here are the general rules used for choosing time zone abbreviations,
-in decreasing order of importance:
-
- Use abbreviations that consist of three or more ASCII letters.
- Previous editions of this database also used characters like
- ' ' and '?', but these characters have a special meaning to
- the shell and cause commands like
- set `date`
- to have unexpected effects.
- Previous editions of this rule required upper-case letters,
- but the Congressman who introduced Chamorro Standard Time
- preferred "ChST", so the rule has been relaxed.
-
- This rule guarantees that all abbreviations could have
- been specified by a POSIX.1 TZ string. POSIX.1
- requires at least three characters for an
- abbreviation. POSIX.1-1996 says that an abbreviation
- cannot start with ':', and cannot contain ',', '-',
- '+', NUL, or a digit. Draft 7 of POSIX 1003.1-200x
- changes this rule to say that an abbreviation can
- contain only '-', '+', and alphanumeric characters in
- the current locale. To be portable to both sets of
- rules, an abbreviation must therefore use only ASCII
- letters, as these are the only letters that are
- alphabetic in all locales.
-
- Use abbreviations that are in common use among English-speakers,
- e.g. `EST' for Eastern Standard Time in North America.
- We assume that applications translate them to other languages
- as part of the normal localization process; for example,
- a French application might translate `EST' to `HNE'.
-
- For zones whose times are taken from a city's longitude, use the
- traditional xMT notation, e.g. `PMT' for Paris Mean Time.
- The only name like this in current use is `GMT'.
-
- If there is no common English abbreviation, abbreviate the English
- translation of the usual phrase used by native speakers.
- If this is not available or is a phrase mentioning the country
- (e.g. ``Cape Verde Time''), then:
-
- When a country has a single or principal time zone region,
- append `T' to the country's ISO code, e.g. `CVT' for
- Cape Verde Time. For summer time append `ST';
- for double summer time append `DST'; etc.
- When a country has multiple time zones, take the first three
- letters of an English place name identifying each zone
- and then append `T', `ST', etc. as before;
- e.g. `VLAST' for VLAdivostok Summer Time.
-
- Use "zzz" for locations while uninhabited. The mnemonic is that
- these locations are, in some sense, asleep.
-
-Application writers should note that these abbreviations are ambiguous
-in practice: e.g. `EST' has a different meaning in Australia than
-it does in the United States. In new applications, it's often better
-to use numeric UTC offsets like `-0500' instead of time zone
-abbreviations like `EST'; this avoids the ambiguity.
-
-
------ Calendrical issues -----
-
-Calendrical issues are a bit out of scope for a time zone database,
-but they indicate the sort of problems that we would run into if we
-extended the time zone database further into the past. An excellent
-resource in this area is Nachum Dershowitz and Edward M. Reingold,
-<a href="http://emr.cs.uiuc.edu/home/reingold/calendar-book/index.shtml">
-Calendrical Calculations
-</a>, Cambridge University Press (1997). Other information and
-sources are given below. They sometimes disagree.
-
-
-France
-
-Gregorian calendar adopted 1582-12-20.
-French Revolutionary calendar used 1793-11-24 through 1805-12-31,
-and (in Paris only) 1871-05-06 through 1871-05-23.
-
-
-Russia
-
-From Chris Carrier <72157.3334@CompuServe.COM> (1996-12-02):
-On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar''
-with 30-day months plus 5 holidays, with a 5-day week.
-On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
-Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
-reverted to the 7-day week. With the 6-day week the usual days
-off were the 6th, 12th, 18th, 24th and 30th of the month.
-(Source: Evitiar Zerubavel, _The Seven Day Circle_)
-
-
-Mark Brader reported a similar story in "The Book of Calendars", edited
-by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But:
-
-From: Petteri Sulonen (via Usenet)
-Date: 14 Jan 1999 00:00:00 GMT
-Message-ID: <Petteri.Sulonen-1401991626030001@lapin-kulta.in.helsinki.fi>
-
-If your source is correct, how come documents between 1929 -- 1940 were
-still dated using the conventional, Gregorian calendar?
-
-I can post a scan of a document dated December 1, 1934, signed by
-Yenukidze, the secretary, on behalf of Kalinin, the President of the
-Executive Committee of the Supreme Soviet, if you like.
-
-
-
-Sweden (and Finland)
-
-From: msb@sq.com (Mark Brader)
-<a href="news:1996Jul6.012937.29190@sq.com">
-Subject: Re: Gregorian reform -- a part of locale?
-</a>
-Date: 1996-07-06
-
-In 1700, Denmark made the transition from Julian to Gregorian. Sweden
-decided to *start* a transition in 1700 as well, but rather than have one of
-those unsightly calendar gaps :-), they simply decreed that the next leap
-year after 1696 would be in 1744 -- putting the whole country on a calendar
-different from both Julian and Gregorian for a period of 40 years.
-
-However, in 1704 something went wrong and the plan was not carried through;
-they did, after all, have a leap year that year. And one in 1708. In 1712
-they gave it up and went back to Julian, putting 30 days in February that
-year!...
-
-Then in 1753, Sweden made the transition to Gregorian in the usual manner,
-getting there only 13 years behind the original schedule.
-
-(A previous posting of this story was challenged, and Swedish readers
-produced the following references to support it: "Tiderakning och historia"
-by Natanael Beckman (1924) and "Tid, en bok om tiderakning och
-kalendervasen" by Lars-Olof Lode'n (no date was given).)
-
-
-Grotefend's data
-
-From: "Michael Palmer" <mpalmer@netcom.com> [with one obvious typo fixed]
-Subject: Re: Gregorian Calendar (was Re: Another FHC related question
-Newsgroups: soc.genealogy.german
-Date: Tue, 9 Feb 1999 02:32:48 -800
-Message-ID: <199902091032.CAA09644@netcom10.netcom.com>
-
-The following is a(n incomplete) listing, arranged chronologically, of
-European states, with the date they converted from the Julian to the
-Gregorian calendar:
-
-04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
- Catholics and Danzig only)
-09/20 Dec 1582 - France, Lorraine
-
-21 Dec 1582/
- 01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
-10/21 Feb 1583 - bishopric of Liege (L"uttich)
-13/24 Feb 1583 - bishopric of Augsburg
-04/15 Oct 1583 - electorate of Trier
-05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
- Salzburg, Brixen
-13/24 Oct 1583 - Austrian Oberelsass and Breisgau
-20/31 Oct 1583 - bishopric of Basel
-02/13 Nov 1583 - duchy of J"ulich-Berg
-02/13 Nov 1583 - electorate and city of K"oln
-04/15 Nov 1583 - bishopric of W"urzburg
-11/22 Nov 1583 - electorate of Mainz
-16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
-17/28 Nov 1583 - bishopric of M"unster and duchy of Cleve
-14/25 Dec 1583 - Steiermark
-
-06/17 Jan 1584 - Austria and Bohemia
-11/22 Jan 1584 - Luzern, Uri, Schwyz, Zug, Freiburg, Solothurn
-12/23 Jan 1584 - Silesia and the Lausitz
-22 Jan/
- 02 Feb 1584 - Hungary (legally on 21 Oct 1587)
- Jun 1584 - Unterwalden
-01/12 Jul 1584 - duchy of Westfalen
-
-16/27 Jun 1585 - bishopric of Paderborn
-
-14/25 Dec 1590 - Transylvania
-
-22 Aug/
- 02 Sep 1612 - duchy of Prussia
-
-13/24 Dec 1614 - Pfalz-Neuburg
-
- 1617 - duchy of Kurland (reverted to the Julian calendar in
- 1796)
-
- 1624 - bishopric of Osnabr"uck
-
- 1630 - bishopric of Minden
-
-15/26 Mar 1631 - bishopric of Hildesheim
-
- 1655 - Kanton Wallis
-
-05/16 Feb 1682 - city of Strassburg
-
-18 Feb/
- 01 Mar 1700 - Protestant Germany (including Swedish possessions in
- Germany), Denmark, Norway
-30 Jun/
- 12 Jul 1700 - Gelderland, Zutphen
-10 Nov/
- 12 Dec 1700 - Utrecht, Overijssel
-
-31 Dec 1700/
- 12 Jan 1701 - Friesland, Groningen, Z"urich, Bern, Basel, Geneva,
- Turgau, and Schaffhausen
-
- 1724 - Glarus, Appenzell, and the city of St. Gallen
-
-01 Jan 1750 - Pisa and Florence
-
-02/14 Sep 1752 - Great Britain
-
-17 Feb/
- 01 Mar 1753 - Sweden
-
-1760-1812 - Graub"unden
-
-The Russian empire (including Finland and the Baltic states) did not
-convert to the Gregorian calendar until the Soviet revolution of 1917.
-
-Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
-Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
-(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
.Nm zic
.Nd timezone compiler
.Sh SYNOPSIS
-.Nm
+.Nm zic
.Op Fl -version
.Op Fl Dsv
.Op Fl d Ar directory
.Op Ar filename ...
.Sh DESCRIPTION
The
-.Nm
+.Nm zic
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
.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
If
.Fl D
is specified,
-.Nm
+.Nm zic
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
+.Nm zic
utility will act as if the input contained a link line of the form
.Bd -literal -offset indent
.No "Link timezone localtime
.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
+.Nm zic
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.
+.\" ==========
.It Fl u Ar user
After creating each output file, change its owner to
.Ar user
of years representable by
.Xr time 3
values.
-.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.
+.\" ==========
+.It Fl -version
+Output version information and exit.
+.\" ==========
.It Fl y Ar command
Use the given
.Ar command
If
.Em TYPE
is something else, then
-.Nm
+.Nm zic
executes the command
.Li yearistype Ar year Ar type
to check the type of a year:
name.
.PP
\fIzprint\fR interprets the following options:
-.TP 8
-.B \-w
-For each zone, \fIzprint\fR calculates how much space is allocated but
-not currently in use, the space wasted by the zone.
-.TP 8
-.B \-s
-\fIzprint\fR sorts the zones, showing the wasting the most memory first.
+.\" ==========
.TP 8
.B \-c
(Default)
Pageable and collectible zones are shown with 'P' and 'C'
on the far right. Zones with preposterously large maximum
sizes are shown with '----' in the max size and max num elts fields.
+.\" ==========
.TP 8
.B \-h
(Default)
Shows headings for the columns printed with the -c option.
It may be useful to override this option when sorting by column.
+.\" ==========
+.TP 8
+.B \-s
+\fIzprint\fR sorts the zones, showing the wasting the most memory first.
+.\" ==========
+.TP 8
+.B \-w
+For each zone, \fIzprint\fR calculates how much space is allocated but
+not currently in use, the space wasted by the zone.
.PP
Any option (including default options) can be overridden
by specifying the option in upper-case; for example, -C overrides
the (default) option -c.
-.SH "SEE ALSO"
-host_zone_info(2).
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <mach/mach.h>
#include <mach_debug/mach_debug.h>
exit(1);
}
+int
main(argc, argv)
int argc;
char *argv[];
unsigned int infoCnt = sizeof info_buf/sizeof info_buf[0];
char *zname = NULL;
- int znamelen;
+ int znamelen = 0;
kern_return_t kr;
int i, j;
{
unsigned int used, size;
- printf("%.*s zone:\n", sizeof name->zn_name, name->zn_name);
+ printf("%.*s zone:\n", (int)sizeof name->zn_name, name->zn_name);
printf("\tcur_size: %dK bytes (%d elements)\n",
info->zi_cur_size/1024,
info->zi_cur_size/info->zi_elem_size);
zone_info_t *info;
{
char *name = zone_name->zn_name;
- int j, namewidth, retval;
+ int j, namewidth;
unsigned int used, size;
namewidth = 25;