[launchd-changes] [23082] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Sun Feb 18 18:03:20 PST 2007


Revision: 23082
          http://trac.macosforge.org/projects/launchd/changeset/23082
Author:   zarzycki at apple.com
Date:     2007-02-18 18:03:20 -0800 (Sun, 18 Feb 2007)

Log Message:
-----------
Major changes:

1) init.c is 100% dead.
2) single-user-mode is now a feature of launchctl.
3) The 'jobmgr' concept is better able to self-bootstrap now.
4) Some per process kevents have been moved to the root jobmgr.
5) The user's "background" session is now being bootstrapped.
6) Deleted dead code: launchctl stdout/stderr sub commands.
7) Miscellaneous.

Work to be done:

1) Restore launchd.conf functionality.
2) Make jobmgr self-bootstrap atomic WRT bootstrap_look_up().
3) Self-bootstrap sub jobmgr objects.

Modified Paths:
--------------
    trunk/launchd/src/Makefile.am
    trunk/launchd/src/Makefile.in
    trunk/launchd/src/launchctl.1
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd.c
    trunk/launchd/src/launchd.h
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/launchd_core_logic.h
    trunk/launchd/src/launchd_runtime.c
    trunk/launchd/src/launchd_runtime.h
    trunk/launchd/src/launchd_unix_ipc.c
    trunk/launchd/src/launchd_unix_ipc.h
    trunk/launchd/src/liblaunch_private.h
    trunk/launchd/src/libvproc_public.h

Removed Paths:
-------------
    trunk/launchd/src/init.c

Modified: trunk/launchd/src/Makefile.am
===================================================================
--- trunk/launchd/src/Makefile.am	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/Makefile.am	2007-02-19 02:03:20 UTC (rev 23082)
@@ -45,7 +45,7 @@
 
 launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -Wno-unused-parameter
 launchd_LDFLAGS = -lbsm
-launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c init.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c
+launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c
 
 launchd_runtime.c:: notifyServer.h launchd_internal.h
 launchd_core_logic.c:: protocol_vproc.h job_reply.h protocol_vprocServer.h

Modified: trunk/launchd/src/Makefile.in
===================================================================
--- trunk/launchd/src/Makefile.in	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/Makefile.in	2007-02-19 02:03:20 UTC (rev 23082)
@@ -91,13 +91,12 @@
 launchctl_OBJECTS = launchctl-launchctl.$(OBJEXT)
 launchctl_LDADD = $(LDADD)
 am__launchd_SOURCES_DIST = launchd.c launchd_core_logic.c \
-	launchd_unix_ipc.c init.c protocol_vprocServer.c \
-	notifyServer.c launchd_internalUser.c launchd_internalServer.c \
+	launchd_unix_ipc.c protocol_vprocServer.c notifyServer.c \
+	launchd_internalUser.c launchd_internalServer.c \
 	job_replyUser.c launchd_runtime.c
 @LIBS_ONLY_FALSE at am_launchd_OBJECTS = launchd-launchd.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_core_logic.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_unix_ipc.$(OBJEXT) \
- at LIBS_ONLY_FALSE@	launchd-init.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-protocol_vprocServer.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-notifyServer.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_internalUser.$(OBJEXT) \
@@ -244,7 +243,7 @@
 @LIBS_ONLY_FALSE at SystemStarter_SOURCES = StartupItems.c IPC.c SystemStarter.c
 @LIBS_ONLY_FALSE at launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -Wno-unused-parameter
 @LIBS_ONLY_FALSE at launchd_LDFLAGS = -lbsm
- at LIBS_ONLY_FALSE@launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c init.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c
+ at LIBS_ONLY_FALSE@launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c
 @LIBS_ONLY_FALSE at launchproxy_LDFLAGS = -weak_framework Security
 @LIBS_ONLY_FALSE at man1_MANS = wait4path.1 launchctl.1
 @LIBS_ONLY_FALSE at man5_MANS = launchd.plist.5 launchd.conf.5
@@ -425,7 +424,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SystemStarter-StartupItems.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SystemStarter-SystemStarter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchctl-launchctl.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-init.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-job_replyUser.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_core_logic.Po at am__quote@
@@ -614,20 +612,6 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-launchd_unix_ipc.obj `if test -f 'launchd_unix_ipc.c'; then $(CYGPATH_W) 'launchd_unix_ipc.c'; else $(CYGPATH_W) '$(srcdir)/launchd_unix_ipc.c'; fi`
 
-launchd-init.o: init.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -MT launchd-init.o -MD -MP -MF "$(DEPDIR)/launchd-init.Tpo" -c -o launchd-init.o `test -f 'init.c' || echo '$(srcdir)/'`init.c; \
- at am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/launchd-init.Tpo" "$(DEPDIR)/launchd-init.Po"; else rm -f "$(DEPDIR)/launchd-init.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='init.c' object='launchd-init.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-init.o `test -f 'init.c' || echo '$(srcdir)/'`init.c
-
-launchd-init.obj: init.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -MT launchd-init.obj -MD -MP -MF "$(DEPDIR)/launchd-init.Tpo" -c -o launchd-init.obj `if test -f 'init.c'; then $(CYGPATH_W) 'init.c'; else $(CYGPATH_W) '$(srcdir)/init.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/launchd-init.Tpo" "$(DEPDIR)/launchd-init.Po"; else rm -f "$(DEPDIR)/launchd-init.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='init.c' object='launchd-init.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-init.obj `if test -f 'init.c'; then $(CYGPATH_W) 'init.c'; else $(CYGPATH_W) '$(srcdir)/init.c'; fi`
-
 launchd-protocol_vprocServer.o: protocol_vprocServer.c
 @am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -MT launchd-protocol_vprocServer.o -MD -MP -MF "$(DEPDIR)/launchd-protocol_vprocServer.Tpo" -c -o launchd-protocol_vprocServer.o `test -f 'protocol_vprocServer.c' || echo '$(srcdir)/'`protocol_vprocServer.c; \
 @am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/launchd-protocol_vprocServer.Tpo" "$(DEPDIR)/launchd-protocol_vprocServer.Po"; else rm -f "$(DEPDIR)/launchd-protocol_vprocServer.Tpo"; exit 1; fi

Deleted: trunk/launchd/src/init.c
===================================================================
--- trunk/launchd/src/init.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/init.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -1,383 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1991, 1993
- *      The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Donn Seeley at Berkeley Software Design, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-static const char *const __rcs_file_version__ = "$Revision$";
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/sysctl.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <ttyent.h>
-#include <unistd.h>
-#include <paths.h>
-#include <util.h>
-#include <libgen.h>
-#include <paths.h>
-#include <termios.h>
-
-#include "launchd.h"
-#include "launchd_runtime.h"
-
-#define _PATH_RUNCOM            "/etc/rc"
-
-#define	STALL_TIMEOUT		30	/* wait N secs after warning */
-
-static void stall(char *, ...);
-
-static void single_user_callback(void *, struct kevent *);
-static kq_callback kqsingle_user_callback = single_user_callback;
-static void runcom_callback(void *, struct kevent *);
-static kq_callback kqruncom_callback = runcom_callback;
-
-static void single_user(void);
-static void runcom(void);
-
-static bool single_user_mode = false;
-static bool run_runcom = true;
-static pid_t single_user_pid = 0;
-static pid_t runcom_pid = 0;
-
-static void setctty(const char *, int);
-
-static void setsecuritylevel(int);
-static int getsecuritylevel(void);
-static bool should_fsck(void);
-
-void
-init_boot(bool sflag)
-{
-	if (sflag) {
-		single_user_mode = true;
-		run_runcom = false;
-	}
-}
-
-void
-init_pre_kevent(void)
-{
-	if (single_user_pid || runcom_pid)
-		return;
-
-	if (single_user_mode)
-		return single_user();
-
-	if (run_runcom)
-		return runcom();
-		
-	/*
-	 * If the administrator has not set the security level to -1
-	 * to indicate that the kernel should not run multiuser in secure
-	 * mode, and the run script has not set a higher level of security 
-	 * than level 1, then put the kernel into secure mode.
-	 */
-	if (getsecuritylevel() == 0) {
-		setsecuritylevel(1);
-	}
-}
-
-void
-stall(char *message, ...)
-{
-	va_list ap;
-	va_start(ap, message);
-
-	vsyslog(LOG_ALERT, message, ap);
-	va_end(ap);
-	sleep(STALL_TIMEOUT);
-}
-
-int
-getsecuritylevel(void)
-{
-	int name[2], curlevel;
-	size_t len;
-
-	name[0] = CTL_KERN;
-	name[1] = KERN_SECURELVL;
-	len = sizeof (curlevel);
-	if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
-		syslog(LOG_ALERT, "cannot get kernel security level: %m");
-		return -1;
-	}
-	return curlevel;
-}
-
-void
-setsecuritylevel(int newlevel)
-{
-	int name[2], curlevel;
-
-	curlevel = getsecuritylevel();
-	if (newlevel == curlevel)
-		return;
-	name[0] = CTL_KERN;
-	name[1] = KERN_SECURELVL;
-	if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
-		syslog(LOG_ALERT, "cannot change kernel security level from %d to %d: %m",
-				curlevel, newlevel);
-		return;
-	}
-	syslog(LOG_INFO, "kernel security level changed from %d to %d",
-	    curlevel, newlevel);
-}
-
-/*
- * Start a session and allocate a controlling terminal.
- * Only called by children of init after forking.
- */
-void
-setctty(const char *name, int flags)
-{
-	int fd;
-
-	revoke(name);
-	if ((fd = open(name, flags | O_RDWR)) == -1) {
-		stall("can't open %s: %m", name);
-		exit(EXIT_FAILURE);
-	}
-	if (login_tty(fd) == -1) {
-		stall("can't get %s for controlling terminal: %m", name);
-		exit(EXIT_FAILURE);
-	}
-}
-
-void
-single_user(void)
-{
-	bool runcom_fsck = should_fsck();
-	char *argv[2];
-
-	if (getsecuritylevel() > 0)
-		setsecuritylevel(0);
-
-	if ((single_user_pid = launchd_fork()) == -1) {
-		syslog(LOG_ERR, "can't fork single-user shell, trying again: %m");
-		return;
-	} else if (single_user_pid == 0) {
-		setctty(_PATH_CONSOLE, O_POPUP);
-
-                setenv("TERM", "vt100", 1);
-
-		if (runcom_fsck) {
-			fprintf(stdout, "Singleuser boot -- fsck not done\n");
-			fprintf(stdout, "Root device is mounted read-only\n\n");
-			fprintf(stdout, "If you want to make modifications to files:\n");
-			fprintf(stdout, "\t/sbin/fsck -fy\n\t/sbin/mount -uw /\n\n");
-			fprintf(stdout, "If you wish to boot the system:\n");
-			fprintf(stdout, "\texit\n\n");
-			fflush(stdout);
-		}
-
-		argv[0] = "-sh";
-		argv[1] = NULL;
-		execv(_PATH_BSHELL, argv);
-		syslog(LOG_ERR, "can't exec %s for single user: %m", _PATH_BSHELL);
-		sleep(STALL_TIMEOUT);
-		exit(EXIT_FAILURE);
-	} else {
-		if (kevent_mod(single_user_pid, EVFILT_PROC, EV_ADD, 
-					NOTE_EXIT, 0, &kqsingle_user_callback) == -1)
-			single_user_callback(NULL, NULL);
-	}
-}
-
-void
-single_user_callback(void *obj __attribute__((unused)), struct kevent *kev __attribute__((unused)))
-{
-	int status;
-
-	if (!launchd_assumes(waitpid(single_user_pid, &status, 0) == single_user_pid))
-		return;
-
-	if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) {
-		syslog(LOG_INFO, "single user shell terminated, restarting");
-		run_runcom = true;
-		single_user_mode = false;
-	} else {
-		syslog(LOG_INFO, "single user shell terminated.");
-		run_runcom = false;
-		if (WTERMSIG(status) != SIGKILL)
-			single_user_mode = true;
-	}
-
-	single_user_pid = 0;
-}
-
-static struct timeval runcom_start_tv = { 0, 0 };
-
-/*
- * Run the system startup script.
- */
-void
-runcom(void)
-{
-	char *argv[] = { "/bin/launchctl", "bootstrap", NULL };
-	struct termios term;
-	int vdisable;
-
-	gettimeofday(&runcom_start_tv, NULL);
-
-	if ((runcom_pid = launchd_fork()) == -1) {
-		syslog(LOG_ERR, "can't fork for %s on %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
-		sleep(STALL_TIMEOUT);
-		runcom_pid = 0;
-		single_user_mode = true;
-		return;
-	} else if (runcom_pid > 0) {
-		run_runcom = false;
-		if (kevent_mod(runcom_pid, EVFILT_PROC, EV_ADD, 
-					NOTE_EXIT, 0, &kqruncom_callback) == -1) {
-			runcom_callback(NULL, NULL);
-		}
-		return;
-	}
-
-	setctty(_PATH_CONSOLE, 0);
-
-	if ((vdisable = fpathconf(STDIN_FILENO, _PC_VDISABLE)) == -1) {
-		syslog(LOG_WARNING, "fpathconf(\"%s\") %m", _PATH_CONSOLE);
-	} else if (tcgetattr(STDIN_FILENO, &term) == -1) {
-		syslog(LOG_WARNING, "tcgetattr(\"%s\") %m", _PATH_CONSOLE);
-	} else {
-		term.c_cc[VINTR] = vdisable;
-		term.c_cc[VKILL] = vdisable;
-		term.c_cc[VQUIT] = vdisable;
-		term.c_cc[VSUSP] = vdisable;
-		term.c_cc[VSTART] = vdisable;
-		term.c_cc[VSTOP] = vdisable;
-		term.c_cc[VDSUSP] = vdisable;
-
-		if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) == -1)
-			syslog(LOG_WARNING, "tcsetattr(\"%s\") %m", _PATH_CONSOLE);
-	}
-
-	execv(argv[0], argv);
-	stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
-	exit(EXIT_FAILURE);
-}
-
-void
-runcom_callback(void *obj __attribute__((unused)), struct kevent *kev __attribute__((unused)))
-{
-	int status;
-	struct timeval runcom_end_tv, runcom_total_tv;
-	double sec;
-
-	gettimeofday(&runcom_end_tv, NULL);
-	timersub(&runcom_end_tv, &runcom_start_tv, &runcom_total_tv);
-	sec = runcom_total_tv.tv_sec;
-	sec += (double)runcom_total_tv.tv_usec / (double)1000000;
-	syslog(LOG_INFO, "%s finished in: %.3f seconds", _PATH_RUNCOM, sec);
-
-	if (launchd_assumes(waitpid(runcom_pid, &status, 0) == runcom_pid)) {
-		runcom_pid = 0;
-	} else {
-		syslog(LOG_ERR, "going to single user mode");
-		single_user_mode = true;
-		return;
-	}
-
-	if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) {
-		return;
-	} else if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGTERM || WTERMSIG(status) == SIGKILL)) {
-		return;
-	}
-
-	syslog(LOG_ERR, "%s on %s terminated abnormally, going to single user mode",
-			_PATH_BSHELL, _PATH_RUNCOM);
-	single_user_mode = true;
-}
-
-bool
-init_check_pid(pid_t p)
-{
-	if (single_user_pid == p)
-		return true;
-
-	if (runcom_pid == p)
-		return true;
-
-	return false;
-}
-
-bool
-should_fsck(void)
-{
-	struct statfs sfs;
-	bool r = true;
-
-	if (launchd_assumes(statfs("/", &sfs) != -1)) {
-		if (!(sfs.f_flags & MNT_RDONLY)) {
-			r = false;
-		}
-	}
-	
-	return r;
-}

Modified: trunk/launchd/src/launchctl.1
===================================================================
--- trunk/launchd/src/launchctl.1	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchctl.1	2007-02-19 02:03:20 UTC (rev 23082)
@@ -130,12 +130,6 @@
 With four arguments, the third and forth argument represent the soft and hard limits respectively.
 See
 .Xr setrlimit 2 .
-.It Ar stdout path
-Set the standard out file descriptor to the given path.
-.Nm launchd
-.It Ar stderr path
-Set the standard error file descriptor to the given path.
-.Nm launchd
 .It Ar shutdown
 Tell
 .Nm launchd

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchctl.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -61,6 +61,7 @@
 #include <utmpx.h>
 #include <bootfiles.h>
 #include <sysexits.h>
+#include <util.h>
 
 #include "libbootstrap_public.h"
 #include "libvproc_public.h"
@@ -137,6 +138,8 @@
 static void do_application_firewall_magic(int sfd, launch_data_t thejob);
 static void preheat_page_cache_hack(void);
 static void do_bootroot_magic(void);
+static void do_single_user_mode(bool);
+static bool do_single_user_mode2(void);
 
 static int bootstrap_cmd(int argc, char *const argv[]);
 static int load_and_unload_cmd(int argc, char *const argv[]);
@@ -1174,16 +1177,74 @@
 	return fd;
 }
 
-int
-bootstrap_cmd(int argc __attribute__((unused)), char *const argv[] __attribute__((unused)))
+void
+do_single_user_mode(bool sflag)
 {
+	if (sflag) {
+		while (!do_single_user_mode2()) {
+			sleep(1);
+		}
+	}
+}
+
+bool
+do_single_user_mode2(void)
+{
+	bool runcom_fsck = true; /* should_fsck(); */
+	int wstatus;
+	int fd;
+	pid_t p;
+
+	switch ((p = fork())) {
+	case -1:
+		syslog(LOG_ERR, "can't fork single-user shell, trying again: %m");
+		return false;
+	case 0:
+		break;
+	default:
+		assumes(waitpid(p, &wstatus, 0) != -1);
+		if (WIFEXITED(wstatus)) {
+			if (WEXITSTATUS(wstatus) == EXIT_SUCCESS) {
+				return true;
+			} else {
+				fprintf(stdout, "single user mode: exit status: %d\n", WEXITSTATUS(wstatus));
+			}
+		} else {
+			fprintf(stdout, "single user mode shell: %s\n", strsignal(WTERMSIG(wstatus)));
+		}
+		return false;
+	}
+
+	revoke(_PATH_CONSOLE);
+	if (!assumes((fd = open(_PATH_CONSOLE, O_RDWR)) != -1)) {
+		_exit(EXIT_FAILURE);
+	}
+	if (!assumes(login_tty(fd) != -1)) {
+		_exit(EXIT_FAILURE);
+	}
+	setenv("TERM", "vt100", 1);
+	if (runcom_fsck) {
+		fprintf(stdout, "Singleuser boot -- fsck not done\n");
+		fprintf(stdout, "Root device is mounted read-only\n\n");
+		fprintf(stdout, "If you want to make modifications to files:\n");
+		fprintf(stdout, "\t/sbin/fsck -fy\n\t/sbin/mount -uw /\n\n");
+		fprintf(stdout, "If you wish to boot the system:\n");
+		fprintf(stdout, "\texit\n\n");
+		fflush(stdout);
+	}
+
+	execl(_PATH_BSHELL, "-sh", NULL);
+	syslog(LOG_ERR, "can't exec %s for single user: %m", _PATH_BSHELL);
+	_exit(EXIT_FAILURE);
+}
+
+static void
+very_pid2_specific_bootstrap(bool sflag)
+{
 	int hnmib[] = { CTL_KERN, KERN_HOSTNAME };
 	struct group *tfp_gr;
 
-	if (getuid() != 0) {
-		fprintf(stderr, "%s: Only root can run the 'bootstrap' sub-command right now.\n", getprogname());
-		return 1;
-	}
+	do_single_user_mode(sflag);
 
 	if (assumes((tfp_gr = getgrnam("procview")) != NULL)) {
 		int tfp_r_mib[3] = { CTL_KERN, KERN_TFP, KERN_TFP_READ_GROUP };
@@ -1262,9 +1323,12 @@
 
 	_vproc_set_global_on_demand(true);
 
-	char *load_launchd_items[] = { "load", "-D", "all", "/etc/mach_init.d", NULL };
-	if (is_safeboot())
+	char *load_launchd_items[] = { "load", "-D", "all", "/etc/mach_init.d", NULL, NULL };
+
+	if (is_safeboot()) {
 		load_launchd_items[2] = "system";
+	}
+
 	assumes(load_and_unload_cmd(4, load_launchd_items) == 0);
 
 	const char *bcc_tag_tool[] = { "BootCacheControl", "tag", NULL };
@@ -1273,7 +1337,23 @@
 	do_bootroot_magic();
 
 	_vproc_set_global_on_demand(false);
+}
 
+int
+bootstrap_cmd(int argc, char *const argv[] __attribute__((unused)))
+{
+	if (getpid() == 2 && getuid() == 0) {
+		very_pid2_specific_bootstrap(argc == 2);
+	} else if (getuid() != 0) {
+		char *load_launchd_items[] = { "load", "-D", "all", "-S", "Background", NULL };
+
+		if (is_safeboot()) {
+			load_launchd_items[2] = "system";
+		}
+
+		assumes(load_and_unload_cmd(5, load_launchd_items) == 0);
+	}
+
 	return 0;
 }
 
@@ -1680,45 +1760,10 @@
 }
 
 int
-stdio_cmd(int argc, char *const argv[])
+stdio_cmd(int argc __attribute__((unused)), char *const argv[])
 {
-	launch_data_t resp, msg, tmp;
-	int e, r = 0;
-
-	if (argc != 2) {
-		fprintf(stderr, "usage: %s %s <path>\n", getprogname(), argv[0]);
-		return 1;
-	}
-
-	msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
-
-	tmp = launch_data_new_string(argv[1]);
-
-	if (!strcmp(argv[0], "stdout")) {
-		launch_data_dict_insert(msg, tmp, LAUNCH_KEY_SETSTDOUT);
-	} else {
-		launch_data_dict_insert(msg, tmp, LAUNCH_KEY_SETSTDERR);
-	}
-
-	resp = launch_msg(msg);
-	launch_data_free(msg);
-
-	if (resp == NULL) {
-		fprintf(stderr, "launch_msg(): %s\n", strerror(errno));
-		return 1;
-	} else if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) {
-		if ((e = launch_data_get_errno(resp))) {
-			fprintf(stderr, "%s %s error: %s\n", getprogname(), argv[0], strerror(e));
-			r = 1;
-		}
-	} else {
-		fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]);
-		r = 1;
-	}
-
-	launch_data_free(resp);
-
-	return r;
+	fprintf(stderr, "%s %s: This sub-command no longer does anything\n", getprogname(), argv[0]);
+	return 1;
 }
 
 int

Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -70,13 +70,11 @@
 #include "libvproc_public.h"
 #include "libvproc_internal.h"
 #include "liblaunch_public.h"
-#include "liblaunch_private.h"
 
 #include "launchd_runtime.h"
 #include "launchd_core_logic.h"
 #include "launchd_unix_ipc.h"
 
-#define PID1LAUNCHD_CONF "/etc/launchd.conf"
 #define LAUNCHD_CONF ".launchd.conf"
 #define SECURITY_LIB "/System/Library/Frameworks/Security.framework/Versions/A/Security"
 #define SHUTDOWN_LOG_DIR "/var/log/shutdown"
@@ -84,16 +82,12 @@
 
 extern char **environ;
 
-static void signal_callback(void *, struct kevent *);
 static void pfsystem_callback(void *, struct kevent *);
 
-static kq_callback kqsignal_callback = signal_callback;
 static kq_callback kqpfsystem_callback = pfsystem_callback;
 
-static void pid1_magic_init(bool sflag);
+static void pid1_magic_init(void);
 
-static void usage(FILE *where);
-
 static void testfd_or_openfd(int fd, const char *path, int flags);
 static bool get_network_state(void);
 static void monitor_networking_state(void);
@@ -102,13 +96,9 @@
 static void prep_shutdown_log_dir(void);
 
 static bool re_exec_in_single_user_mode = false;
-static job_t rlcj = NULL;
-static jmp_buf doom_doom_doom;
 static void *crash_addr;
 static pid_t crash_pid;
-static const char *launchctl_bootstrap_tool[] = { "/bin/launchctl", /* "bootstrap", */ NULL };
 
-sigset_t blocked_signals = 0;
 static bool shutdown_in_progress = false;
 bool debug_shutdown_hangs = false;
 bool network_up = false;
@@ -118,187 +108,61 @@
 main(int argc, char *const *argv)
 {
 	static const int sigigns[] = { SIGHUP, SIGINT, SIGPIPE, SIGALRM,
-		SIGTERM, SIGURG, SIGTSTP, SIGTSTP, SIGCONT, /*SIGCHLD,*/
-		SIGTTIN, SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF,
+		SIGTERM, SIGURG, SIGTSTP, SIGTSTP, SIGCONT, SIGTTIN,
+		SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF,
 		SIGWINCH, SIGINFO, SIGUSR1, SIGUSR2
 	};
-	bool sflag = false, Dflag = false;
-	char ldconf[PATH_MAX] = PID1LAUNCHD_CONF;
-	const char *h = getenv("HOME");
-	const char *optargs = NULL;
-	struct stat sb;
-	size_t i, checkin_fdcnt = 0;
-	int *checkin_fds = NULL;
-	mach_port_t checkin_mport = MACH_PORT_NULL;
-	int ch, logopts;
+	bool sflag = false;
+	size_t i;
+	int ch;
 
 	testfd_or_openfd(STDIN_FILENO, _PATH_DEVNULL, O_RDONLY);
 	testfd_or_openfd(STDOUT_FILENO, _PATH_DEVNULL, O_WRONLY);
 	testfd_or_openfd(STDERR_FILENO, _PATH_DEVNULL, O_WRONLY);
 
-	/* main() phase one: sanitize the process */
-
-	if (getpid() != 1) {
-		launch_data_t ldresp, ldmsg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
-
-		if ((ldresp = launch_msg(ldmsg))) {
-			if (launch_data_get_type(ldresp) == LAUNCH_DATA_DICTIONARY) {
-				const char *ldlabel = launch_data_get_string(launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_LABEL));
-				launch_data_t tmp;
-
-				if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_SOCKETS))) {
-					if ((tmp = launch_data_dict_lookup(tmp, "LaunchIPC"))) {
-						checkin_fdcnt = launch_data_array_get_count(tmp);
-						checkin_fds = alloca(sizeof(int) * checkin_fdcnt);
-						for (i = 0; i < checkin_fdcnt; i++) {
-							checkin_fds[i] = _fd(launch_data_get_fd(launch_data_array_get_index(tmp, i)));
-						}
-					}
-				}
-				if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_MACHSERVICES))) {
-					if ((tmp = launch_data_dict_lookup(tmp, ldlabel))) {
-						checkin_mport = launch_data_get_machport(tmp);
-					}
-				}
-			}
-			launch_data_free(ldresp);
-		} else {
-			int sigi, fdi, dts = getdtablesize();
-			sigset_t emptyset;
-
-			/* We couldn't check-in.
-			 *
-			 * Assume the worst and clean up whatever mess our parent process left us with...
-			 */
-
-			for (fdi = STDERR_FILENO + 1; fdi < dts; fdi++)
-				close(fdi);
-			for (sigi = 1; sigi < NSIG; sigi++) {
-				switch (sigi) {
-				case SIGKILL:
-				case SIGSTOP:
-					break;
-				default:
-					launchd_assumes(signal(sigi, SIG_DFL) != SIG_ERR);
-					break;
-				}
-			}
-			sigemptyset(&emptyset);
-			launchd_assumes(sigprocmask(SIG_SETMASK, &emptyset, NULL) == 0);
-		}
-
-		launch_data_free(ldmsg);
-	}
-
-	launchd_runtime_init();
-
-	/* main() phase two: parse arguments */
-
-	if (getpid() == 1) {
-		optargs = "s";
-	} else {
-		optargs = "Dh";
-	}
-
-	while ((ch = getopt(argc, argv, optargs)) != -1) {
+	while ((ch = getopt(argc, argv, "s")) != -1) {
 		switch (ch) {
-		case 'D': Dflag = true;   break;	/* debug */
 		case 's': sflag = true;   break;	/* single user */
-		case 'h': usage(stdout);  break;	/* help */
 		case '?': /* we should do something with the global optopt variable here */
 		default:
-			fprintf(stderr, "ignoring unknown arguments\n");
-			usage(stderr);
+			fprintf(stderr, "%s: ignoring unknown arguments\n", getprogname());
 			break;
 		}
 	}
-	argc -= optind;
-	argv += optind;
 
-	/* main phase three: get the party started */
-
-	logopts = LOG_PID|LOG_CONS;
-	if (Dflag) {
-		logopts |= LOG_PERROR;
+	if (getpid() != 1 && getppid() != 1) {
+		fprintf(stderr, "%s: This program is not meant to be run directly.\n", getprogname());
+		exit(EXIT_FAILURE);
 	}
 
-	openlog(getprogname(), logopts, LOG_LAUNCHD);
-	setlogmask(LOG_UPTO(Dflag ? LOG_DEBUG : LOG_NOTICE));
+	launchd_runtime_init();
 
-	sigemptyset(&blocked_signals);
+	openlog(getprogname(), LOG_PID|LOG_CONS, LOG_LAUNCHD);
+	setlogmask(LOG_UPTO(/* LOG_DEBUG */ LOG_NOTICE));
 
 	for (i = 0; i < (sizeof(sigigns) / sizeof(int)); i++) {
-		launchd_assumes(kevent_mod(sigigns[i], EVFILT_SIGNAL, EV_ADD, 0, 0, &kqsignal_callback) != -1);
-		sigaddset(&blocked_signals, sigigns[i]);
 		launchd_assumes(signal(sigigns[i], SIG_IGN) != SIG_ERR);
 	}
 
-	/* sigh... ignoring SIGCHLD has side effects: we can't call wait*() */
-	launchd_assert(kevent_mod(SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, &kqsignal_callback) != -1);
-
-	mach_init_init(checkin_mport);
-
-	if (h) {
-		snprintf(ldconf, sizeof(ldconf), "%s/%s", h, LAUNCHD_CONF);
-	}
-
-	rlcj = job_new(root_jobmgr, READCONF_LABEL, NULL, launchctl_bootstrap_tool, ldconf);
-	launchd_assert(rlcj != NULL);
-
 	if (NULL == getenv("PATH")) {
 		setenv("PATH", _PATH_STDPATH, 1);
 	}
 
 	if (getpid() == 1) {
-		pid1_magic_init(sflag);
+		pid1_magic_init();
 	} else {
-		ipc_server_init(checkin_fds, checkin_fdcnt);
+		ipc_server_init();
 	}
 
 	monitor_networking_state();
 
-	/*
-	 * We cannot stat() anything in the home directory right now.
-	 *
-	 * The per-user launchd can easily be demand launched by the tool doing
-	 * the mount of the home directory. The result is an ugly deadlock.
-	 *
-	 * We hope to someday have a non-blocking stat(), but for now, we have
-	 * to skip it.
-	 */
-	if (!h && stat(ldconf, &sb) == 0) {
-		rlcj = job_dispatch(rlcj, true);
-	}
 
-	char *doom_why = "at instruction";
-	switch (setjmp(doom_doom_doom)) {
-		case 0:
-			break;
-		case SIGBUS:
-		case SIGSEGV:
-			doom_why = "trying to read/write";
-		case SIGILL:
-		case SIGFPE:
-			syslog(LOG_EMERG, "We crashed %s: %p (sent by PID %u)", doom_why, crash_addr, crash_pid);
-		default:
-			sync();
-			sleep(3);
-			/* the kernel will panic() when PID 1 exits */
-			_exit(EXIT_FAILURE);
-			/* we should never get here */
-			reboot(0);
-			/* or here either */
-			break;
-	}
-
 	if (getpid() == 1) {
 		handle_pid1_crashes_separately();
-
-		if (!job_active(rlcj)) {
-			init_pre_kevent();
-		}
 	}
 
+	jobmgr_init(sflag);
+
 	launchd_runtime();
 }
 
@@ -322,6 +186,7 @@
 void
 fatal_signal_handler(int sig, siginfo_t *si, void *uap)
 {
+	const char *doom_why = "at instruction";
 	char *sample_args[] = { "/usr/bin/sample", "1", "1", "-file", PID1_CRASH_LOGFILE, NULL };
 	pid_t sample_p;
 	int wstatus;
@@ -338,51 +203,42 @@
 		break;
 	default:
 		waitpid(sample_p, &wstatus, 0);
-		sync();
 		break;
 	case -1:
 		break;
 	}
 
-	longjmp(doom_doom_doom, sig);
+	switch (sig) {
+	default:
+	case 0:
+		break;
+	case SIGBUS:
+	case SIGSEGV:
+		doom_why = "trying to read/write";
+	case SIGILL:
+	case SIGFPE:
+		syslog(LOG_EMERG, "We crashed %s: %p (sent by PID %u)", doom_why, crash_addr, crash_pid);
+		sync();
+		sleep(3);
+		/* the kernel will panic() when PID 1 exits */
+		_exit(EXIT_FAILURE);
+		/* we should never get here */
+		reboot(0);
+		/* or here either */
+		break;
+	}
 }
 
 void
-pid1_magic_init(bool sflag)
+pid1_magic_init(void)
 {
 	launchd_assumes(setsid() != -1);
 	launchd_assumes(chdir("/") != -1);
 	launchd_assumes(setlogin("root") != -1);
 	launchd_assumes(mount("fdesc", "/dev", MNT_UNION, NULL) != -1);
-
-	init_boot(sflag);
 }
 
 
-void
-usage(FILE *where)
-{
-	const char *opts = "[-d]";
-
-	if (getuid() == 0) {
-		opts = "[-d] [-S <type> -U <user>]";
-	}
-
-	fprintf(where, "%s: %s [-- command [args ...]]\n", getprogname(), opts);
-
-	fprintf(where, "\t-d          Daemonize.\n");
-	fprintf(where, "\t-h          This usage statement.\n");
-
-	if (getuid() == 0) {
-		fprintf(where, "\t-S <type>   What type of session to create (Aqua, tty or X11).\n");
-		fprintf(where, "\t-U <user>   Which user to create the session as.\n");
-	}
-
-	if (where == stdout) {
-		exit(EXIT_SUCCESS);
-	}
-}
-
 int
 _fd(int fd)
 {
@@ -395,46 +251,7 @@
 void
 prep_shutdown_log_dir(void)
 {
-	struct stat sb;
-	struct dirent *de;
-	DIR *thedir = NULL;
-
-	if (!launchd_assumes(mkdir(SHUTDOWN_LOG_DIR, S_IRWXU) != -1 || errno == EEXIST)) {
-		goto out;
-	}
-
-	if (!launchd_assumes(lstat(SHUTDOWN_LOG_DIR, &sb) != -1)) {
-		goto out;
-	}
-
-	if (!launchd_assumes(S_ISDIR(sb.st_mode))) {
-		goto out;
-	}
-
-	if (!launchd_assumes(chdir(SHUTDOWN_LOG_DIR) != -1)) {
-		goto out;
-	}
-
-	if (!launchd_assumes((thedir = opendir(".")) != NULL)) {
-		goto out;
-	}
-
-	while ((de = readdir(thedir))) {
-		if (strcmp(de->d_name, ".") == 0) {
-			continue;
-		} else if (strcmp(de->d_name, "..") == 0) {
-			continue;
-		} else {
-			launchd_assumes(remove(de->d_name) != -1);
-		}
-	}
-
-out:
-	if (thedir) {
-		closedir(thedir);
-	}
-
-	chdir("/");
+	launchd_assumes(mkdir(SHUTDOWN_LOG_DIR, S_IRWXU) != -1 || errno == EEXIST);
 }
 
 void
@@ -457,8 +274,6 @@
 		debug_shutdown_hangs = true;
 	}
 
-	rlcj = NULL;
-
 	launchd_assert(jobmgr_shutdown(root_jobmgr) != NULL);
 }
 
@@ -476,24 +291,6 @@
 	kill(-1, SIGKILL);
 }
 
-static void signal_callback(void *obj __attribute__((unused)), struct kevent *kev)
-{
-	syslog(LOG_DEBUG, "Received signal: %u", kev->ident);
-
-	switch (kev->ident) {
-	case SIGHUP:
-		if (rlcj) {
-			rlcj = job_dispatch(rlcj, true);
-		}
-		break;
-	case SIGTERM:
-		launchd_shutdown();
-		break;
-	default:
-		break;
-	} 
-}
-
 void
 launchd_SessionCreate(void)
 {
@@ -525,30 +322,6 @@
 	}
 }
 
-launch_data_t                   
-launchd_setstdio(int d, launch_data_t o)
-{
-	launch_data_t resp = launch_data_new_errno(0);
-
-	if (launch_data_get_type(o) == LAUNCH_DATA_STRING) {
-		switch (d) {
-		case STDOUT_FILENO:
-			jobmgr_set_stdout(root_jobmgr, launch_data_get_string(o));
-			break;
-		case STDERR_FILENO:
-			jobmgr_set_stderr(root_jobmgr, launch_data_get_string(o));
-			break;
-		default:
-			launch_data_set_errno(resp, EINVAL);
-			break;
-		}
-	} else {
-		launch_data_set_errno(resp, EINVAL);
-	}
-
-	return resp;
-}
-
 void
 batch_job_enable(bool e, struct conncb *c)
 {
@@ -662,26 +435,3 @@
 
 	syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u: %s", file, line, buf, saved_errno, test);
 }
-
-void
-launchd_post_kevent(void)
-{
-#if 0
-	if (shutdown_in_progress && jobmgr_is_idle(root_jobmgr)) {
-		shutdown_in_progress = false;
-
-		if (getpid() == 1) {
-			if (re_exec_in_single_user_mode) {
-				kill(-1, SIGKILL); /* One last time, just to clear the room */
-				launchd_assumes(execl("/sbin/launchd", "/sbin/launchd", "-s", NULL) != -1);
-			}
-		}
-	}
-#endif
-	if (getpid() == 1) {
-		if (rlcj && job_active(rlcj)) {
-			return;
-		}
-		init_pre_kevent();
-	}
-}

Modified: trunk/launchd/src/launchd.h
===================================================================
--- trunk/launchd/src/launchd.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -26,12 +26,11 @@
 #include "libbootstrap_public.h"
 #include "launchd_runtime.h"
 
-#define READCONF_LABEL "com.apple.launchd.readconfig"
+#define SHUTDOWN_LOG_DIR "/var/log/shutdown"
 
 struct kevent;
 struct conncb;
 
-extern sigset_t blocked_signals;
 extern bool debug_shutdown_hangs;
 extern bool network_up;
 extern int batch_disabler_count;
@@ -45,15 +44,9 @@
 void launchd_SessionCreate(void);
 void launchd_shutdown(void);
 void launchd_single_user(void);
-void launchd_post_kevent(void);
-pid_t launchd_fork(void);
 boolean_t launchd_mach_ipc_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply);
 
-void init_boot(bool sflag);
-void init_pre_kevent(void);
-
 void mach_start_shutdown(void);
-void mach_init_init(mach_port_t);
 
 int _fd(int fd);
 

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_core_logic.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -194,6 +194,7 @@
 static void semaphoreitem_ignore(job_t j, struct semaphoreitem *si);
 
 struct jobmgr_s {
+	kq_callback kqjobmgr_callback;
 	SLIST_ENTRY(jobmgr_s) sle;
 	SLIST_HEAD(, jobmgr_s) submgrs;
 	TAILQ_HEAD(, job_s) jobs;
@@ -201,8 +202,6 @@
 	mach_port_t req_port;
 	jobmgr_t parentmgr;
 	job_t anonj;
-	char *jm_stdout;
-	char *jm_stderr;
 	int reboot_flags;
 	unsigned int global_on_demand_cnt;
 	unsigned int sent_stop_to_hopeful_jobs:1, shutting_down:1;
@@ -212,7 +211,7 @@
 #define jobmgr_assumes(jm, e)      \
 	                (__builtin_expect(!(e), 0) ? jobmgr_log_bug(jm, __rcs_file_version__, __FILE__, __LINE__, #e), false : true)
 
-static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t checkin_port);
+static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag);
 static jobmgr_t jobmgr_parent(jobmgr_t jm);
 static jobmgr_t jobmgr_do_garbage_collection(jobmgr_t jm);
 static bool jobmgr_is_idle(jobmgr_t jm);
@@ -222,6 +221,7 @@
 static job_t jobmgr_new_anonymous(jobmgr_t jm);
 static job_t job_mig_intran2(jobmgr_t jm, mach_port_t p);
 static void job_export_all2(jobmgr_t jm, launch_data_t where);
+static void jobmgr_callback(void *obj, struct kevent *kev);
 static pid_t jobmgr_fork(jobmgr_t jm);
 static void jobmgr_setup_env_from_other_jobs(jobmgr_t jm);
 static struct machservice *jobmgr_lookup_service(jobmgr_t jm, const char *name, bool check_parent);
@@ -229,8 +229,6 @@
 static void jobmgr_log(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4)));
 /* static void jobmgr_log_error(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); */
 static void jobmgr_log_bug(jobmgr_t jm, const char *rcs_rev, const char *path, unsigned int line, const char *test);
-static char *jobmgr_get_stdout(jobmgr_t jm);
-static char *jobmgr_get_stderr(jobmgr_t jm);
 
 struct job_s {
 	kq_callback kqjob_callback;
@@ -255,7 +253,6 @@
 	char *workingdir;
 	char *username;
 	char *groupname;
-	char *stdinpath;
 	char *stdoutpath;
 	char *stderrpath;
 	pid_t p;
@@ -311,6 +308,7 @@
 static void job_callback_timer(job_t j, void *ident);
 static void job_callback_read(job_t j, int ident);
 static launch_data_t job_export2(job_t j, bool subjobs);
+static job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv);
 static job_t job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d);
 static job_t job_new_via_mach_init(job_t j, const char *cmd, uid_t uid, bool ond);
 static const char *job_prog(job_t j);
@@ -577,14 +575,6 @@
 		jobmgr_assumes(jm, launchd_mport_close_recv(jm->jm_port) == KERN_SUCCESS);
 	}
 
-	if (jm->jm_stdout) {
-		free(jm->jm_stdout);
-	}
-
-	if (jm->jm_stderr) {
-		free(jm->jm_stderr);
-	}
-
 	if (jm->parentmgr) {
 		SLIST_REMOVE(&jm->parentmgr->submgrs, jm, jobmgr_s, sle);
 	} else if (getpid() == 1) {
@@ -677,9 +667,6 @@
 	if (j->groupname) {
 		free(j->groupname);
 	}
-	if (j->stdinpath) {
-		free(j->stdinpath);
-	}
 	if (j->stdoutpath) {
 		free(j->stdoutpath);
 	}
@@ -797,7 +784,7 @@
 	/* preflight the string so we know how big it is */
 	snprintf(buf, sizeof(buf), "%s.%s", sizeof(void *) == 8 ? "0xdeadbeeffeedface" : "0xbabecafe", basename((char *)argv[0]));
 
-	jr = job_new(j->mgr, buf, NULL, argv, NULL);
+	jr = job_new(j->mgr, buf, NULL, argv);
 
 	free(argv);
 
@@ -852,7 +839,7 @@
 		return NULL;
 	}
 
-	jr = job_new(j->mgr, label, path, argv, NULL);
+	jr = job_new(j->mgr, label, path, argv);
 
 	if (!jr) {
 		return NULL;
@@ -907,7 +894,7 @@
 
 	snprintf(newlabel, sizeof(newlabel), "%u.anonymous", MACH_PORT_INDEX(jm->jm_port));
 
-	if ((jr = job_new(jm, newlabel, procname, NULL, NULL))) {
+	if ((jr = job_new(jm, newlabel, procname, NULL))) {
 		jr->anonymous = true;
 	}
 
@@ -915,14 +902,15 @@
 }
 
 job_t 
-job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv, const char *stdinpath)
+job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv)
 {
-	char compile_time_assert[offsetof(struct job_s, kqjob_callback) == 0 ? 1 : -1] __attribute__((unused));
 	const char *const *argv_tmp = argv;
 	char *co;
 	int i, cc = 0;
 	job_t j;
 
+	launchd_assert(offsetof(struct job_s, kqjob_callback) == 0);
+
 	if (jm->shutting_down) {
 		errno = EINVAL;
 		return NULL;
@@ -956,13 +944,6 @@
 		}
 	}
 
-	if (stdinpath) {
-		j->stdinpath = strdup(stdinpath);
-		if (!job_assumes(j, j->stdinpath != NULL)) {
-			goto out_bad;
-		}
-	}
-
 	if (argv) {
 		while (*argv_tmp++)
 			j->argc++;
@@ -996,9 +977,6 @@
 	if (j->prog) {
 		free(j->prog);
 	}
-	if (j->stdinpath) {
-		free(j->stdinpath);
-	}
 	free(j);
 
 	return NULL;
@@ -1488,7 +1466,7 @@
 		return NULL;
 	}
 
-	if ((j = job_new(root_jobmgr, label, prog, argv, NULL))) {
+	if ((j = job_new(root_jobmgr, label, prog, argv))) {
 		launch_data_dict_iterate(pload, job_import_keys, j);
 	}
 
@@ -1801,7 +1779,7 @@
 	j->sent_sigkill = true;
 
 	job_assumes(j, kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER,
-				EV_ADD|EV_ONESHOT, NOTE_SECONDS, LAUNCHD_SIGKILL_TIMEOUT, j) != -1);
+				EV_ADD, NOTE_SECONDS, LAUNCHD_SIGKILL_TIMEOUT, j) != -1);
 }
 
 void
@@ -1832,8 +1810,15 @@
 		job_dispatch(j, true);
 	} else if (&j->exit_timeout == ident) {
 		if (j->sent_sigkill) {
-			job_log(j, LOG_ERR, "Did not die after sending SIGKILL %u seconds ago...", LAUNCHD_SIGKILL_TIMEOUT);
-			if (debug_shutdown_hangs) {
+			struct timeval tvd, tve;
+			double delta;
+
+			job_assumes(j, gettimeofday(&tve, NULL) != -1);
+			timersub(&tve, &j->sent_sigterm_time,  &tvd);
+			delta = (double)tvd.tv_sec + (double)tvd.tv_usec / (double)1000000;
+			delta -= (double)j->exit_timeout;
+			job_log(j, LOG_ERR, "Did not die after sending SIGKILL %f seconds ago...", delta);
+			if (debug_shutdown_hangs && delta > 60) {
 				job_assumes(j, host_reboot(mach_host_self(), HOST_REBOOT_DEBUGGER) == KERN_SUCCESS);
 			}
 		} else {
@@ -1857,6 +1842,25 @@
 }
 
 void
+jobmgr_callback(void *obj, struct kevent *kev)
+{
+	jobmgr_t jm = obj;
+
+	switch (kev->filter) {
+	case EVFILT_SIGNAL:
+		switch (kev->ident) {
+		case SIGTERM:
+			return launchd_shutdown();
+		default:
+			return (void)jobmgr_assumes(jm, false);
+		}
+		break;
+	default:
+		return (void)jobmgr_assumes(jm, false);
+	}
+}
+
+void
 job_callback(void *obj, struct kevent *kev)
 {
 	job_t j = obj;
@@ -1915,10 +1919,7 @@
 	j->sent_sigterm_time.tv_sec = 0;
 	j->sent_sigterm_time.tv_usec = 0;
 
-	/* FIXME, using stdinpath is a hack for re-reading the conf file */
-	if (j->stdinpath) {
-	       sipc = true;
-	} else if (!j->legacy_mach_job) {
+	if (!j->legacy_mach_job) {
 		sipc = (!SLIST_EMPTY(&j->sockets) || !SLIST_EMPTY(&j->machservices));
 	}
 
@@ -2056,6 +2057,10 @@
 		job_assumes(j, binpref_out_cnt == j->j_binpref_cnt);
 	}
 
+	for (i = 1; i < NSIG; i++) {
+		signal(i, SIG_DFL);
+	}
+
 	if (j->prog) {
 		errno = posix_spawn(&junk_pid, j->inetcompat ? file2exec : j->prog, NULL, &spattr, (char *const*)argv, environ);
 		job_log_error(j, LOG_ERR, "posix_spawn(\"%s\", ...)", j->prog);
@@ -2262,9 +2267,8 @@
 		umask(j->mask);
 	}
 
-	job_setup_fd(j, STDIN_FILENO,  j->stdinpath,  O_RDONLY);
-	job_setup_fd(j, STDOUT_FILENO, j->stdoutpath ? j->stdoutpath : jobmgr_get_stdout(j->mgr), O_WRONLY|O_APPEND|O_CREAT);
-	job_setup_fd(j, STDERR_FILENO, j->stderrpath ? j->stderrpath : jobmgr_get_stderr(j->mgr), O_WRONLY|O_APPEND|O_CREAT);
+	job_setup_fd(j, STDOUT_FILENO, j->stdoutpath, O_WRONLY|O_APPEND|O_CREAT);
+	job_setup_fd(j, STDERR_FILENO, j->stderrpath, O_WRONLY|O_APPEND|O_CREAT);
 
 	jobmgr_setup_env_from_other_jobs(j->mgr);
 
@@ -2278,43 +2282,10 @@
 void
 job_setup_fd(job_t j, int target_fd, const char *path, int flags)
 {
-#if 0
-	char newpath[PATH_MAX];
-#endif
 	int fd;
 
 	if (!path) {
-#if 0
-		switch (target_fd) {
-		case STDOUT_FILENO:
-		case STDERR_FILENO:
-			flags |= O_TRUNC;
-			break;
-		default:
-			return;
-		}
-
-		if (getuid() == 0) {
-			snprintf(newpath, sizeof(newpath), "/var/log/launchd");
-		} else {
-			struct passwd *pwe;
-
-			if (!job_assumes(j, (pwe = getpwuid(getuid())) != NULL)) {
-				return;
-			}
-
-			snprintf(newpath, sizeof(newpath), "%s/Library/Logs/launchd", pwe->pw_dir);
-		}
-
-		mkdir(newpath, ACCESSPERMS);
-
-		strcat(newpath, "/");
-		strcat(newpath, j->label);
-
-		path = newpath;
-#else
 		return;
-#endif
 	}
 
 	if ((fd = open(path, flags|O_NOCTTY, DEFFILEMODE)) == -1) {
@@ -2427,10 +2398,10 @@
 void
 job_logv(job_t j, int pri, int err, const char *msg, va_list ap)
 {
-	char newmsg[10000];
+	char *newmsg;
 	char *newlabel;
 	int oldmask = 0;
-	size_t i, o, jlabel_len = strlen(j->label);
+	size_t i, o, jlabel_len = strlen(j->label), newmsgsz;
 
 	/*
 	 * Hack: If bootstrap_port is set, we must be on the child side of a
@@ -2442,6 +2413,8 @@
 	}
 
 	newlabel = alloca((jlabel_len + 1) * 2);
+	newmsgsz = (jlabel_len + 1) * 2 + strlen(msg) + 100;
+	newmsg = alloca(newmsgsz);
 
 	for (i = 0, o = 0; i < jlabel_len; i++, o++) {
 		if (j->label[i] == '%') {
@@ -2453,16 +2426,16 @@
 	newlabel[o] = '\0';
 
 	if (err) {
-		snprintf(newmsg, sizeof(newmsg), "%s: %s: %s", newlabel, msg, strerror(err));
+		snprintf(newmsg, newmsgsz, "%s: %s: %s", newlabel, msg, strerror(err));
 	} else {
-		snprintf(newmsg, sizeof(newmsg), "%s: %s", newlabel, msg);
+		snprintf(newmsg, newmsgsz, "%s: %s", newlabel, msg);
 	}
 
 	if (j->debug) {
 		oldmask = setlogmask(LOG_UPTO(LOG_DEBUG));
 	}
 
-	vsyslog(pri, newmsg, ap);
+	jobmgr_logv(j->mgr, pri, 0, newmsg, ap);
 
 	if (j->debug) {
 		setlogmask(oldmask);
@@ -2514,9 +2487,34 @@
 void
 jobmgr_logv(jobmgr_t jm, int pri, int err, const char *msg, va_list ap)
 {
-	if (launchd_assumes(jm->anonj)) {
-		job_logv(jm->anonj, pri, err, msg, ap);
+	char *newmsg;
+	char *newname;
+	size_t i, o, jmname_len = strlen(jm->name), newmsgsz;
+
+	newname = alloca((jmname_len + 1) * 2);
+	newmsgsz = (jmname_len + 1) * 2 + strlen(msg) + 100;
+	newmsg = alloca(newmsgsz);
+
+	for (i = 0, o = 0; i < jmname_len; i++, o++) {
+		if (jm->name[i] == '%') {
+			newname[o] = '%';
+			o++;
+		}
+		newname[o] = jm->name[i];
 	}
+	newname[o] = '\0';
+
+	if (err) {
+		snprintf(newmsg, newmsgsz, "%s: %s: %s", newname, msg, strerror(err));
+	} else {
+		snprintf(newmsg, newmsgsz, "%s: %s", newname, msg);
+	}
+
+	if (jm->parentmgr) {
+		jobmgr_logv(jm->parentmgr, pri, 0, newmsg, ap);
+	} else {
+		vsyslog(pri, newmsg, ap);
+	}
 }
 
 void    
@@ -3045,20 +3043,12 @@
 }
 
 pid_t
-launchd_fork(void)
-{
-	return jobmgr_fork(root_jobmgr);
-}
-
-pid_t
 jobmgr_fork(jobmgr_t jm)
 {
 	mach_port_t p = jm->jm_port;
 	pid_t r = -1;
 	int saved_errno;
 
-	sigprocmask(SIG_BLOCK, &blocked_signals, NULL);
-
 	jobmgr_assumes(jm, launchd_mport_make_send(p) == KERN_SUCCESS);
 	jobmgr_assumes(jm, launchd_set_bport(p) == KERN_SUCCESS);
 	jobmgr_assumes(jm, launchd_mport_deallocate(p) == KERN_SUCCESS);
@@ -3069,18 +3059,8 @@
 
 	if (r != 0) {
 		jobmgr_assumes(jm, launchd_set_bport(MACH_PORT_NULL) == KERN_SUCCESS);
-	} else if (r == 0) {
-		size_t i;
-
-		for (i = 0; i < NSIG; i++) {
-			if (sigismember(&blocked_signals, i)) {
-				signal(i, SIG_DFL);
-			}
-		}
 	}
 
-	sigprocmask(SIG_UNBLOCK, &blocked_signals, NULL);
-	
 	errno = saved_errno;
 	return r;
 }
@@ -3360,50 +3340,6 @@
 	return true;
 }
 
-void
-jobmgr_set_stdout(jobmgr_t jm, const char *what)
-{
-	if (jm->jm_stdout) {
-		free(jm->jm_stdout);
-	}
-
-	jm->jm_stdout = strdup(what);
-}
-
-void
-jobmgr_set_stderr(jobmgr_t jm, const char *what)
-{
-	if (jm->jm_stderr) {
-		free(jm->jm_stderr);
-	}
-
-	jm->jm_stderr = strdup(what);
-}
-
-char *
-jobmgr_get_stdout(jobmgr_t jm)
-{
-	if (jm->jm_stdout) {
-		return jm->jm_stdout;
-	} else if (jm->parentmgr == NULL) {
-		return NULL;
-	}
-
-	return jobmgr_get_stdout(jm->parentmgr);
-}
-
-char *
-jobmgr_get_stderr(jobmgr_t jm)
-{
-	if (jm->jm_stderr) {
-		return jm->jm_stderr;
-	} else if (jm->parentmgr == NULL) {
-		return NULL;
-	}
-
-	return jobmgr_get_stderr(jm->parentmgr);
-}
-
 jobmgr_t 
 jobmgr_parent(jobmgr_t jm)
 {
@@ -3424,25 +3360,33 @@
 }
 
 jobmgr_t 
-jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t checkin_port)
+jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag)
 {
+	const char *bootstrap_tool[] = { "/bin/launchctl", "bootstrap", NULL, NULL };
 	mach_msg_size_t mxmsgsz;
+	job_t bootstrapper = NULL;
 	jobmgr_t jmr;
 
-	if (requestorport == MACH_PORT_NULL) {
-		if (jm) {
-			jobmgr_log(jm, LOG_ERR, "Mach sub-bootstrap create request requires a requester port");
-		}
+	if (sflag) {
+		bootstrap_tool[2] = "-s";
+	}
+
+	launchd_assert(offsetof(struct jobmgr_s, kqjobmgr_callback) == 0);
+
+	if (jm && requestorport == MACH_PORT_NULL) {
+		jobmgr_log(jm, LOG_ERR, "Mach sub-bootstrap create request requires a requester port");
 		return NULL;
 	}
 
-	jmr = calloc(1, sizeof(struct jobmgr_s) + strlen("LoginWindow") + 1);
+	jmr = calloc(1, sizeof(struct jobmgr_s) + 30);
 	
 	if (jmr == NULL) {
 		return NULL;
 	}
 
 	TAILQ_INIT(&jmr->jobs);
+	jmr->kqjobmgr_callback = jobmgr_callback;
+	strcpy(jmr->name, "In-utero");
 
 	jmr->req_port = requestorport;
 
@@ -3450,17 +3394,44 @@
 		SLIST_INSERT_HEAD(&jm->submgrs, jmr, sle);
 	}
 
-	if (!jobmgr_assumes(jmr, launchd_mport_notify_req(jmr->req_port, MACH_NOTIFY_DEAD_NAME) == KERN_SUCCESS)) {
+	if (jm && !jobmgr_assumes(jmr, launchd_mport_notify_req(jmr->req_port, MACH_NOTIFY_DEAD_NAME) == KERN_SUCCESS)) {
 		goto out_bad;
 	}
 
-	if (checkin_port != MACH_PORT_NULL) {
-		jmr->jm_port = checkin_port;
+	if (transfer_port != MACH_PORT_NULL) {
+		jobmgr_assumes(jmr, jm != NULL);
+		jmr->jm_port = transfer_port;
+	} else if (!jm && getpid() != 1) {
+		char *trusted_fd = getenv(LAUNCHD_TRUSTED_FD_ENV);
+		name_t service_buf;
+
+		snprintf(service_buf, sizeof(service_buf), "com.apple.launchd.peruser.%u", getuid());
+
+		if (!jobmgr_assumes(jmr, bootstrap_check_in(bootstrap_port, service_buf, &jmr->jm_port) == 0)) {
+			goto out_bad;
+		}
+
+		if (trusted_fd) {
+			int dfd, lfd = strtol(trusted_fd, NULL, 10);
+
+			if ((dfd = dup(lfd)) >= 0) {
+				jobmgr_assumes(jmr, close(dfd) != -1);
+				jobmgr_assumes(jmr, close(lfd) != -1);
+			}
+
+			unsetenv(LAUNCHD_TRUSTED_FD_ENV);
+		}
+
+		inherited_bootstrap_port = bootstrap_port;
+		/* cut off the Libc cache, we don't want to deadlock against ourself */
+		bootstrap_port = MACH_PORT_NULL;
+		/* We set this explicitly as we start each child */
+		launchd_assert(launchd_set_bport(MACH_PORT_NULL) == KERN_SUCCESS);
 	} else if (!jobmgr_assumes(jmr, launchd_mport_create_recv(&jmr->jm_port) == KERN_SUCCESS)) {
 		goto out_bad;
 	}
 
-	snprintf(jmr->name, strlen(jmr->name) + 1, "%u", MACH_PORT_INDEX(jmr->jm_port));
+	sprintf(jmr->name, "%u", MACH_PORT_INDEX(jmr->jm_port));
 
 	/* Sigh... at the moment, MIG has maxsize == sizeof(reply union) */
 	mxmsgsz = sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem);
@@ -3472,16 +3443,20 @@
 		goto out_bad;
 	}
 
-	if (jm) {
-		jobmgr_log(jm, LOG_DEBUG, "Mach sub-bootstrap created: %s", jmr->name);
-	}
+	jobmgr_assumes(jmr, (jmr->anonj = jobmgr_new_anonymous(jmr)) != NULL);
 
-	jmr->anonj = jobmgr_new_anonymous(jmr);
+	bootstrapper = job_new(jmr, "com.apple.launchctld", NULL, bootstrap_tool);
 
-	jobmgr_assumes(jmr, jmr->anonj != NULL);
+	if (!jm) {
+		jobmgr_assumes(jmr, kevent_mod(SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, jmr) != -1);
+	}
 
-	jobmgr_log(jmr, LOG_DEBUG, "Created job manager");
+	jobmgr_log(jmr, LOG_DEBUG, "Created job manager%s%s", jm ? " with parent: " : ".", jm ? jm->name : "");
 
+	if (!jm && jobmgr_assumes(jmr, bootstrapper != NULL)) {
+		jobmgr_assumes(jmr, job_dispatch(bootstrapper, true) != NULL);
+	}
+
 	return jmr;
 
 out_bad:
@@ -3759,9 +3734,11 @@
 	}
 	
 	snprintf(pidstr, sizeof(pidstr), "%u", j->p);
-	snprintf(logfile, sizeof(logfile), "/var/log/shutdown/%s-%u.sample.txt", j->label, j->p);
+	snprintf(logfile, sizeof(logfile), SHUTDOWN_LOG_DIR "/%s-%u.sample.txt", j->label, j->p);
 
-	job_assumes(j, mkdir("/var/log/shutdown", S_IRWXU) != -1 || errno == EEXIST);
+	if (!job_assumes(j, unlink(logfile) != -1 || errno == ENOENT)) {
+		goto out;
+	}
 
 	/*
 	 * This will stall launchd for as long as the 'sample' tool runs.
@@ -3777,6 +3754,8 @@
 		goto out;
 	}
 
+	sync();
+
 	if (!job_assumes(j, WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0)) {
 		goto out;
 	}
@@ -4194,7 +4173,7 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	ipc_server_init(NULL, 0);
+	ipc_server_init();
 
 	if (!sockpath) {
 		return BOOTSTRAP_NO_MEMORY;
@@ -4262,7 +4241,7 @@
 
 		sprintf(lbuf, "com.apple.launchd.peruser.%u", which_user);
 
-		ji = job_new(root_jobmgr, lbuf, "/sbin/launchd", NULL, NULL);
+		ji = job_new(root_jobmgr, lbuf, "/sbin/launchd", NULL);
 
 		if (ji == NULL) {
 			return BOOTSTRAP_NO_MEMORY;
@@ -4562,7 +4541,7 @@
 
 	launchd_assert(l2l_name_cnt == l2l_port_cnt);
 
-	if ((jmr = jobmgr_new(j->mgr, reqport, rcvright)) == NULL) {
+	if ((jmr = jobmgr_new(j->mgr, reqport, rcvright, false)) == NULL) {
 		kr = BOOTSTRAP_NO_MEMORY;
 		goto out;
 	}
@@ -4691,7 +4670,7 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	if ((jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL)) == NULL) {
+	if ((jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false)) == NULL) {
 		if (requestorport == MACH_PORT_NULL) {
 			return BOOTSTRAP_NOT_PRIVILEGED;
 		}
@@ -4864,30 +4843,7 @@
 }
 
 void
-mach_init_init(mach_port_t checkin_port)
+jobmgr_init(bool sflag)
 {
-	job_t ji, anon_job = NULL;
-
-	launchd_assert((root_jobmgr = jobmgr_new(NULL, mach_task_self(), checkin_port)) != NULL);
-
-	TAILQ_FOREACH(ji, &root_jobmgr->jobs, sle) {
-		if (ji->anonymous) {
-			anon_job = ji;
-			break;
-		}
-	}
-
-	launchd_assert(anon_job != NULL);
-
-	launchd_assert(launchd_get_bport(&inherited_bootstrap_port) == KERN_SUCCESS);
-
-	if (getpid() != 1) {
-		launchd_assumes(inherited_bootstrap_port != MACH_PORT_NULL);
-	}
-
-	/* We set this explicitly as we start each child */
-	launchd_assert(launchd_set_bport(MACH_PORT_NULL) == KERN_SUCCESS);
-
-	/* cut off the Libc cache, we don't want to deadlock against ourself */
-	bootstrap_port = MACH_PORT_NULL;
+	launchd_assert((root_jobmgr = jobmgr_new(NULL, MACH_PORT_NULL, MACH_PORT_NULL, sflag)) != NULL);
 }

Modified: trunk/launchd/src/launchd_core_logic.h
===================================================================
--- trunk/launchd/src/launchd_core_logic.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_core_logic.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -28,8 +28,7 @@
 
 extern jobmgr_t root_jobmgr;
 
-void jobmgr_set_stdout(jobmgr_t jm, const char *what);
-void jobmgr_set_stderr(jobmgr_t jm, const char *what);
+void jobmgr_init(bool);
 jobmgr_t jobmgr_shutdown(jobmgr_t jm);
 void jobmgr_dispatch_all_semaphores(jobmgr_t jm);
 job_t jobmgr_find(jobmgr_t jm, const char *label);
@@ -39,7 +38,6 @@
 
 launch_data_t job_export_all(void);
 
-job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv, const char *stdinpath);
 job_t job_dispatch(job_t j, bool kickstart); /* returns j on success, NULL on job removal */
 bool job_active(job_t j);
 launch_data_t job_export(job_t j);

Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_runtime.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -73,6 +73,7 @@
 
 static void *mport_demand_loop(void *arg);
 static void *kqueue_demand_loop(void *arg);
+static void log_kevent_struct(int level, struct kevent *kev);
 
 static void async_callback(void);
 static kq_callback kqasync_callback = (kq_callback)async_callback;
@@ -143,7 +144,51 @@
 	return NULL;
 }
 
-static void
+const char *
+signal_to_C_name(unsigned int sig)
+{
+	static char unknown[25];
+
+#define SIG2CASE(sg)	case sg: return #sg
+
+	switch (sig) {
+	SIG2CASE(SIGHUP);
+	SIG2CASE(SIGINT);
+	SIG2CASE(SIGQUIT);
+	SIG2CASE(SIGILL);
+	SIG2CASE(SIGTRAP);
+	SIG2CASE(SIGABRT);
+	SIG2CASE(SIGFPE);
+	SIG2CASE(SIGKILL);
+	SIG2CASE(SIGBUS);
+	SIG2CASE(SIGSEGV);
+	SIG2CASE(SIGSYS);
+	SIG2CASE(SIGPIPE);
+	SIG2CASE(SIGALRM);
+	SIG2CASE(SIGTERM);
+	SIG2CASE(SIGURG);
+	SIG2CASE(SIGSTOP);
+	SIG2CASE(SIGTSTP);
+	SIG2CASE(SIGCONT);
+	SIG2CASE(SIGCHLD);
+	SIG2CASE(SIGTTIN);
+	SIG2CASE(SIGTTOU);
+	SIG2CASE(SIGIO);
+	SIG2CASE(SIGXCPU);
+	SIG2CASE(SIGXFSZ);
+	SIG2CASE(SIGVTALRM);
+	SIG2CASE(SIGPROF);
+	SIG2CASE(SIGWINCH);
+	SIG2CASE(SIGINFO);
+	SIG2CASE(SIGUSR1);
+	SIG2CASE(SIGUSR2);
+	default:
+		snprintf(unknown, sizeof(unknown), "%u", sig);
+		return unknown;
+	}
+}
+
+void
 log_kevent_struct(int level, struct kevent *kev)
 {
 	const char *filter_str;
@@ -245,42 +290,7 @@
 		break;
 	case EVFILT_SIGNAL:
 		filter_str = "EVFILT_SIGNAL";
-		switch (kev->ident) {
-#define SIG2CASE(sg)	case sg: sprintf(ident_buf, #sg); break
-		SIG2CASE(SIGHUP);
-		SIG2CASE(SIGINT);
-		SIG2CASE(SIGQUIT);
-		SIG2CASE(SIGILL);
-		SIG2CASE(SIGTRAP);
-		SIG2CASE(SIGABRT);
-		SIG2CASE(SIGFPE);
-		SIG2CASE(SIGKILL);
-		SIG2CASE(SIGBUS);
-		SIG2CASE(SIGSEGV);
-		SIG2CASE(SIGSYS);
-		SIG2CASE(SIGPIPE);
-		SIG2CASE(SIGALRM);
-		SIG2CASE(SIGTERM);
-		SIG2CASE(SIGURG);
-		SIG2CASE(SIGSTOP);
-		SIG2CASE(SIGTSTP);
-		SIG2CASE(SIGCONT);
-		SIG2CASE(SIGCHLD);
-		SIG2CASE(SIGTTIN);
-		SIG2CASE(SIGTTOU);
-		SIG2CASE(SIGIO);
-		SIG2CASE(SIGXCPU);
-		SIG2CASE(SIGXFSZ);
-		SIG2CASE(SIGVTALRM);
-		SIG2CASE(SIGPROF);
-		SIG2CASE(SIGWINCH);
-		SIG2CASE(SIGINFO);
-		SIG2CASE(SIGUSR1);
-		SIG2CASE(SIGUSR2);
-		default:
-			sprintf(ident_buf, "%ld", kev->ident);
-			break;
-		}
+		strcpy(ident_buf, signal_to_C_name(kev->ident));
 		break;
 	case EVFILT_TIMER:
 		filter_str = "EVFILT_TIMER";
@@ -404,8 +414,6 @@
 #endif
 	}
 
-	launchd_post_kevent();
-
 	return 0;
 }
 

Modified: trunk/launchd/src/launchd_runtime.h
===================================================================
--- trunk/launchd/src/launchd_runtime.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_runtime.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -45,7 +45,7 @@
 #define launchd_blame(e, b)	\
 	(__builtin_expect(!(e), 0) ? syslog(LOG_DEBUG, "Encountered bug: %d", b), false : true)
 
-#define launchd_assert(e)	launchd_assumes(e) ? true : abort();
+#define launchd_assert(e)	if (__builtin_constant_p(e)) { char __compile_time_assert__[e ? 1 : -1] __attribute__((unused)); } else if (!launchd_assumes(e)) { abort(); }
 
 void _log_launchd_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test);
 
@@ -64,6 +64,7 @@
 kern_return_t runtime_remove_mport(mach_port_t name);
 bool runtime_get_caller_creds(struct ldcred *ldc);
 
+const char *signal_to_C_name(unsigned int sig);
 
 int kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata);
 

Modified: trunk/launchd/src/launchd_unix_ipc.c
===================================================================
--- trunk/launchd/src/launchd_unix_ipc.c	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_unix_ipc.c	2007-02-19 02:03:20 UTC (rev 23082)
@@ -88,22 +88,17 @@
 }
 
 void
-ipc_server_init(int *fds, size_t fd_cnt)
+ipc_server_init(void)
 {
 	struct sockaddr_un sun;
 	mode_t oldmask;
 	int r, fd = -1;
 	char ourdir[1024];
-	size_t i;
 
 	if (ipc_inited) {
 		return;
 	}
 
-	if (fds) {
-		goto add_fds;
-	}
-
 	memset(&sun, 0, sizeof(sun));
 	sun.sun_family = AF_UNIX;
 
@@ -163,27 +158,17 @@
 		goto out_bad;
 	}
 
-add_fds:
-	if (fds) {
-		for (i = 0; i < fd_cnt; i++) {
-			if (kevent_mod(fds[i], EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
-				syslog(LOG_ERR, "kevent_mod(%d, EVFILT_READ): %m", fds[i]);
-				goto out_bad;
-			}
-		}
-	} else if (kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
+	if (kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
 		syslog(LOG_ERR, "kevent_mod(\"thesocket\", EVFILT_READ): %m");
 		goto out_bad;
 	}
 
 	ipc_inited = true;
 
-	if (!fds) {
-		sockdir = strdup(ourdir);
-		sockpath = strdup(sun.sun_path);
-		ipc_self = getpid();
-		atexit(ipc_clean_up);
-	}
+	sockdir = strdup(ourdir);
+	sockpath = strdup(sun.sun_path);
+	ipc_self = getpid();
+	atexit(ipc_clean_up);
 
 out_bad:
 	if (!ipc_inited && fd != -1) {
@@ -446,10 +431,6 @@
 		resp = launch_data_new_integer(setlogmask(launch_data_get_integer(data)));
 	} else if (!strcmp(cmd, LAUNCH_KEY_SETUMASK)) {
 		resp = launch_data_new_integer(umask(launch_data_get_integer(data)));
-	} else if (!strcmp(cmd, LAUNCH_KEY_SETSTDOUT)) {
-		resp = launchd_setstdio(STDOUT_FILENO, data);
-	} else if (!strcmp(cmd, LAUNCH_KEY_SETSTDERR)) {
-		resp = launchd_setstdio(STDERR_FILENO, data);
 	} else if (!strcmp(cmd, LAUNCH_KEY_BATCHCONTROL)) {
 		batch_job_enable(launch_data_get_bool(data), rmc->c);
 		resp = launch_data_new_errno(0);

Modified: trunk/launchd/src/launchd_unix_ipc.h
===================================================================
--- trunk/launchd/src/launchd_unix_ipc.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/launchd_unix_ipc.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -43,6 +43,6 @@
 void ipc_revoke_fds(launch_data_t o);
 void ipc_close_fds(launch_data_t o);
 void ipc_clean_up(void);
-void ipc_server_init(int *, size_t);
+void ipc_server_init(void);
 
 #endif

Modified: trunk/launchd/src/liblaunch_private.h
===================================================================
--- trunk/launchd/src/liblaunch_private.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/liblaunch_private.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -31,8 +31,6 @@
 #define LAUNCH_KEY_GETUSERENVIRONMENT	"GetUserEnvironment"
 #define LAUNCH_KEY_SETUSERENVIRONMENT	"SetUserEnvironment"
 #define LAUNCH_KEY_UNSETUSERENVIRONMENT	"UnsetUserEnvironment"
-#define LAUNCH_KEY_SETSTDOUT		"SetStandardOut"
-#define LAUNCH_KEY_SETSTDERR		"SetStandardError"
 #define LAUNCH_KEY_SHUTDOWN		"Shutdown"
 #define LAUNCH_KEY_SINGLEUSER		"SingleUser"
 #define LAUNCH_KEY_GETRESOURCELIMITS	"GetResourceLimits"
@@ -76,7 +74,7 @@
  * This returns 1 on success (it used to return otherwise), and -1 on failure.
  */
 #define	LOAD_ONLY_SAFEMODE_LAUNCHAGENTS	1
-pid_t create_and_switch_to_per_session_launchd(const char *login, int flags, ...);
+pid_t create_and_switch_to_per_session_launchd(const char * /* loginname */, int flags, ...);
 
 /* Also for LoginWindow.
  *

Modified: trunk/launchd/src/libvproc_public.h
===================================================================
--- trunk/launchd/src/libvproc_public.h	2007-02-18 18:48:19 UTC (rev 23081)
+++ trunk/launchd/src/libvproc_public.h	2007-02-19 02:03:20 UTC (rev 23082)
@@ -26,60 +26,11 @@
 
 typedef void * vproc_err_t;
 
-#if 0
-
 typedef void * vproc_t;
 typedef void * vprocmgr_t;
 
-/* By default, pass NULL for vprocmgr_t or vproc_t to get notions of self or "my manager" */
-
-vproc_err_t vprocmgr_create_vproc(vprocmgr_t vpm, launch_data_t the_vproc, vproc_t *vp);
-
-/* If creating multiple jobs, it is wise to create them atomically with respect to each other */
-vproc_err_t vprocmgr_create_vprocs(vprocmgr_t vpm, launch_data_t *the_vprocs, vproc_t *vp, size_t cnt);
-
-vproc_err_t vprocmgr_delete_vproc(vprocmgr_t vpm, vproc_t vp);
-
-/* The virtual process managers are arranged in a hierarchy */
-vproc_err_t vprocmgr_get_parent(vprocmgr_t vpm, vprocmgr_t *vpm_parent);
-
-vproc_err_t vprocmgr_get_all_vprocs(vprocmgr_t vpm, vproc_t **vps, size_t *vp_cnt);
-
-vproc_err_t vprocmgr_lookup_vproc(vprocmgr_t vpm, const char *label, vproc_t *vp);
-
-vproc_err_t vprocmgr_lookup_vprocmgr_for_user(vprocmgr_t vpm, const char *user, vprocmgr_t *vpm_out);
-
-vproc_err_t vprocmgr_lookup_mach_service(vprocmgr_t vpm, const char *service, mach_port_t *service_port);
-
-/* For controlling speculative and optimistical spawning of vprocs */
-vproc_err_t vprocmgr_set_force_on_demand(vproc_mgr_t vpm, bool force);
-vproc_err_t vprocmgr_get_force_on_demand(vproc_mgr_t vpm, bool *force);
-
-/* Only release those vprocmgr_t objects that returned from APIs. */
-vproc_err_t vprocmgr_release(vprocmgr_t vpm);
-
-
-/* Get meta-data and IPC handles from launchd */
-vproc_err_t vproc_checkin(launch_data_t *out);
-
-/* Get only meta-data from launchd */
-vproc_err_t vproc_get_info(vproc_t vp, launch_data_t *out);
-
-/* Lookup a Mach service amongst our peers and progenitors */
-vproc_err_t vproc_lookup_mach_service(vproc_t vp, const char *service, mach_port_t *service_port);
-
-/* Sending signals to a program that isn't running will return an error */
-vproc_err_t vproc_send_signal(vproc_t vp, int signum);
-
-/* Only release those vproc_t objects that returned from APIs. */
-vproc_err_t vproc_release(vproc_t vp);
-
-
-
 const char *vproc_strerror(vproc_err_t r);
 
-#endif
-
 __END_DECLS
 
 #endif

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20070218/47eb16e6/attachment.html


More information about the launchd-changes mailing list