[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