├── liblaunch ├── test │ ├── liblaunch.c │ ├── .gitignore │ ├── launch_data.c │ ├── launch_getters.c │ ├── cmocka.c │ ├── Makefile │ ├── liblaunch_test.h │ ├── getter_tests.c │ ├── byteswap_tests.c │ └── liblaunch_test.c ├── launchd.ops ├── Makefile ├── shims │ └── Availability.h ├── reboot2.h ├── launch_getters.c ├── byteswap.h ├── bootstrap_priv.h ├── launch_internal.h ├── vproc_internal.h ├── vproc.h ├── vproc_priv.h ├── launch_priv.h ├── libbootstrap.c ├── launch_data.c └── launch.h ├── wait4path ├── .gitignore ├── Makefile ├── wait4path.1 └── wait4path.c ├── .gitignore ├── launchctl ├── Makefile └── launchctl.1 ├── launchd ├── Makefile ├── helper.defs ├── ktrace.c ├── kill2.h ├── internal.defs ├── config.h ├── kill2.c ├── ktrace.h ├── ipc.h ├── job_forward.defs ├── launchd.h ├── log.h ├── job_types.defs ├── core.h ├── launchd.8 ├── job_reply.defs ├── protocol_jobmgr.defs ├── runtime.h ├── job.defs └── log.c ├── SystemStarter ├── StartupItemContext ├── hostconfig ├── com.apple.SystemStarter.plist ├── IPC.h ├── StartupItemContext.8 ├── SystemStarter.h ├── SystemStarter.8 ├── SystemStarterIPC.h ├── StartupItems.h └── IPC.c ├── .gitmodules ├── launchproxy ├── Makefile ├── launchproxy.8 └── launchproxy.c ├── t ├── assertions.sh └── wait4path-test.sh ├── xcscripts ├── SystemStarter-postflight.sh ├── liblaunch-postflight.sh ├── launchctl-postflight.sh └── launchd-postflight.sh ├── DEPENDS.md ├── Makefile ├── man ├── rc.8 └── launchd.conf.5 ├── ROADMAP.md ├── launchd.mk ├── README.md ├── rc ├── rc.common └── rc.netboot ├── support └── roundup └── COPYING /liblaunch/test/liblaunch.c: -------------------------------------------------------------------------------- 1 | ../liblaunch.c -------------------------------------------------------------------------------- /liblaunch/test/.gitignore: -------------------------------------------------------------------------------- 1 | liblaunch_test 2 | -------------------------------------------------------------------------------- /liblaunch/test/launch_data.c: -------------------------------------------------------------------------------- 1 | ../launch_data.c -------------------------------------------------------------------------------- /liblaunch/test/launch_getters.c: -------------------------------------------------------------------------------- 1 | ../launch_getters.c -------------------------------------------------------------------------------- /wait4path/.gitignore: -------------------------------------------------------------------------------- 1 | wait4path 2 | *.gz 3 | *.o 4 | -------------------------------------------------------------------------------- /liblaunch/test/cmocka.c: -------------------------------------------------------------------------------- 1 | ../../support/cmocka/src/cmocka.c -------------------------------------------------------------------------------- /liblaunch/launchd.ops: -------------------------------------------------------------------------------- 1 | < mach* > 2 | mach-per-user-lookup 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.po 4 | *.swp 5 | *.swo 6 | doc/ 7 | 8 | -------------------------------------------------------------------------------- /launchctl/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | PROG=launchctl 4 | 5 | .include "../launchd.mk" 6 | -------------------------------------------------------------------------------- /launchd/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | PROG=launchd 4 | MAN=launchd.8 5 | 6 | .include <../launchd.mk> 7 | -------------------------------------------------------------------------------- /wait4path/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | PROG=wait4path 4 | MAN=wait4path.1 5 | 6 | .include <../launchd.mk> 7 | -------------------------------------------------------------------------------- /SystemStarter/StartupItemContext: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | unset LAUNCHD_SOCKET 4 | 5 | exec launchctl bsexec / "$@" 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "support/cmocka"] 2 | path = support/cmocka 3 | url = git://git.cryptomilk.org/projects/cmocka.git 4 | -------------------------------------------------------------------------------- /SystemStarter/hostconfig: -------------------------------------------------------------------------------- 1 | # This file is going away 2 | 3 | AFPSERVER=-NO- 4 | AUTHSERVER=-NO- 5 | TIMESYNC=-NO- 6 | QTSSERVER=-NO- 7 | -------------------------------------------------------------------------------- /launchproxy/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | PROG=launchproxy 4 | MAN=launchproxy.8 5 | 6 | DPADD= ${LIBLAUNCH} 7 | LDADD= ${LIBLAUNCH} 8 | 9 | .include <../launchd.mk> 10 | -------------------------------------------------------------------------------- /t/assertions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | assert_empty() { 4 | test "$1" = "" 5 | } 6 | 7 | assert_success() { 8 | test $1 = 0 9 | } 10 | 11 | runit() { 12 | ${COMMAND} 2>&1 $@ 13 | } 14 | 15 | -------------------------------------------------------------------------------- /xcscripts/SystemStarter-postflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/System/Library/StartupItems 4 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/Library/StartupItems 5 | -------------------------------------------------------------------------------- /DEPENDS.md: -------------------------------------------------------------------------------- 1 | # Open Launchd Dependencies 2 | 3 | * [libuuid from e2fsprogs](http://e2fsprogs.sourceforge.net/) for uuid 4 | generation ("e2fsprogs-libuuid" in FreeBSD ports tree) 5 | * [libdispatch](http://libdispatch.macosforge.org/) ("libdispatch" in FreeBSD 6 | ports tree) 7 | -------------------------------------------------------------------------------- /liblaunch/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | MAINTAINER=tyler@freebsd.org 4 | 5 | LIB=launch 6 | SRCS=liblaunch.c libbootstrap.c \ 7 | launch_getters.c \ 8 | launch_data.c # XXX: Disabled, see #5 libvproc.c 9 | 10 | .include <../launchd.mk> 11 | .include 12 | 13 | -------------------------------------------------------------------------------- /xcscripts/liblaunch-postflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/usr/include/servers 4 | mv "$DSTROOT"/usr/include/bootstrap.h "$DSTROOT"/usr/include/servers/ 5 | ln -sf bootstrap.h "$DSTROOT"/usr/include/servers/bootstrap_defs.h 6 | -------------------------------------------------------------------------------- /launchproxy/launchproxy.8: -------------------------------------------------------------------------------- 1 | .Dd February 2, 2005 2 | .Dt launchproxy 8 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm launchproxy 6 | .Nd inetd job emulation helper 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | handles the inetd emulation for 12 | .Nm launchd . 13 | This program may be merged into 14 | .Nm launchd 15 | in the future. 16 | .Sh SEE ALSO 17 | .Xr launchctl 1 , 18 | .Xr launchd.plist 5 , 19 | .Xr launchd 8 20 | -------------------------------------------------------------------------------- /xcscripts/launchctl-postflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/System/Library/LaunchAgents 4 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/System/Library/LaunchDaemons 5 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/Library/LaunchAgents 6 | install -o "$INSTALL_OWNER" -g "$INSTALL_GROUP" -m 0755 -d "$DSTROOT"/Library/LaunchDaemons 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | MAINTAINER=tyler@freebsd.org 4 | 5 | SUBDIR=liblaunch/test \ 6 | liblaunch \ 7 | wait4path \ 8 | launchproxy \ 9 | launchctl \ 10 | launchd 11 | 12 | 13 | test: liblaunch/test wait4path liblaunch 14 | @for d in `find . -iname "*_test"`; do \ 15 | echo "> Running $$d" && ./$$d ; \ 16 | done 17 | 18 | @./support/roundup ./t/*.sh 19 | 20 | docs: 21 | doxygen launchd.doxy 22 | 23 | .include 24 | -------------------------------------------------------------------------------- /man/rc.8: -------------------------------------------------------------------------------- 1 | .Dd 1 May, 2009 2 | .Dt RC 8 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm rc 6 | .Nd command script for boot 7 | .Sh SYNOPSIS 8 | .Nm rc 9 | .Nm rc.local 10 | .Sh DESCRIPTION 11 | .Nm rc.local 12 | is now unsupported and has been replaced with 13 | .Xr launchd 8 , 14 | which bootstraps itself via the 15 | .Xr launchctl 1 16 | .Ar bootstrap 17 | subcommand to read in 18 | .Xr launchd 8 19 | jobs from the standard locations. 20 | .Sh SEE ALSO 21 | .Xr launchd 8 , 22 | .Xr launchctl 1 23 | -------------------------------------------------------------------------------- /launchd/helper.defs: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | import "vproc.h"; 4 | import "vproc_priv.h"; 5 | import "vproc_internal.h"; 6 | 7 | subsystem launchd_helper 4241011; 8 | 9 | userprefix helper_downcall_; 10 | serverprefix helper_recv_; 11 | 12 | skip; 13 | 14 | /* For coreservicesd to harvest exit status, not actually for UserEventAgent. */ 15 | simpleroutine 16 | wait( 17 | p : mach_port_move_send_once_t; 18 | status : int 19 | ); 20 | -------------------------------------------------------------------------------- /wait4path/wait4path.1: -------------------------------------------------------------------------------- 1 | .Dd April 6, 2004 2 | .Dt WAIT4PATH 1 3 | .Os "Mac OS X" 10.4 4 | .Sh NAME 5 | .Nm wait4path 6 | .Nd wait for given path to show up in the namespace 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ao Ar path Ac 10 | .Sh DESCRIPTION 11 | The 12 | .Nm 13 | program simply checks to see if the given path exists, and if so, it exits. Otherwise, it sleeps until the mount table is updated and checks again. The program will loop indefinitely until the path shows up in the file system namespace. 14 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Open Launchd Roadmap 2 | 3 | In this document is a semi-sequential list of projects/tasks for porting 4 | launchd to other platforms. 5 | 6 | ## Building liblaunch 7 | ## Cross-platform vproc 8 | ## Building launchd 9 | ## Spawning a single process 10 | ## Building launchctl 11 | ## launchd <-> launchctl IPC 12 | ## Per-user launchd/launchctl 13 | ## Processing/parsing launchd job files 14 | ## Cross-platform kernel events 15 | ## launchd as FreeBSD PID 1 16 | ## Build/test launchproxy 17 | -------------------------------------------------------------------------------- /liblaunch/test/Makefile: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | PROG=liblaunch_test 4 | MAN= 5 | 6 | DPADD= ${LIBLAUNCH} 7 | LDADD= ${LIBLAUNCH} 8 | 9 | LIBLAUNCH_SRCS=liblaunch.c launch_data.c launch_getters.c 10 | CMOCKA_SRCS=cmocka.c 11 | TEST_SRCS=liblaunch_test.c getter_tests.c byteswap_tests.c 12 | 13 | SRCS=${TEST_SRCS} ${CMOCKA_SRCS} ${LIBLAUNCH_SRCS} 14 | 15 | CFLAGS+=-DUNIT_TEST \ 16 | -I../../support/cmocka/include \ 17 | -I../ \ 18 | -I../../launchd \ 19 | -I/usr/local/include \ 20 | -DDEBUG 21 | 22 | .include <../../launchd.mk> 23 | -------------------------------------------------------------------------------- /launchd.mk: -------------------------------------------------------------------------------- 1 | # $FreeBSD$ 2 | 3 | MAINTAINER=tyler@freebsd.org 4 | 5 | CFLAGS+=-g -fPIC -fno-exceptions -fstack-protector -fvisibility=hidden 6 | 7 | # WARNINGS 8 | CFLAGS+=-Wall -Wextra -Wno-unused-parameter \ 9 | -Wno-unused-label -Wformat -Wreturn-type \ 10 | -Wsign-compare -Wmultichar -Winit-self \ 11 | -Wuninitialized -Wno-deprecated -Wformat-security \ 12 | -Werror 13 | 14 | # INCLUDES 15 | CFLAGS+=-I${PWD}/../launchd \ 16 | -I${PWD}/../liblaunch \ 17 | -I/usr/local/include 18 | 19 | # DEFINES 20 | CFLAGS+=-DDEBUG 21 | 22 | .include 23 | -------------------------------------------------------------------------------- /t/wait4path-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | describe "wait4path" 4 | 5 | it_shows_usage_by_default() { 6 | test "$(runit)" = "usage: ${COMMAND} " 7 | } 8 | 9 | it_exits_for_existing_paths() { 10 | output=$(runit wait4path) 11 | assert_success $? 12 | assert_empty $output 13 | } 14 | it_exits_for_existing_mounts() { 15 | output=$(runit /) 16 | assert_success $? 17 | assert_empty $output 18 | } 19 | 20 | it_should_wait_for_mount() { 21 | # mkdir /tmp/foo && mdmfs -s 32m md /tmp/foo 22 | true 23 | } 24 | 25 | ################################################################################ 26 | 27 | COMMAND=./wait4path/wait4path 28 | source "t/assertions.sh" 29 | -------------------------------------------------------------------------------- /man/launchd.conf.5: -------------------------------------------------------------------------------- 1 | .Dd 1 May, 2009 2 | .Dt launchd.conf 5 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm launchd.conf 6 | .Nd launchd configuration file 7 | .Sh SYNOPSIS 8 | .Nm $HOME/.launchd.conf 9 | .Nm /etc/launchd.conf 10 | .Sh DESCRIPTION 11 | .Nm 12 | contains a list of subcommands 13 | .Ar ( load , 14 | .Ar unload , 15 | etc.) to run via 16 | .Xr launchctl 1 17 | when 18 | .Xr launchd 8 19 | starts. 20 | .Sh FILES 21 | .Bl -tag -width "$HOME/.launchd.conf" -compact 22 | .It Pa $HOME/.launchd.conf 23 | Your launchd configuration file (currently unsupported). 24 | .It Pa /etc/launchd.conf 25 | The system's launchd configuration file. 26 | .El 27 | .Sh SEE ALSO 28 | .Xr launchctl 1 , 29 | .Xr launchd 8 , 30 | .Xr launchd.plist 5 31 | -------------------------------------------------------------------------------- /SystemStarter/com.apple.SystemStarter.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | KeepAlive 6 | 7 | PathState 8 | 9 | /etc/rc.local 10 | 11 | /etc/rc.shutdown.local 12 | 13 | 14 | 15 | Label 16 | com.apple.SystemStarter 17 | Program 18 | /sbin/SystemStarter 19 | QueueDirectories 20 | 21 | /Library/StartupItems 22 | /System/Library/StartupItems 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /xcscripts/launchd-postflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p "$DSTROOT/private/var/db/launchd.db/com.apple.launchd" 4 | chown root:wheel "$DSTROOT/private/var/db/launchd.db" 5 | chown root:wheel "$DSTROOT/private/var/db/launchd.db/com.apple.launchd" 6 | 7 | mkdir -p "$DSTROOT/private/var/log/com.apple.launchd" 8 | chown root:wheel "$DSTROOT/private/var/log/com.apple.launchd" 9 | 10 | # These directories need to be here to satisfy certain third-party dependencies. 11 | mkdir -p "$DSTROOT/private/etc/mach_init.d" 12 | mkdir -p "$DSTROOT/private/etc/mach_init_per_user.d" 13 | mkdir -p "$DSTROOT/private/etc/mach_init_per_login_session.d" 14 | chown root:wheel "$DSTROOT/private/etc/mach_init.d" 15 | chown root:wheel "$DSTROOT/private/etc/mach_init_per_user.d" 16 | chown root:wheel "$DSTROOT/private/etc/mach_init_per_login_session.d" 17 | -------------------------------------------------------------------------------- /launchd/ktrace.c: -------------------------------------------------------------------------------- 1 | #include "ktrace.h" 2 | 3 | void 4 | runtime_ktrace1(runtime_ktrace_code_t code) 5 | { 6 | void *ra = __builtin_extract_return_addr(__builtin_return_address(1)); 7 | 8 | /* This syscall returns EINVAL when the trace isn't enabled. */ 9 | if (launchd_apple_internal) { 10 | syscall(180, code, 0, 0, 0, (long)ra); 11 | } 12 | } 13 | 14 | void 15 | runtime_ktrace0(runtime_ktrace_code_t code) 16 | { 17 | void *ra = __builtin_extract_return_addr(__builtin_return_address(0)); 18 | 19 | /* This syscall returns EINVAL when the trace isn't enabled. */ 20 | if (launchd_apple_internal) { 21 | syscall(180, code, 0, 0, 0, (long)ra); 22 | } 23 | } 24 | 25 | void 26 | runtime_ktrace(runtime_ktrace_code_t code, long a, long b, long c) 27 | { 28 | void *ra = __builtin_extract_return_addr(__builtin_return_address(0)); 29 | 30 | /* This syscall returns EINVAL when the trace isn't enabled. */ 31 | if (launchd_apple_internal) { 32 | syscall(180, code, a, b, c, (long)ra); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /launchd/kill2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | #ifndef __LAUNCHD_KILL2_H__ 21 | #define __LAUNCHD_KILL2_H__ 22 | 23 | #include 24 | 25 | int kill2(pid_t pid, int sig); 26 | int killpg2(pid_t pgrp, int sig); 27 | 28 | #endif /* __LAUNCHD_KILL2_H__ */ 29 | -------------------------------------------------------------------------------- /launchd/internal.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | subsystem internal 137000; 22 | 23 | #include 24 | #include 25 | 26 | serverprefix x_; 27 | 28 | routine 29 | handle_kqueue( 30 | p : mach_port_t; 31 | fd : integer_t 32 | ); 33 | -------------------------------------------------------------------------------- /liblaunch/shims/Availability.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 R. Tyler Croy 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /*' 18 | * Availability is Apple OS functionality for tagging function prototypes with 19 | * the version of OS in which they became available, or in which version they 20 | * will be deprecated. 21 | */ 22 | 23 | #ifndef __AVAILABILITY_H__ 24 | #define __AVAILABILITY_H__ 25 | 26 | #define __OSX_AVAILABLE_STARTING(x, y) __attribute__((visibility("default"))) 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /launchd/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H__ 2 | #define __CONFIG_H__ 3 | 4 | #ifndef __has_include 5 | #define __has_include(n) 0 6 | #endif 7 | 8 | #ifdef __APPLE__ 9 | /* 10 | * TargetConditionals.h contains Autoconfiguration of TARGET_ conditionals for 11 | * Mac OS X and iPhone. Unless we're on an __APPLE__ based system, we don't 12 | * really have any requirement for these macros 13 | */ 14 | #include 15 | #endif 16 | 17 | #if __has_include() 18 | #define HAVE_QUARANTINE 1 19 | #else 20 | #define HAVE_QUARANTINE 0 21 | #endif 22 | 23 | #if __has_include() 24 | #define HAVE_RESPONSIBILITY 1 25 | #else 26 | #define HAVE_RESPONSIBILITY 0 27 | #endif 28 | 29 | #if __has_include() 30 | #define HAVE_SANDBOX 1 31 | #else 32 | #define HAVE_SANDBOX 0 33 | #endif 34 | 35 | #define HAVE_LIBAUDITD !TARGET_OS_EMBEDDED 36 | 37 | #if !TARGET_OS_EMBEDDED && __has_include() 38 | #define HAVE_SYSTEMSTATS 1 39 | #else 40 | #define HAVE_SYSTEMSTATS 0 41 | #endif 42 | 43 | #endif /* __CONFIG_H__ */ 44 | -------------------------------------------------------------------------------- /liblaunch/reboot2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __REBOOT2_H__ 22 | #define __REBOOT2_H__ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | __BEGIN_DECLS 29 | 30 | #define RB2_FULLREBOOT 0x8000000000000000llu 31 | 32 | /* Returns NULL on success. Not NULL on failure */ 33 | 34 | __attribute__((visibility("default"))) 35 | void *reboot2(uint64_t flags); 36 | 37 | __END_DECLS 38 | 39 | #endif /* __REBOOT2_H__ */ 40 | -------------------------------------------------------------------------------- /SystemStarter/IPC.h: -------------------------------------------------------------------------------- 1 | /** 2 | * IPC.h - System Starter IPC routines 3 | * Wilfredo Sanchez | wsanchez@opensource.apple.com 4 | * Kevin Van Vechten | kevinvv@uclink4.berkeley.edu 5 | * $Apple$ 6 | ** 7 | * Copyright (c) 1999-2001 Apple Computer, Inc. All rights reserved. 8 | * 9 | * @APPLE_APACHE_LICENSE_HEADER_START@ 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | * 23 | * @APPLE_APACHE_LICENSE_HEADER_END@ 24 | **/ 25 | 26 | #ifndef _IPC_H_ 27 | #define _IPC_H_ 28 | 29 | #include "SystemStarter.h" 30 | 31 | /** 32 | * Monitor a startup item task. Creates a mach port and uses the 33 | * invalidation callback to notify system starter when the process 34 | * terminates. 35 | **/ 36 | void MonitorStartupItem (StartupContext aStartupContext, CFMutableDictionaryRef anItem); 37 | 38 | #endif /* _IPC_H_ */ 39 | -------------------------------------------------------------------------------- /launchd/kill2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "kill2.h" 26 | 27 | int 28 | kill2(pid_t pid, int sig) 29 | { 30 | /* 31 | * POSIX defines consistency over correctness, and consequently 32 | * kill/killpg now returns EPERM instead of ESRCH. 33 | * 34 | * I've filed 5487498 to get a non-portable kill(). 35 | * We'll regretfully take advantage of implementation details for now. 36 | */ 37 | return syscall(SYS_kill, pid, sig, 0); 38 | } 39 | 40 | int 41 | killpg2(pid_t pgrp, int sig) 42 | { 43 | return kill2(-pgrp, sig); 44 | } 45 | -------------------------------------------------------------------------------- /launchd/ktrace.h: -------------------------------------------------------------------------------- 1 | #ifndef __LAUNCHD_KTRACE_H__ 2 | #define __LAUNCHD_KTRACE_H__ 3 | 4 | #include 5 | #include 6 | 7 | extern bool launchd_apple_internal; 8 | 9 | #ifndef DBG_LAUNCHD 10 | #define DBG_LAUNCHD 34 11 | #endif /* DBG_LAUNCHD */ 12 | 13 | /* Class(8) | SubClass(8) | Code(14) | Qual(2) */ 14 | #define RTKT_CODE(c) ((DBG_LAUNCHD << 24) | (((c) & 0x3fffff) << 2)) 15 | 16 | typedef enum { 17 | RTKT_LAUNCHD_STARTING = RTKT_CODE(1), 18 | RTKT_LAUNCHD_EXITING = RTKT_CODE(2), 19 | RTKT_LAUNCHD_FINDING_STRAY_PG = RTKT_CODE(3), 20 | RTKT_LAUNCHD_FINDING_ALL_STRAYS = RTKT_CODE(4), 21 | RTKT_LAUNCHD_FINDING_EXECLESS = RTKT_CODE(5), 22 | RTKT_LAUNCHD_FINDING_WEIRD_UIDS = RTKT_CODE(6), 23 | RTKT_LAUNCHD_DATA_PACK = RTKT_CODE(7), 24 | RTKT_LAUNCHD_DATA_UNPACK = RTKT_CODE(8), 25 | RTKT_LAUNCHD_BUG = RTKT_CODE(9), 26 | RTKT_LAUNCHD_MACH_IPC = RTKT_CODE(10), 27 | RTKT_LAUNCHD_BSD_KEVENT = RTKT_CODE(11), 28 | RTKT_VPROC_TRANSACTION_INCREMENT = RTKT_CODE(12), 29 | RTKT_VPROC_TRANSACTION_DECREMENT = RTKT_CODE(13), 30 | } runtime_ktrace_code_t; 31 | 32 | /* All of these log the return address as "arg4" */ 33 | void runtime_ktrace1(runtime_ktrace_code_t code); 34 | void runtime_ktrace0(runtime_ktrace_code_t code); 35 | void runtime_ktrace(runtime_ktrace_code_t code, long a, long b, long c); 36 | 37 | #endif /* __LAUNCHD_KTRACE_H__ */ 38 | -------------------------------------------------------------------------------- /launchd/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCHD_IPC_H__ 22 | #define __LAUNCHD_IPC_H__ 23 | 24 | #include 25 | #include "runtime.h" 26 | #include "core.h" 27 | #include "launch_priv.h" 28 | #include "launch_internal.h" 29 | 30 | struct conncb { 31 | kq_callback kqconn_callback; 32 | LIST_ENTRY(conncb) sle; 33 | launch_t conn; 34 | job_t j; 35 | }; 36 | 37 | extern char *sockpath; 38 | 39 | void ipc_open(int fd, job_t j); 40 | void ipc_close_all_with_job(job_t j); 41 | void ipc_close(struct conncb *c); 42 | void ipc_callback(void *, struct kevent *); 43 | void ipc_revoke_fds(launch_data_t o); 44 | void ipc_close_fds(launch_data_t o); 45 | void ipc_server_init(void); 46 | 47 | #endif /* __LAUNCHD_IPC_H__ */ 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Launchd 2 | 3 | Mac OS X 10.4 Tiger introduced a new program called `launchd`. The daemon 4 | replaced `SystemStarter` (MacOS legacy) and older `rc.d` (BSD legacy) startup 5 | processes and job management functionality. 6 | 7 | Launchd can be split into two logical pieces, "process 1", i.e. the root 8 | launchd which controls system startup and system daemons and "user launchd" 9 | which allows invividual users to manage their own processes/jobs. 10 | 11 | 12 | ## Why? 13 | 14 | The primary goal of this project is to port `launchd` in its entirety over to 15 | FreeBSD, hopefully making it usable by other BSD or Linux systems along the 16 | way. That said, the primary motivator for the original porting work in 2005 was 17 | to improve boot time. While improved boot time would be of tangible benefit to 18 | FreeBSD users, the current motivator of this project is to enable **modern 19 | process management for user and system level processes** on FreeBSD systems. 20 | 21 | 22 | ## Getting involved: 23 | 24 | * `#openlaunchd` on the [Freenode](http://freenode.net) is where development 25 | discussion can occur. 26 | * [open launchd](https://groups.google.com/forum/#!forum/openlaunchd) mailing 27 | list 28 | 29 | 30 | ### Helpful links 31 | 32 | * The main project [home page](https://wiki.freebsd.org/launchd) can be found 33 | on the FreeBSD [project wiki](https://wiki.freebsd.org/). 34 | * `rwatson@` runs [fxr.watson.org](http://fxr.watson.org/) which can be very 35 | useful for cross-referencing Apple system headers and code, with FreeBSD system 36 | headers and code 37 | -------------------------------------------------------------------------------- /launchd/job_forward.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | subsystem job_forward 400; 22 | 23 | #include 24 | #include 25 | #include "job_types.defs" 26 | import "vproc.h"; 27 | import "vproc_priv.h"; 28 | import "vproc_internal.h"; 29 | 30 | userprefix vproc_mig_; 31 | serverprefix job_mig_; 32 | 33 | skip; /* create_server */ 34 | 35 | skip; /* reboot2 */ 36 | 37 | skip; /* check_in */ 38 | 39 | skip; /* register2 */ 40 | 41 | simpleroutine 42 | look_up2_forward( 43 | j : job_t; 44 | replyport rp : mach_port_move_send_once_t; 45 | servicename : name_t; 46 | targetpid : pid_t; 47 | instanceid : uuid_t; 48 | flags : uint64_t 49 | ); 50 | 51 | skip; /* send_signal */ 52 | 53 | simpleroutine 54 | parent_forward( 55 | j : job_t; 56 | replyport rp : mach_port_move_send_once_t 57 | ); 58 | 59 | -------------------------------------------------------------------------------- /launchd/launchd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCHD_H__ 22 | #define __LAUNCHD_H__ 23 | 24 | #if HAS_MACH 25 | #include 26 | #include 27 | #endif 28 | 29 | #include "launch.h" 30 | 31 | #ifdef __APPLE__ 32 | #include "bootstrap.h" 33 | #endif 34 | 35 | #include "runtime.h" 36 | 37 | struct kevent; 38 | struct conncb; 39 | 40 | extern bool pid1_magic; 41 | extern bool launchd_shutting_down; 42 | extern bool fake_launchd_shutting_down; 43 | extern bool network_up; 44 | extern FILE *launchd_console; 45 | extern uid_t launchd_uid; 46 | 47 | void launchd_SessionCreate(void); 48 | void launchd_shutdown(void); 49 | 50 | enum { 51 | LAUNCHD_PERSISTENT_STORE_DB, 52 | LAUNCHD_PERSISTENT_STORE_LOGS, 53 | }; 54 | char *launchd_copy_persistent_store(int type, const char *file); 55 | 56 | int _fd(int fd); 57 | 58 | #endif /* __LAUNCHD_H__ */ 59 | -------------------------------------------------------------------------------- /SystemStarter/StartupItemContext.8: -------------------------------------------------------------------------------- 1 | .Dd July 7, 2002 2 | .Dt StartupItemContext 8 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm StartupItemContext 6 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 7 | .\" words here as the database is built based on the words here and in the .ND line. 8 | .\" Use .Nm macro to designate other names for the documented program. 9 | .Nd Execute a program in StartupItem context 10 | .Sh SYNOPSIS 11 | .Nm 12 | .Op Ar program Op Ar arguments 13 | .Sh DESCRIPTION 14 | The 15 | .Nm 16 | utility launches the specified program in StartupItem bootstrap context. Each Darwin 17 | and Mac OS X login creates a unique bootstrap subset context to contain login specific 18 | Mach port registrations with the bootstrap server. All such registrations performed 19 | within the context of that subset are only visible to other processes within that 20 | context or subsequent subsets of it. Therefore, a Mach port based service/daemon 21 | launched within a login context will not be visible to other such contexts. 22 | .Pp 23 | To override this, a root user can use the 24 | .Nm 25 | utility to launch the program within the same bootstrap context as all other 26 | StartupItems. All subsequent Mach port bootstrap registrations perfomed by the program 27 | will be visible system-wide. 28 | .Sh NOTES 29 | All bootstrap port lookups will also be resticted 30 | to the StartupItem context. The services provided on a per-login basis (clipboard, 31 | etc...) will not be available to the program. 32 | .Sh SEE ALSO 33 | .\" List links in ascending order by section, alphabetically within a section. 34 | .\" Please do not reference files that do not exist without filing a bug report 35 | .Xr SystemStarter 8 36 | -------------------------------------------------------------------------------- /wait4path/wait4path.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | int kq = kqueue(); 34 | struct kevent kev; 35 | struct stat sb; 36 | 37 | if (argc != 2) { 38 | fprintf(stderr, "usage: %s \n", argv[0]); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | EV_SET(&kev, 0, EVFILT_FS, EV_ADD, 0, 0, 0); 43 | 44 | if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) { 45 | fprintf(stderr, "adding EVFILT_FS to kqueue failed: %s\n", strerror(errno)); 46 | exit(EXIT_FAILURE); 47 | } 48 | 49 | if (stat(argv[1], &sb) == 0) { 50 | exit(EXIT_SUCCESS); 51 | } 52 | 53 | for (;;) { 54 | kevent(kq, NULL, 0, &kev, 1, NULL); 55 | if (stat(argv[1], &sb) == 0) { 56 | break; 57 | } 58 | } 59 | 60 | exit(EXIT_SUCCESS); 61 | } 62 | -------------------------------------------------------------------------------- /SystemStarter/SystemStarter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SystemStarter.h - System Starter driver 3 | * Wilfredo Sanchez | wsanchez@opensource.apple.com 4 | * $Apple$ 5 | ** 6 | * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. 7 | * 8 | * @APPLE_APACHE_LICENSE_HEADER_START@ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | * @APPLE_APACHE_LICENSE_HEADER_END@ 23 | **/ 24 | 25 | #ifndef _SYSTEM_STARTER_H_ 26 | #define _SYSTEM_STARTER_H_ 27 | 28 | /* Structure to pass common objects from system_starter to the IPC handlers */ 29 | typedef struct StartupContextStorage { 30 | CFMutableArrayRef aWaitingList; 31 | CFMutableArrayRef aFailedList; 32 | CFMutableDictionaryRef aStatusDict; 33 | int aServicesCount; 34 | int aRunningCount; 35 | } *StartupContext; 36 | 37 | #define kFixerDir "/var/db/fixer" 38 | #define kFixerPath "/var/db/fixer/StartupItems" 39 | 40 | /* Action types */ 41 | typedef enum { 42 | kActionNone = 0, 43 | kActionStart, 44 | kActionStop, 45 | kActionRestart 46 | } Action; 47 | 48 | void CF_syslog(int level, CFStringRef message, ...); 49 | extern bool gVerboseFlag; 50 | 51 | #endif /* _SYSTEM_STARTER_H_ */ 52 | -------------------------------------------------------------------------------- /liblaunch/test/liblaunch_test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef _LIBLAUNCH_TEST_H_ 19 | #define _LIBLAUNCH_TEST_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "launch.h" 28 | #include "byteswap.h" 29 | #include 30 | 31 | /* byteswap.h */ 32 | void test_host2wire_64(void**); 33 | void test_host2wire_32(void**); 34 | void test_host2wire_16(void**); 35 | void test_host2wire_8(void**); 36 | 37 | void test_wire2host_64(void**); 38 | void test_wire2host_32(void**); 39 | void test_wire2host_16(void**); 40 | void test_wire2host_8(void**); 41 | 42 | /* getters.c */ 43 | void test_launch_data_get_errno_null(void**); 44 | void test_launch_data_get_errno(void**); 45 | void test_launch_data_get_fd_null(void**); 46 | void test_launch_data_get_integer_null(void**); 47 | void test_launch_data_get_integer(void**); 48 | void test_launch_data_get_bool_default(void**); 49 | void test_launch_data_get_bool_false(void**); 50 | 51 | /* liblaunch.c */ 52 | void test_launch_init_globals(void**); 53 | void test_launch_data_alloc(void**); 54 | void test_launch_data_alloc_array(void**); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /launchd/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LAUNCHD_LOG_H__ 2 | #define __LAUNCHD_LOG_H__ 3 | 4 | #if HAS_MACH 5 | #include 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifdef __APPLE__ 13 | #include 14 | #endif 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | extern char *launchd_username; 26 | extern char *launchd_label; 27 | extern mach_port_t launchd_drain_reply_port; 28 | extern bool launchd_var_available; 29 | extern int64_t launchd_system_start; 30 | 31 | struct launchd_syslog_attr { 32 | const char *from_name; 33 | const char *about_name; 34 | const char *session_name; 35 | int priority; 36 | uid_t from_uid; 37 | pid_t from_pid; 38 | pid_t about_pid; 39 | }; 40 | 41 | /* These constants must not have the high bit set so we can safely mask them 42 | * mask them with LOG_CONSOLE. 43 | */ 44 | #define LOG_PERF 0x5252615d 45 | #define LOG_APPLEONLY 0x4141504c 46 | #define LOG_CONSOLE (1 << 31) 47 | 48 | __attribute__((visibility("default"))) 49 | __attribute__((used)) 50 | extern bool 51 | _launchd_os_redirect(const char *message); 52 | 53 | int 54 | runtime_setlogmask(int maskpri); 55 | 56 | void 57 | launchd_closelog(void); 58 | 59 | __attribute__((format(printf, 2, 3))) 60 | void 61 | launchd_syslog(int pri, const char *message, ...); 62 | 63 | __attribute__((format(printf, 2, 0))) 64 | void 65 | launchd_vsyslog(struct launchd_syslog_attr *attr, const char *message, va_list args); 66 | 67 | void 68 | launchd_log_push(void); 69 | 70 | kern_return_t 71 | launchd_log_forward(uid_t forward_uid, gid_t forward_gid, vm_offset_t inval, mach_msg_type_number_t invalCnt); 72 | 73 | kern_return_t 74 | launchd_log_drain(mach_port_t srp, vm_offset_t *outval, mach_msg_type_number_t *outvalCnt); 75 | 76 | #endif /* __LAUNCHD_LOG_H__ */ 77 | -------------------------------------------------------------------------------- /launchd/job_types.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | /* 21 | * bootstrap -- fundamental service initiator and port server 22 | * Mike DeMoney, NeXT, Inc. 23 | * Copyright, 1990. All rights reserved. 24 | */ 25 | 26 | /* These really should be a part of the standard types... */ 27 | type mach_port_move_send_array_t = array[] of mach_port_move_send_t 28 | ctype: mach_port_array_t; 29 | type mach_port_make_send_array_t = array[] of mach_port_make_send_t 30 | ctype: mach_port_array_t; 31 | 32 | type pid_t = integer_t; 33 | type pid_array_t = ^array [] of pid_t; 34 | type uid_t = natural_t; 35 | type gid_t = natural_t; 36 | type vproc_gsk_t = integer_t; 37 | type logmsg_t = c_string[*:2048]; 38 | type cmd_t = c_string[512]; 39 | type name_t = c_string[128]; 40 | type name_array_t = ^array [] of name_t; 41 | type bootstrap_property_t = natural_t; 42 | type bootstrap_property_array_t = ^array [] of bootstrap_property_t; 43 | type bootstrap_status_t = integer_t; 44 | type bootstrap_status_array_t = ^array [] of bootstrap_status_t; 45 | type uuid_t = array [16] of MACH_MSG_TYPE_BYTE; 46 | 47 | type job_t = mach_port_t 48 | intran : job_t job_mig_intran(mach_port_t) 49 | outtran : mach_port_t job_mig_outtran(job_t) 50 | destructor : job_mig_destructor(job_t) 51 | cusertype : vproc_mig_t; 52 | -------------------------------------------------------------------------------- /rc/rc.common: -------------------------------------------------------------------------------- 1 | ## 2 | # Common setup for startup scripts. 3 | ## 4 | # Copyright 1998-2002 Apple Computer, Inc. 5 | ## 6 | 7 | ####################### 8 | # Configure the shell # 9 | ####################### 10 | 11 | ## 12 | # Be strict 13 | ## 14 | #set -e 15 | set -u 16 | 17 | ## 18 | # Set command search path 19 | ## 20 | PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/System/Library/CoreServices; export PATH 21 | 22 | ## 23 | # Set the terminal mode 24 | ## 25 | #if [ -x /usr/bin/tset ] && [ -f /usr/share/misc/termcap ]; then 26 | # TERM=$(tset - -Q); export TERM 27 | #fi 28 | 29 | #################### 30 | # Useful functions # 31 | #################### 32 | 33 | ## 34 | # Determine if the network is up by looking for any non-loopback 35 | # internet network interfaces. 36 | ## 37 | CheckForNetwork() 38 | { 39 | local test 40 | 41 | if [ -z "${NETWORKUP:=}" ]; then 42 | test=$(ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/inet/p' | wc -l) 43 | if [ "${test}" -gt 0 ]; then 44 | NETWORKUP="-YES-" 45 | else 46 | NETWORKUP="-NO-" 47 | fi 48 | fi 49 | } 50 | 51 | alias ConsoleMessage=echo 52 | 53 | ## 54 | # Process management 55 | ## 56 | GetPID () 57 | { 58 | local program="$1" 59 | local pidfile="${PIDFILE:=/var/run/${program}.pid}" 60 | local pid="" 61 | 62 | if [ -f "${pidfile}" ]; then 63 | pid=$(head -1 "${pidfile}") 64 | if ! kill -0 "${pid}" 2> /dev/null; then 65 | echo "Bad pid file $pidfile; deleting." 66 | pid="" 67 | rm -f "${pidfile}" 68 | fi 69 | fi 70 | 71 | if [ -n "${pid}" ]; then 72 | echo "${pid}" 73 | return 0 74 | else 75 | return 1 76 | fi 77 | } 78 | 79 | ## 80 | # Generic action handler 81 | ## 82 | RunService () 83 | { 84 | case $1 in 85 | start ) StartService ;; 86 | stop ) StopService ;; 87 | restart) RestartService ;; 88 | * ) echo "$0: unknown argument: $1";; 89 | esac 90 | } 91 | 92 | ########################## 93 | # Get host configuration # 94 | ########################## 95 | . /etc/hostconfig 96 | -------------------------------------------------------------------------------- /liblaunch/launch_getters.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Apple, Inc, R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | #include "launch.h" 18 | #include "launch_priv.h" 19 | #include "launch_internal.h" 20 | 21 | int 22 | launch_data_get_errno(launch_data_t d) 23 | { 24 | if (NULL == d) { 25 | return 0; 26 | } 27 | return d->err; 28 | } 29 | 30 | int 31 | launch_data_get_fd(launch_data_t d) 32 | { 33 | if (NULL == d) { 34 | return 0; 35 | } 36 | return d->fd; 37 | } 38 | 39 | long long 40 | launch_data_get_integer(launch_data_t d) 41 | { 42 | if (NULL == d) { 43 | return 0; 44 | } 45 | return d->number; 46 | } 47 | 48 | bool 49 | launch_data_get_bool(launch_data_t d) 50 | { 51 | return d->boolean; 52 | } 53 | 54 | double 55 | launch_data_get_real(launch_data_t d) 56 | { 57 | return d->float_num; 58 | } 59 | 60 | const char * 61 | launch_data_get_string(launch_data_t d) 62 | { 63 | if (LAUNCH_DATA_STRING != d->type) 64 | return NULL; 65 | return d->string; 66 | } 67 | 68 | void * 69 | launch_data_get_opaque(launch_data_t d) 70 | { 71 | if (LAUNCH_DATA_OPAQUE != d->type) 72 | return NULL; 73 | return d->opaque; 74 | } 75 | 76 | size_t 77 | launch_data_get_opaque_size(launch_data_t d) 78 | { 79 | return d->opaque_size; 80 | } 81 | 82 | int 83 | launchd_getfd(launch_t l) 84 | { 85 | return (l->which == LAUNCHD_USE_CHECKIN_FD) ? l->cifd : l->fd; 86 | } 87 | 88 | #if HAS_MACH 89 | mach_port_t 90 | launch_data_get_machport(launch_data_t d) 91 | { 92 | return d->mp; 93 | } 94 | #endif 95 | -------------------------------------------------------------------------------- /liblaunch/byteswap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Apple, Inc., R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifdef __FreeBSD__ 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | #define host2wire(x) \ 25 | ({ typeof (x) _X, _x = (x); \ 26 | switch (sizeof(_x)) { \ 27 | case 8: \ 28 | _X = htobe64(_x); \ 29 | break; \ 30 | case 4: \ 31 | _X = htobe32(_x); \ 32 | break; \ 33 | case 2: \ 34 | _X = htobe16(_x); \ 35 | break; \ 36 | case 1: \ 37 | _X = _x; \ 38 | break; \ 39 | default: \ 40 | _X = x; \ 41 | break; \ 42 | } \ 43 | _X; \ 44 | }) 45 | 46 | #define wire2host(x) \ 47 | ({ typeof (x) _X, _x = (x); \ 48 | switch (sizeof(_x)) { \ 49 | case 8: \ 50 | _X = be64toh(_x); \ 51 | break; \ 52 | case 4: \ 53 | _X = be32toh(_x); \ 54 | break; \ 55 | case 2: \ 56 | _X = be16toh(_x); \ 57 | break; \ 58 | case 1: \ 59 | _X = _x; \ 60 | break; \ 61 | default: \ 62 | _X = _x; \ 63 | break; \ 64 | } \ 65 | _X; \ 66 | }) 67 | 68 | 69 | union _launch_double_u { 70 | uint64_t iv; 71 | double dv; 72 | }; 73 | 74 | #define host2wire_f(x) ({ \ 75 | typeof(x) _F, _f = (x); \ 76 | union _launch_double_u s; \ 77 | s.dv = _f; \ 78 | s.iv = host2wire(s.iv); \ 79 | _F = s.dv; \ 80 | _F; \ 81 | }) 82 | 83 | #define wire2host_f(x) ({ \ 84 | typeof(x) _F, _f = (x); \ 85 | union _launch_double_u s; \ 86 | s.dv = _f; \ 87 | s.iv = wire2host(s.iv); \ 88 | _F = s.dv; \ 89 | _F; \ 90 | }) 91 | -------------------------------------------------------------------------------- /liblaunch/test/getter_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include "liblaunch_test.h" 19 | 20 | /* 21 | * TEST: launch_data_get_errno 22 | *****************************************************/ 23 | void test_launch_data_get_errno_null(void **state) { 24 | launch_data_t d = NULL; 25 | assert_int_equal(0, launch_data_get_errno(d)); 26 | }; 27 | 28 | void test_launch_data_get_errno(void **state) { 29 | struct _launch_data d; 30 | d.err = 4; 31 | assert_int_equal(4, launch_data_get_errno(&d)); 32 | } 33 | /*****************************************************/ 34 | 35 | /* TEST: launch_data_get_fd 36 | *****************************************************/ 37 | void test_launch_data_get_fd_null(void **state) { 38 | launch_data_t d = NULL; 39 | assert_int_equal(0, launch_data_get_fd(d)); 40 | }; 41 | 42 | /* TEST: launch_data_get_integer 43 | *****************************************************/ 44 | void test_launch_data_get_integer_null(void **state) { 45 | launch_data_t d = NULL; 46 | assert_true(0 == launch_data_get_integer(d)); 47 | } 48 | 49 | void test_launch_data_get_integer(void **state) { 50 | struct _launch_data d; 51 | d.number = 7; 52 | assert_true(7 == launch_data_get_integer(&d)); 53 | }; 54 | /*****************************************************/ 55 | 56 | 57 | /* TEST: launch_data_get_bool 58 | *****************************************************/ 59 | void test_launch_data_get_bool_default(void **state) { 60 | struct _launch_data d; 61 | assert_true(launch_data_get_bool(&d)); 62 | }; 63 | 64 | void test_launch_data_get_bool_false(void **state) { 65 | struct _launch_data d; 66 | d.boolean = false; 67 | assert_false(launch_data_get_bool(&d)); 68 | }; 69 | /*****************************************************/ 70 | -------------------------------------------------------------------------------- /liblaunch/test/byteswap_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include "liblaunch_test.h" 19 | 20 | /* 21 | * TEST: host2wire 22 | *****************************************************/ 23 | void test_host2wire_64(void **state) { 24 | /* 25 | uint64_t host_int = 1024; 26 | uint64_t wire_int = host2wire(host_int); 27 | */ 28 | /* Nothing to test here on a big-endian system, and we can't verify because 29 | * htonll() doesn't exist */ 30 | }; 31 | 32 | void test_host2wire_32(void **state) { 33 | uint32_t host_int = 1024; 34 | uint32_t wire_int = htonl(host_int); 35 | assert_true(wire_int == host2wire(host_int)); 36 | }; 37 | 38 | void test_host2wire_16(void **state) { 39 | uint16_t host_int = 32; 40 | uint16_t wire_int = htons(host_int); 41 | assert_true(wire_int == host2wire(host_int)); 42 | }; 43 | 44 | void test_host2wire_8(void **state) { 45 | uint8_t host_int = 8; 46 | assert_true(host_int == host2wire(host_int)); 47 | }; 48 | /*****************************************************/ 49 | 50 | #include 51 | /* 52 | * TEST: wire2host 53 | *****************************************************/ 54 | void test_wire2host_64(void **s) { 55 | uint64_t wire_int = htobe64(1024); 56 | uint64_t host_int = 1024; 57 | assert_true(host_int == wire2host(wire_int)); 58 | }; 59 | 60 | void test_wire2host_32(void **s) { 61 | uint32_t wire_int = htonl(32); 62 | uint32_t host_int = 32; 63 | assert_true(host_int == wire2host(wire_int)); 64 | }; 65 | 66 | void test_wire2host_16(void **s) { 67 | uint16_t wire_int = htons(32); 68 | uint16_t host_int = 32; 69 | assert_true(host_int == wire2host(wire_int)); 70 | }; 71 | 72 | void test_wire2host_8(void **s) { 73 | uint8_t host_int = 8; 74 | assert_true(host_int = wire2host(host_int)); 75 | }; 76 | /****************************************************/ 77 | -------------------------------------------------------------------------------- /launchd/core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCHD_CORE_LOGIC__ 22 | #define __LAUNCHD_CORE_LOGIC__ 23 | 24 | #include "runtime.h" 25 | #include "bootstrap.h" 26 | #include "launch.h" 27 | #include 28 | 29 | typedef struct job_s *job_t; 30 | typedef struct jobmgr_s *jobmgr_t; 31 | 32 | extern jobmgr_t root_jobmgr; 33 | extern mach_port_t launchd_audit_port; 34 | extern au_asid_t launchd_audit_session; 35 | extern bool launchd_flat_mach_namespace; 36 | extern bool launchd_embedded_handofgod; 37 | 38 | void jobmgr_init(bool); 39 | jobmgr_t jobmgr_shutdown(jobmgr_t jm); 40 | void jobmgr_dispatch_all_semaphores(jobmgr_t jm); 41 | void jobmgr_dispatch_all_interested(jobmgr_t jm, job_t j); 42 | jobmgr_t jobmgr_delete_anything_with_port(jobmgr_t jm, mach_port_t port); 43 | 44 | launch_data_t job_export_all(void); 45 | 46 | job_t job_dispatch(job_t j, bool kickstart); /* returns j on success, NULL on job removal */ 47 | job_t job_find(jobmgr_t jm, const char *label); 48 | job_t job_find_by_service_port(mach_port_t p); 49 | bool job_ack_port_destruction(mach_port_t p); 50 | bool job_is_anonymous(job_t j); 51 | launch_data_t job_export(job_t j); 52 | void job_stop(job_t j); 53 | void job_checkin(job_t j); 54 | void job_remove(job_t j); 55 | bool job_is_god(job_t j); 56 | job_t job_import(launch_data_t pload); 57 | launch_data_t job_import_bulk(launch_data_t pload); 58 | job_t job_mig_intran(mach_port_t mp); 59 | void job_mig_destructor(job_t j); 60 | void job_ack_no_senders(job_t j); 61 | void job_log(job_t j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); 62 | void job_set_pid_crashed(pid_t p); 63 | 64 | bool xpc_event_demux(mach_port_t p, xpc_object_t request, xpc_object_t *reply); 65 | bool xpc_process_demux(mach_port_t p, xpc_object_t request, xpc_object_t *reply); 66 | 67 | #endif /* __LAUNCHD_CORE_LOGIC__ */ 68 | -------------------------------------------------------------------------------- /launchd/launchd.8: -------------------------------------------------------------------------------- 1 | .Dd 1 May, 2009 2 | .Dt launchd 8 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm launchd 6 | .Nd System wide and per-user daemon/agent manager 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl d 10 | .Op Fl D 11 | .Op Fl s 12 | .Op Fl S Ar SessionType 13 | .Op Ar -- command Op Ar args ... 14 | .Sh DESCRIPTION 15 | .Nm 16 | manages processes, both for the system as a whole and for individual users. 17 | The primary and preferred interface to 18 | .Nm 19 | is via the 20 | .Xr launchctl 1 21 | tool which (among other options) allows the user or administrator to load and unload jobs. 22 | Where possible, it is preferable for jobs to launch on demand based on criteria specified 23 | in their respective configuration files. 24 | .Pp 25 | During boot 26 | .Nm 27 | is invoked by the kernel to run as the first process on the system and to further bootstrap the rest of the system. 28 | .Pp 29 | You cannot invoke 30 | .Nm 31 | directly. 32 | .Sh ENVIRONMENTAL VARIABLES 33 | .Bl -tag -width -indent 34 | .It Pa LAUNCHD_SOCKET 35 | This variable is exported when invoking a command via the launchd command line. It informs launchctl how to find the correct launchd to talk to. 36 | .El 37 | .Sh NOTES 38 | In Darwin, the canonical way to launch a daemon is through 39 | .Nm launchd 40 | as opposed to more traditional mechanisms or mechanisms provided in earlier versions of Mac OS X. These alternate methods should 41 | be considered deprecated and not suitable for new projects. 42 | .Pp 43 | In the 44 | .Nm launchd 45 | lexicon, a "daemon" is, by definition, a system-wide service of which there is one instance for all clients. An "agent" is a service that runs on 46 | a per-user basis. Daemons should not attempt to display UI or interact directly with a user's login session. Any and all work that involves interacting 47 | with a user should be done through agents. 48 | .Pp 49 | If you wish your service to run as a certain user, in that user's environment, making it a 50 | .Nm launchd 51 | agent is the ONLY supported means of accomplishing this on Mac OS X. In other words, it is not sufficient to perform a 52 | .Xr setuid 2 53 | to become a user in the truest sense on Mac OS X. 54 | .Sh FILES 55 | .Bl -tag -width "/System/Library/LaunchDaemons" -compact 56 | .It Pa ~/Library/LaunchAgents 57 | Per-user agents provided by the user. 58 | .It Pa /Library/LaunchAgents 59 | Per-user agents provided by the administrator. 60 | .It Pa /Library/LaunchDaemons 61 | System-wide daemons provided by the administrator. 62 | .It Pa /System/Library/LaunchAgents 63 | Per-user agents provided by Mac OS X. 64 | .It Pa /System/Library/LaunchDaemons 65 | System-wide daemons provided by Mac OS X. 66 | .El 67 | .Sh SEE ALSO 68 | .Xr launchctl 1 , 69 | .Xr launchd.plist 5 , 70 | -------------------------------------------------------------------------------- /liblaunch/test/liblaunch_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 R. Tyler Croy, All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include "liblaunch_test.h" 20 | 21 | 22 | #include "launch_priv.h" 23 | #include "launch_internal.h" 24 | /* Verify _launch_init_globals() properly sets up a given launch_globals_t */ 25 | void test_launch_init_globals(void **s) { 26 | struct launch_globals_s data; 27 | void *prev_ptr = data.lc_mtx; 28 | _launch_init_globals(&data); 29 | assert_true(data.lc_mtx == prev_ptr); 30 | }; 31 | 32 | void setup_empty(void **s) { 33 | }; 34 | 35 | void teardown_launch_data(void **state) { 36 | launch_data_free((launch_data_t)(*state)); 37 | }; 38 | 39 | void test_launch_data_alloc(void **s) { 40 | launch_data_t data = launch_data_alloc(LAUNCH_DATA_INTEGER); 41 | *s = (void *)(data); 42 | assert_false(NULL == data); 43 | assert_true(data->type == LAUNCH_DATA_INTEGER); 44 | }; 45 | 46 | void test_launch_data_alloc_array(void **s) { 47 | launch_data_t data = launch_data_alloc(LAUNCH_DATA_ARRAY); 48 | *s = (void *)(data); 49 | assert_false(NULL == data); 50 | assert_true(data->type == LAUNCH_DATA_ARRAY); 51 | assert_false(NULL == data->_array); 52 | }; 53 | 54 | int main(void) { 55 | const UnitTest tests[] = { 56 | unit_test(test_host2wire_64), 57 | unit_test(test_host2wire_32), 58 | unit_test(test_host2wire_16), 59 | unit_test(test_host2wire_8), 60 | unit_test(test_wire2host_64), 61 | unit_test(test_wire2host_32), 62 | unit_test(test_wire2host_16), 63 | unit_test(test_wire2host_8), 64 | unit_test(test_launch_data_get_errno_null), 65 | unit_test(test_launch_data_get_errno), 66 | unit_test(test_launch_data_get_fd_null), 67 | unit_test(test_launch_data_get_integer_null), 68 | unit_test(test_launch_data_get_integer), 69 | unit_test(test_launch_data_get_bool_default), 70 | unit_test(test_launch_data_get_bool_false), 71 | unit_test(test_launch_init_globals), 72 | unit_test_setup_teardown(test_launch_data_alloc, setup_empty, teardown_launch_data), 73 | unit_test_setup_teardown(test_launch_data_alloc_array, setup_empty, teardown_launch_data), 74 | }; 75 | 76 | return run_tests(tests); 77 | } 78 | -------------------------------------------------------------------------------- /launchd/job_reply.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | subsystem job_reply 500; 22 | 23 | #include 24 | #include 25 | #include "job_types.defs" 26 | import "bootstrap.h"; 27 | import "vproc.h"; 28 | import "vproc_internal.h"; 29 | 30 | skip; /* create_server */ 31 | 32 | skip; /* reboot2 */ 33 | 34 | skip; /* check_in2 */ 35 | 36 | skip; /* register2 */ 37 | 38 | skip; /* look_up2 */ 39 | 40 | simpleroutine 41 | job_mig_send_signal_reply( 42 | rp : mach_port_move_send_once_t; 43 | kr : kern_return_t, RetCode 44 | ); 45 | 46 | skip; /* parent */ 47 | 48 | skip; /* post_fork_ping */ 49 | 50 | skip; /* info */ 51 | 52 | skip; /* subset */ 53 | 54 | skip; /* setup_shmem */ 55 | 56 | skip; /* take_subset */ 57 | 58 | skip; /* getsocket */ 59 | 60 | skip; /* spawn */ 61 | 62 | skip; /* wait */ 63 | 64 | skip; /* uncork_fork */ 65 | 66 | skip; /* swap_integer */ 67 | 68 | skip; /* log */ 69 | 70 | skip; /* lookup_per_user_context */ 71 | 72 | skip; /* move_subset */ 73 | 74 | skip; /* swap_complex */ 75 | 76 | simpleroutine 77 | job_mig_log_drain_reply( 78 | rp : mach_port_move_send_once_t; 79 | kr : kern_return_t, RetCode; 80 | outval : pointer_t 81 | ); 82 | 83 | skip; /* log_forward */ 84 | 85 | skip; /* kickstart */ 86 | 87 | skip; /* embedded_wait */ 88 | 89 | skip; /* lookup_children */ 90 | 91 | skip; /* switch_to_session */ 92 | 93 | skip; /* transaction_count_for_pid */ 94 | 95 | skip; /* pid_is_managed */ 96 | 97 | skip; /* port_for_label */ 98 | 99 | skip; /* init_session */ 100 | 101 | skip; /* set_security_session */ 102 | 103 | skip; /* wait2 */ 104 | 105 | skip; /* event_source_check_in */ 106 | 107 | skip; /* event_set_state */ 108 | 109 | simpleroutine 110 | job_mig_spawn2_reply( 111 | rp : mach_port_move_send_once_t; 112 | kr : kern_return_t, RetCode; 113 | pid : pid_t; 114 | obsrvp : mach_port_move_receive_t 115 | ); 116 | 117 | skip; /* get_root_bootstrap */ 118 | 119 | skip; /* legacy_ipc_request */ 120 | -------------------------------------------------------------------------------- /liblaunch/bootstrap_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __BOOTSTRAP_PRIVATE_H__ 22 | #define __BOOTSTRAP_PRIVATE_H__ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | __BEGIN_DECLS 29 | 30 | #pragma GCC visibility push(default) 31 | 32 | #define BOOTSTRAP_PER_PID_SERVICE (1 << 0) 33 | #define BOOTSTRAP_ALLOW_LOOKUP (1 << 1) 34 | #define BOOTSTRAP_DENY_JOB_CREATION (1 << 2) 35 | #define BOOTSTRAP_PRIVILEGED_SERVER (1 << 3) 36 | #define BOOTSTRAP_FORCE_LOCAL (1 << 4) 37 | #define BOOTSTRAP_SPECIFIC_INSTANCE (1 << 5) 38 | #define BOOTSTRAP_STRICT_CHECKIN (1 << 6) 39 | #define BOOTSTRAP_STRICT_LOOKUP (1 << 7) 40 | 41 | #define BOOTSTRAP_PROPERTY_EXPLICITSUBSET (1 << 0) /* Created via bootstrap_subset(). */ 42 | #define BOOTSTRAP_PROPERTY_IMPLICITSUBSET (1 << 1) /* Created via _vprocmgr_switch_to_session(). */ 43 | #define BOOTSTRAP_PROPERTY_MOVEDSUBSET (1 << 2) /* Created via _vprocmgr_move_subset_to_user(). */ 44 | #define BOOTSTRAP_PROPERTY_PERUSER (1 << 3) /* A per-user launchd's root bootstrap. */ 45 | #define BOOTSTRAP_PROPERTY_XPC_DOMAIN (1 << 4) /* An XPC domain. Duh. */ 46 | #define BOOTSTRAP_PROPERTY_XPC_SINGLETON (1 << 5) /* A singleton XPC domain. */ 47 | 48 | void bootstrap_init(void); 49 | 50 | kern_return_t bootstrap_register2(mach_port_t bp, name_t service_name, mach_port_t sp, uint64_t flags); 51 | 52 | kern_return_t bootstrap_look_up2(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, uint64_t flags); 53 | 54 | kern_return_t bootstrap_check_in2(mach_port_t bp, const name_t service_name, mach_port_t *sp, uint64_t flags); 55 | 56 | kern_return_t bootstrap_look_up_per_user(mach_port_t bp, const name_t service_name, uid_t target_user, mach_port_t *sp); 57 | 58 | kern_return_t bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, bootstrap_property_array_t *properties, mach_msg_type_number_t *n_children); 59 | 60 | kern_return_t bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags); 61 | 62 | kern_return_t bootstrap_check_in3(mach_port_t bp, const name_t service_name, mach_port_t *sp, uuid_t instance_id, uint64_t flags); 63 | 64 | kern_return_t bootstrap_get_root(mach_port_t bp, mach_port_t *root); 65 | 66 | #pragma GCC visibility pop 67 | 68 | __END_DECLS 69 | 70 | #endif /* __BOOTSTRAP_PRIVATE_H__ */ 71 | -------------------------------------------------------------------------------- /SystemStarter/SystemStarter.8: -------------------------------------------------------------------------------- 1 | .Dd April 12, 2002 2 | .Dt SystemStarter 8 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm SystemStarter 6 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 7 | .\" words here as the database is built based on the words here and in the .ND line. 8 | .\" Use .Nm macro to designate other names for the documented program. 9 | .Nd Start, stop, and restart system services 10 | .Sh SYNOPSIS 11 | .Nm 12 | .Op Fl gvxdDqn 13 | .Op Ar action Op Ar service 14 | .Sh DESCRIPTION 15 | The 16 | .Nm 17 | utility is deprecated. System services should instead be described by a 18 | .Xr launchd.plist 5 . 19 | See 20 | .Xr launchd 8 21 | for more details. 22 | The 23 | .Nm launchd 24 | utility is available on Mac OS X 10.4 and later. 25 | .Pp 26 | In earlier versions of Mac OS X, the 27 | .Nm 28 | utility is used to start, stop, and restart the system services which 29 | are described in the 30 | .Pa /Library/StartupItems/ 31 | and 32 | .Pa /System/Library/StartupItems/ 33 | paths. 34 | .Pp 35 | The optional 36 | .Ar action 37 | argument specifies which action 38 | .Nm 39 | performs on the startup items. The optional 40 | .Ar service 41 | argument specifies which startup items to perform the action on. If no 42 | .Ar service 43 | is specified, all startup items will be acted on; otherwise, only the item providing the 44 | .Ar service , 45 | any items it requires, or any items that depend on it will be acted on. 46 | .Pp 47 | During boot 48 | .Nm 49 | is invoked by 50 | .Xr launchd 8 51 | and is responsible for 52 | starting all startup items in an order that satisfies each item's 53 | requirements. 54 | .Sh ACTIONS 55 | .Bl -tag -width -indent 56 | .It Nm start 57 | start all items, or start the item that provides the specified 58 | .Ar service 59 | and all items providing services it requires. 60 | .It Nm stop 61 | stop all items, or stop the item that provides the specified 62 | .Ar service 63 | and all items that depend on it. 64 | .It Nm restart 65 | restart all items, or restart the item providing the specified 66 | .Ar service . 67 | .El 68 | .Sh OPTIONS 69 | .Bl -tag -width -indent 70 | .It Fl g 71 | (ignored) 72 | .It Fl v 73 | verbose (text mode) startup 74 | .It Fl x 75 | (ignored) 76 | .It Fl r 77 | (ignored) 78 | .It Fl d 79 | print debugging output 80 | .It Fl D 81 | print debugging output and dependencies 82 | .It Fl q 83 | be quiet (disable debugging output) 84 | .It Fl n 85 | don't actually perform action on items (no-run mode) 86 | .El 87 | .Sh NOTES 88 | Unless an explicit call to 89 | .Nm ConsoleMessage 90 | is made, 91 | .Nm 92 | examines the exit status of the startup item scripts to determine the success or failure of the services provided by that script. 93 | .Pp 94 | .Sh FILES 95 | .Bl -tag -width -/System/Library/StartupItems -compact 96 | .It Pa /Library/StartupItems/ 97 | User-installed startup items. 98 | .It Pa /System/Library/StartupItems/ 99 | System-provided startup items. 100 | .El 101 | .Sh SEE ALSO 102 | .\" List links in ascending order by section, alphabetically within a section. 103 | .\" Please do not reference files that do not exist without filing a bug report 104 | .Xr ConsoleMessage 8 , 105 | .Xr launchd 8 , 106 | .Xr launchd.plist 5 , 107 | .Xr rc 8 108 | .\" .Sh BUGS \" Document known, unremedied bugs 109 | .Sh HISTORY 110 | The 111 | .Nm 112 | utility appeared in Darwin 1.0 and 113 | was extended in Darwin 6.0 to support partial startup and interprocess communication. 114 | .Nm 115 | was deprecated by 116 | .Xr launchd 8 117 | in Darwin 8.0. 118 | -------------------------------------------------------------------------------- /SystemStarter/SystemStarterIPC.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SystemStarterIPC.h - System Starter IPC definitions 3 | * Wilfredo Sanchez | wsanchez@opensource.apple.com 4 | * Kevin Van Vechten | kevinvv@uclink4.berkeley.edu 5 | ** 6 | * Copyright (c) 1999-2001 Apple Computer, Inc. All rights reserved. 7 | * 8 | * @APPLE_APACHE_LICENSE_HEADER_START@ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | * @APPLE_APACHE_LICENSE_HEADER_END@ 23 | ** 24 | * Definitions used for IPC communications with SystemStarter. 25 | * SystemStarter listens on a CFMessagePort with the name defined by 26 | * kSystemStarterMessagePort. The messageID of each message should 27 | * be set to the kIPCProtocolVersion constant. The contents of each 28 | * message should be an XML plist containing a dictionary using 29 | * the keys defined in this file. 30 | **/ 31 | 32 | #ifndef _SYSTEM_STARTER_IPC_H 33 | #define _SYSTEM_STARTER_IPC_H 34 | 35 | #include 36 | #include 37 | 38 | /* Compatible with inline CFMessagePort messages. */ 39 | typedef struct SystemStarterIPCMessage { 40 | mach_msg_header_t aHeader; 41 | mach_msg_body_t aBody; 42 | SInt32 aProtocol; 43 | SInt32 aByteLength; 44 | /* Data follows. */ 45 | } SystemStarterIPCMessage; 46 | 47 | /* Name of the CFMessagePort SystemStarter listens on. */ 48 | #define kSystemStarterMessagePort "com.apple.SystemStarter" 49 | 50 | /* kIPCProtocolVersion should be passed as the messageID of the CFMessage. */ 51 | #define kIPCProtocolVersion 0 52 | 53 | /* kIPCTypeKey should be provided for all messages. */ 54 | #define kIPCMessageKey CFSTR("Message") 55 | 56 | /* Messages are one of the following types: */ 57 | #define kIPCConsoleMessage CFSTR("ConsoleMessage") 58 | #define kIPCStatusMessage CFSTR("StatusMessage") 59 | #define kIPCQueryMessage CFSTR("QueryMessage") 60 | #define kIPCLoadDisplayBundleMessage CFSTR("LoadDisplayBundle") 61 | #define kIPCUnloadDisplayBundleMessage CFSTR("UnloadDisplayBundle") 62 | 63 | /* kIPCServiceNameKey identifies a startup item by one of the services it provides. */ 64 | #define kIPCServiceNameKey CFSTR("ServiceName") 65 | 66 | /* kIPCProcessIDKey identifies a running startup item by its process id. */ 67 | #define kIPCProcessIDKey CFSTR("ProcessID") 68 | 69 | /* kIPCConsoleMessageKey contains the non-localized string to 70 | * display for messages of type kIPCTypeConsoleMessage. 71 | */ 72 | #define kIPCConsoleMessageKey CFSTR("ConsoleMessage") 73 | 74 | /* kIPCStatus key contains a boolean value. True for success, false for failure. */ 75 | #define kIPCStatusKey CFSTR("StatusKey") 76 | 77 | /* kIPCDisplayBundlePathKey contains a string path to the display bundle 78 | SystemStarter should attempt to load. */ 79 | #define kIPCDisplayBundlePathKey CFSTR("DisplayBundlePath") 80 | 81 | /* kIPCConfigNamegKey contains the name of a config setting to query */ 82 | #define kIPCConfigSettingKey CFSTR("ConfigSetting") 83 | 84 | /* Some config settings */ 85 | #define kIPCConfigSettingVerboseFlag CFSTR("VerboseFlag") 86 | #define kIPCConfigSettingNetworkUp CFSTR("NetworkUp") 87 | 88 | #endif /* _SYSTEM_STARTER_IPC_H */ 89 | -------------------------------------------------------------------------------- /liblaunch/launch_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2012 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCH_INTERNAL_H__ 22 | #define __LAUNCH_INTERNAL_H__ 23 | 24 | #include "vproc_priv.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #if __has_include() 31 | #include 32 | #if defined(OS_ALLOC_ONCE_KEY_LIBLAUNCH) 33 | #define _LIBLAUNCH_HAS_ALLOC_ONCE 1 34 | #endif 35 | #endif 36 | 37 | enum { 38 | LAUNCHD_USE_CHECKIN_FD, 39 | LAUNCHD_USE_OTHER_FD, 40 | }; 41 | struct _launch { 42 | void *sendbuf; 43 | int *sendfds; 44 | void *recvbuf; 45 | int *recvfds; 46 | size_t sendlen; 47 | size_t sendfdcnt; 48 | size_t recvlen; 49 | size_t recvfdcnt; 50 | int which; 51 | int cifd; 52 | int fd; 53 | }; 54 | 55 | typedef struct _launch *launch_t; 56 | 57 | struct launch_globals_s { 58 | // liblaunch.c 59 | pthread_once_t lc_once; 60 | pthread_mutex_t lc_mtx; 61 | launch_t l; 62 | launch_data_t async_resp; 63 | 64 | launch_t in_flight_msg_recv_client; 65 | 66 | int64_t s_am_embedded_god; 67 | 68 | // libvproc.c 69 | dispatch_queue_t _vproc_gone2zero_queue; 70 | _vproc_transaction_callout _vproc_gone2zero_callout; 71 | void *_vproc_gone2zero_ctx; 72 | 73 | dispatch_once_t _vproc_transaction_once; 74 | uint64_t _vproc_transaction_enabled; 75 | dispatch_queue_t _vproc_transaction_queue; 76 | int64_t _vproc_transaction_cnt; 77 | }; 78 | typedef struct launch_globals_s *launch_globals_t; 79 | 80 | void _launch_init_globals(launch_globals_t globals); 81 | 82 | #if !_LIBLAUNCH_HAS_ALLOC_ONCE 83 | launch_globals_t _launch_globals_impl(void); 84 | #endif 85 | 86 | __attribute__((__pure__)) 87 | static inline launch_globals_t 88 | _launch_globals(void) { 89 | #if _LIBLAUNCH_HAS_ALLOC_ONCE 90 | return (launch_globals_t)os_alloc_once(OS_ALLOC_ONCE_KEY_LIBLAUNCH, 91 | sizeof(struct launch_globals_s), 92 | (void*)&_launch_init_globals); 93 | #else 94 | return _launch_globals_impl(); 95 | #endif 96 | } 97 | 98 | #pragma GCC visibility push(default) 99 | 100 | #define LAUNCHD_DB_PREFIX "/private/var/db/launchd.db" 101 | #define LAUNCHD_LOG_PREFIX "/private/var/log" 102 | 103 | #define LAUNCHD_JOB_DEFAULTS "Defaults" 104 | #define LAUNCHD_JOB_DEFAULTS_CACHED "CachedDefaults" 105 | 106 | launch_t launchd_fdopen(int, int); 107 | int launchd_getfd(launch_t); 108 | void launchd_close(launch_t, __typeof__(close) closefunc); 109 | 110 | launch_data_t launch_data_new_errno(int); 111 | bool launch_data_set_errno(launch_data_t, int); 112 | 113 | int launchd_msg_send(launch_t, launch_data_t); 114 | int launchd_msg_recv(launch_t, void (*)(launch_data_t, void *), void *); 115 | 116 | size_t launch_data_pack(launch_data_t d, void *where, size_t len, int *fd_where, size_t *fdslotsleft); 117 | launch_data_t launch_data_unpack(void *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset); 118 | 119 | #pragma GCC visibility pop 120 | 121 | #endif /* __LAUNCH_INTERNAL_H__*/ 122 | -------------------------------------------------------------------------------- /launchd/protocol_jobmgr.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | /* 21 | * bootstrap -- fundamental service initiator and port server 22 | * Mike DeMoney, NeXT, Inc. 23 | * Copyright, 1990. All rights reserved. 24 | */ 25 | 26 | subsystem bootstrap 400; 27 | 28 | #include 29 | #include 30 | #include "launchd_mig_types.defs" 31 | import "bootstrap_public.h"; 32 | import "bootstrap_private.h"; 33 | 34 | userprefix vproc_mig_; 35 | serverprefix job_mig_; 36 | 37 | routine create_server( 38 | __bs_port : job_t; 39 | __server_cmd : cmd_t; 40 | __server_uid : natural_t; 41 | __on_demand : boolean_t; 42 | ServerAuditToken __token : audit_token_t; 43 | out __server_port : mach_port_make_send_t); 44 | 45 | skip; /* Last used in 10.4. Was bootstrap_unprivileged() */ 46 | 47 | routine check_in( 48 | __bs_port : job_t; 49 | __service_name : name_t; 50 | ServerAuditToken __token : audit_token_t; 51 | out __service_port : mach_port_move_receive_t); 52 | 53 | routine register( 54 | __bs_port : job_t; 55 | ServerAuditToken __token : audit_token_t; 56 | __service_name : name_t; 57 | __service_port : mach_port_t); 58 | 59 | routine look_up( 60 | __bs_port : job_t; 61 | ServerAuditToken __token : audit_token_t; 62 | __service_name : name_t; 63 | out __service_port : mach_port_send_t); 64 | 65 | skip; /* last used in 10.4 */ 66 | 67 | routine parent( 68 | __bs_port : job_t; 69 | out __parent_port : mach_port_send_t); 70 | 71 | skip; /* last used in 10.4 */ 72 | 73 | routine info( 74 | __bs_port : job_t; 75 | out __service_names : name_array_t, dealloc; 76 | out __service_active : bootstrap_status_array_t, dealloc); 77 | 78 | routine subset( 79 | __bs_port : job_t; 80 | __requestor_port: mach_port_t; 81 | out __subset_port : mach_port_make_send_t); 82 | 83 | routine create_service( 84 | __bs_port : job_t; 85 | __service_name : name_t; 86 | out __service_port : mach_port_t); 87 | 88 | routine transfer_subset( 89 | __bs_port : job_t; 90 | out __bs_reqport : mach_port_t; 91 | out __bs_rcvright : mach_port_move_receive_t; 92 | out __service_names : name_array_t, dealloc; 93 | out __service_pids : pointer_t, dealloc; 94 | out __service_ports : mach_port_array_t, dealloc); 95 | 96 | routine getsocket( 97 | __bs_port : job_t; 98 | out __sockpath : name_t); 99 | 100 | routine spawn( 101 | __bs_port : job_t; 102 | ServerAuditToken __token : audit_token_t; 103 | __chars : _internal_string_t; 104 | __argc : uint32_t; 105 | __envc : uint32_t; 106 | __flags : uint64_t; 107 | __umask : uint16_t; 108 | out __pid : pid_t; 109 | out __obsvr_port : mach_port_make_send_t); 110 | 111 | routine wait( 112 | __bs_port : job_t; 113 | sreplyport __rport : mach_port_make_send_once_t; 114 | ServerAuditToken __token : audit_token_t; 115 | out __waitval : integer_t); 116 | 117 | routine uncork_fork( 118 | __bs_port : job_t; 119 | ServerAuditToken __token : audit_token_t); 120 | 121 | /* Essentially the inverse of bootstrap_unprivileged() */ 122 | routine get_self( 123 | __bs_port : job_t; 124 | ServerAuditToken __token : audit_token_t; 125 | out __job_port : mach_port_make_send_t); 126 | -------------------------------------------------------------------------------- /liblaunch/vproc_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __VPROC_INTERNAL_H__ 22 | #define __VPROC_INTERNAL_H__ 23 | 24 | #if HAS_MACH 25 | #include 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "launch.h" 33 | #ifdef __APPLE__ 34 | #include "bootstrap_priv.h" 35 | #endif 36 | #include "vproc.h" 37 | 38 | typedef char * _internal_string_t; 39 | typedef char * logmsg_t; 40 | typedef pid_t * pid_array_t; 41 | #if HAS_MACH 42 | typedef mach_port_t vproc_mig_t; 43 | #else 44 | #warning "PORT: vproc_mig_t ifdef'd out, used in job_types.defs" 45 | #endif 46 | 47 | #if defined(job_MSG_COUNT) || defined (xpc_domain_MSG_COUNT) 48 | /* HACK */ 49 | #include "core.h" 50 | #endif 51 | 52 | #define VPROC_ERR_TRY_PER_USER 1099 53 | 54 | #pragma GCC visibility push(default) 55 | 56 | vproc_err_t _vprocmgr_init(const char *session_type); 57 | vproc_err_t _vproc_post_fork_ping(void); 58 | 59 | #if !TARGET_OS_EMBEDDED 60 | #define _audit_session_self(v) (mach_port_t)syscall(SYS_audit_session_self) 61 | #define _audit_session_join(s) (au_asid_t)syscall(SYS_audit_session_join, session) 62 | #else 63 | #define _audit_session_self(v) MACH_PORT_NULL 64 | #define _audit_session_join(s) 0 65 | #endif 66 | 67 | #define __LAUNCH_MACH_PORT_CONTEXT_T_DEFINED__ 0 68 | 69 | #define SPAWN_HAS_PATH 0x0001 70 | #define SPAWN_HAS_WDIR 0x0002 71 | #define SPAWN_HAS_UMASK 0x0004 72 | #define SPAWN_WANTS_WAIT4DEBUGGER 0x0008 73 | 74 | #ifdef __APPLE__ 75 | kern_return_t 76 | _vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, launch_data_t *outval, 77 | mach_port_array_t *ports, mach_msg_type_number_t *portCnt); 78 | 79 | kern_return_t _vprocmgr_getsocket(name_t); 80 | #else 81 | #warning "PORT: _vproc_grab_subset() What is this for?" 82 | #endif 83 | 84 | struct logmsg_s { 85 | union { 86 | STAILQ_ENTRY(logmsg_s) sqe; 87 | uint64_t __pad; 88 | }; 89 | int64_t when; 90 | pid_t from_pid; 91 | pid_t about_pid; 92 | uid_t sender_uid; 93 | gid_t sender_gid; 94 | int err_num; 95 | int pri; 96 | union { 97 | const char *from_name; 98 | uint64_t from_name_offset; 99 | }; 100 | union { 101 | const char *about_name; 102 | uint64_t about_name_offset; 103 | }; 104 | union { 105 | const char *session_name; 106 | uint64_t session_name_offset; 107 | }; 108 | union { 109 | const char *msg; 110 | uint64_t msg_offset; 111 | }; 112 | uint64_t obj_sz; 113 | char data[0]; 114 | }; 115 | 116 | 117 | #ifdef __APPLE__ 118 | vproc_err_t _vprocmgr_log_forward(mach_port_t mp, void *data, size_t len); 119 | 120 | kern_return_t 121 | bootstrap_info(mach_port_t bp, 122 | name_array_t *service_names, 123 | mach_msg_type_number_t *service_namesCnt, 124 | name_array_t *service_jobs, 125 | mach_msg_type_number_t *service_jobsCnt, 126 | bootstrap_status_array_t *service_active, 127 | mach_msg_type_number_t *service_activeCnt, 128 | uint64_t flags); 129 | #else 130 | #warning "PORT: bootstrap_info(): is this only for bootstrap servics?" 131 | #endif 132 | 133 | #pragma GCC visibility pop 134 | 135 | #endif /* __VPROC_INTERNAL_H__ */ 136 | -------------------------------------------------------------------------------- /SystemStarter/StartupItems.h: -------------------------------------------------------------------------------- 1 | /** 2 | * StartupItems.h - Startup Item management routines 3 | * Wilfredo Sanchez | wsanchez@opensource.apple.com 4 | * Kevin Van Vechten | kevinvv@uclink4.berkeley.edu 5 | * $Apple$ 6 | ** 7 | * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. 8 | * 9 | * @APPLE_APACHE_LICENSE_HEADER_START@ 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | * 23 | * @APPLE_APACHE_LICENSE_HEADER_END@ 24 | **/ 25 | 26 | #ifndef _StartupItems_H_ 27 | #define _StartupItems_H_ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include "SystemStarter.h" 35 | 36 | #define kProvidesKey CFSTR("Provides") 37 | #define kRequiresKey CFSTR("Requires") 38 | #define kDescriptionKey CFSTR("Description") 39 | #define kUsesKey CFSTR("Uses") 40 | #define kErrorKey CFSTR("Error") 41 | #define kBundlePathKey CFSTR("PathToBundle") 42 | #define kPIDKey CFSTR("ProcessID") 43 | #define kDomainKey CFSTR("Domain") 44 | 45 | 46 | #define kErrorPermissions CFSTR("incorrect permissions") 47 | #define kErrorInternal CFSTR("SystemStarter internal error") 48 | #define kErrorReturnNonZero CFSTR("execution of Startup script failed") 49 | #define kErrorFork CFSTR("could not fork() StartupItem") 50 | 51 | 52 | /* 53 | * Find all available startup items in NSDomains specified by aMask. 54 | */ 55 | CFMutableArrayRef StartupItemListCreateWithMask (NSSearchPathDomainMask aMask); 56 | 57 | /* 58 | * Returns the item responsible for providing aService. 59 | */ 60 | CFMutableDictionaryRef StartupItemListGetProvider (CFArrayRef anItemList, CFStringRef aService); 61 | 62 | /* 63 | * Creates a list of items in anItemList which depend on anItem, given anAction. 64 | */ 65 | CFMutableArrayRef StartupItemListCreateDependentsList (CFMutableArrayRef anItemList, 66 | CFStringRef aService , 67 | Action anAction ); 68 | 69 | /* 70 | * Given aWaitingList of startup items, and aStatusDict describing the current 71 | * startup state, returns the next startup item to run, if any. Returns nil if 72 | * none is available. 73 | * Note that this is not necessarily deterministic; if more than one startup 74 | * item is ready to run, which item gets returned is not specified. An item is 75 | * not ready to run if the specified dependencies are not satisfied yet. 76 | */ 77 | CFMutableDictionaryRef StartupItemListGetNext (CFArrayRef aWaitingList, 78 | CFDictionaryRef aStatusDict , 79 | Action anAction ); 80 | 81 | CFMutableDictionaryRef StartupItemWithPID (CFArrayRef anItemList, pid_t aPID); 82 | pid_t StartupItemGetPID(CFDictionaryRef anItem); 83 | 84 | CFStringRef StartupItemCreateDescription(CFMutableDictionaryRef anItem); 85 | 86 | /* 87 | * Returns a list of currently executing startup items. 88 | */ 89 | CFArrayRef StartupItemListCreateFromRunning(CFArrayRef anItemList); 90 | 91 | /* 92 | * Returns the total number of "Provides" entries of all loaded items. 93 | */ 94 | CFIndex StartupItemListCountServices (CFArrayRef anItemList); 95 | 96 | 97 | /* 98 | * Utility functions 99 | */ 100 | void RemoveItemFromWaitingList(StartupContext aStartupContext, CFMutableDictionaryRef anItem); 101 | void AddItemToFailedList(StartupContext aStartupContext, CFMutableDictionaryRef anItem); 102 | 103 | /* 104 | * Run the startup item. 105 | */ 106 | int StartupItemRun (CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Action anAction); 107 | void StartupItemExit (CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Boolean aSuccess); 108 | void StartupItemSetStatus(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, CFStringRef aServiceName, Boolean aSuccess, Boolean aReplaceFlag); 109 | 110 | /* 111 | * Check whether file was created before boot and has proper permissions to run. 112 | */ 113 | bool StartupItemSecurityCheck(const char *aPath); 114 | 115 | #endif /* _StartupItems_H_ */ 116 | -------------------------------------------------------------------------------- /SystemStarter/IPC.c: -------------------------------------------------------------------------------- 1 | /** 2 | * IPC.c - System Starter IPC routines 3 | * Wilfredo Sanchez | wsanchez@opensource.apple.com 4 | * Kevin Van Vechten | kevinvv@uclink4.berkeley.edu 5 | * $Apple$ 6 | ** 7 | * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. 8 | * 9 | * @APPLE_APACHE_LICENSE_HEADER_START@ 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | * 23 | * @APPLE_APACHE_LICENSE_HEADER_END@ 24 | **/ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "bootstrap.h" 34 | 35 | #include "IPC.h" 36 | #include "StartupItems.h" 37 | #include "SystemStarter.h" 38 | #include "SystemStarterIPC.h" 39 | 40 | /* Structure to pass StartupContext and anItem to the termination handler. */ 41 | typedef struct TerminationContextStorage { 42 | StartupContext aStartupContext; 43 | CFMutableDictionaryRef anItem; 44 | } *TerminationContext; 45 | 46 | /** 47 | * A CFMachPort invalidation callback that records the termination of 48 | * a startup item task. Stops the current run loop to give system_starter 49 | * another go at running items. 50 | **/ 51 | static void 52 | startupItemTerminated(CFMachPortRef aMachPort, void *anInfo) 53 | { 54 | TerminationContext aTerminationContext = (TerminationContext) anInfo; 55 | 56 | if (aMachPort) { 57 | mach_port_deallocate(mach_task_self(), CFMachPortGetPort(aMachPort)); 58 | } 59 | if (aTerminationContext && aTerminationContext->anItem) { 60 | pid_t aPID = 0; 61 | pid_t rPID = 0; 62 | int aStatus = 0; 63 | CFMutableDictionaryRef anItem = aTerminationContext->anItem; 64 | StartupContext aStartupContext = aTerminationContext->aStartupContext; 65 | 66 | /* Get the exit status */ 67 | if (anItem) { 68 | aPID = StartupItemGetPID(anItem); 69 | if (aPID > 0) 70 | rPID = waitpid(aPID, &aStatus, 0); 71 | } 72 | if (aStartupContext) { 73 | --aStartupContext->aRunningCount; 74 | 75 | /* Record the item's status */ 76 | if (aStartupContext->aStatusDict) { 77 | StartupItemExit(aStartupContext->aStatusDict, anItem, (WIFEXITED(aStatus) && WEXITSTATUS(aStatus) == 0)); 78 | if (aStatus) { 79 | CF_syslog(LOG_WARNING, CFSTR("%@ (%d) did not complete successfully"), CFDictionaryGetValue(anItem, CFSTR("Description")), aPID); 80 | } else { 81 | CF_syslog(LOG_DEBUG, CFSTR("Finished %@ (%d)"), CFDictionaryGetValue(anItem, CFSTR("Description")), aPID); 82 | } 83 | } 84 | /* 85 | * If the item failed to start, then add it to the 86 | * failed list 87 | */ 88 | if (WEXITSTATUS(aStatus) || WTERMSIG(aStatus) || WCOREDUMP(aStatus)) { 89 | CFDictionarySetValue(anItem, kErrorKey, kErrorReturnNonZero); 90 | AddItemToFailedList(aStartupContext, anItem); 91 | } 92 | /* 93 | * Remove the item from the waiting list regardless 94 | * if it was successful or it failed. 95 | */ 96 | RemoveItemFromWaitingList(aStartupContext, anItem); 97 | } 98 | } 99 | if (aTerminationContext) 100 | free(aTerminationContext); 101 | } 102 | 103 | void 104 | MonitorStartupItem(StartupContext aStartupContext, CFMutableDictionaryRef anItem) 105 | { 106 | pid_t aPID = StartupItemGetPID(anItem); 107 | if (anItem && aPID > 0) { 108 | mach_port_t aPort; 109 | kern_return_t aResult; 110 | CFMachPortContext aContext; 111 | CFMachPortRef aMachPort; 112 | CFRunLoopSourceRef aSource; 113 | TerminationContext aTerminationContext = (TerminationContext) malloc(sizeof(struct TerminationContextStorage)); 114 | 115 | aTerminationContext->aStartupContext = aStartupContext; 116 | aTerminationContext->anItem = anItem; 117 | 118 | aContext.version = 0; 119 | aContext.info = aTerminationContext; 120 | aContext.retain = 0; 121 | aContext.release = 0; 122 | 123 | if ((aResult = task_name_for_pid(mach_task_self(), aPID, &aPort)) != KERN_SUCCESS) 124 | goto out_bad; 125 | 126 | if (!(aMachPort = CFMachPortCreateWithPort(NULL, aPort, NULL, &aContext, NULL))) 127 | goto out_bad; 128 | 129 | if (!(aSource = CFMachPortCreateRunLoopSource(NULL, aMachPort, 0))) { 130 | CFRelease(aMachPort); 131 | goto out_bad; 132 | } 133 | CFMachPortSetInvalidationCallBack(aMachPort, startupItemTerminated); 134 | CFRunLoopAddSource(CFRunLoopGetCurrent(), aSource, kCFRunLoopCommonModes); 135 | CFRelease(aSource); 136 | CFRelease(aMachPort); 137 | return; 138 | out_bad: 139 | /* 140 | * The assumption is something failed, the task already 141 | * terminated. 142 | */ 143 | startupItemTerminated(NULL, aTerminationContext); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /launchd/runtime.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCHD_RUNTIME_H__ 22 | #define __LAUNCHD_RUNTIME_H__ 23 | 24 | #ifdef __APPLE__ 25 | /* XPC is an IPC mechanism for Apple OSes that works with Grand Central 26 | * Dispatch. See here for more details: 27 | * 28 | */ 29 | #include 30 | #endif 31 | 32 | #if HAS_MACH 33 | #include 34 | #endif 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "kill2.h" 43 | #ifdef __APPLE__ 44 | #include "ktrace.h" 45 | #endif 46 | #include "log.h" 47 | 48 | #define likely(x) __builtin_expect((bool)(x), true) 49 | #define unlikely(x) __builtin_expect((bool)(x), false) 50 | 51 | struct ldcred { 52 | uid_t euid; 53 | uid_t uid; 54 | gid_t egid; 55 | gid_t gid; 56 | pid_t pid; 57 | au_asid_t asid; 58 | mach_port_t asport; 59 | }; 60 | 61 | typedef void (*kq_callback)(void *, struct kevent *); 62 | typedef boolean_t (*mig_callback)(mach_msg_header_t *, mach_msg_header_t *); 63 | typedef void (*timeout_callback)(void); 64 | 65 | extern bool launchd_verbose_boot; 66 | /* Configuration knobs set in do_file_init(). */ 67 | extern bool launchd_shutdown_debugging; 68 | extern bool launchd_use_gmalloc; 69 | extern bool launchd_malloc_log_stacks; 70 | extern bool launchd_log_shutdown; 71 | extern bool launchd_log_debug; 72 | extern bool launchd_log_perf; 73 | extern bool launchd_trap_sigkill_bugs; 74 | extern bool launchd_no_jetsam_perm_check; 75 | extern bool launchd_osinstaller; 76 | extern bool launchd_allow_global_dyld_envvars; 77 | #if TARGET_OS_EMBEDDED 78 | extern bool launchd_appletv; 79 | #endif 80 | 81 | extern bool launchd_runtime_busy_time; 82 | extern mach_port_t inherited_bootstrap_port; 83 | extern size_t runtime_busy_cnt; 84 | extern int32_t launchd_sync_frequency; 85 | extern pid_t launchd_wsp; 86 | 87 | mach_port_t runtime_get_kernel_port(void); 88 | extern boolean_t launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply); 89 | 90 | void runtime_add_ref(void); 91 | void runtime_del_ref(void); 92 | void runtime_add_weak_ref(void); 93 | void runtime_del_weak_ref(void); 94 | void runtime_install_timer(void); 95 | void runtime_remove_timer(void); 96 | 97 | void launchd_runtime_init(void); 98 | void launchd_runtime_init2(void); 99 | void launchd_runtime(void) __attribute__((noreturn)); 100 | 101 | void launchd_log_vm_stats(void); 102 | 103 | int runtime_close(int fd); 104 | int runtime_fsync(int fd); 105 | 106 | #define RUNTIME_ADVISABLE_IDLE_TIMEOUT 30 107 | 108 | void runtime_set_timeout(timeout_callback to_cb, unsigned int sec); 109 | kern_return_t runtime_add_mport(mach_port_t name, mig_callback demux); 110 | kern_return_t runtime_remove_mport(mach_port_t name); 111 | void runtime_record_caller_creds(audit_token_t *token); 112 | struct ldcred *runtime_get_caller_creds(void); 113 | audit_token_t *runtime_get_caller_token(void); 114 | 115 | const char *signal_to_C_name(unsigned int sig); 116 | const char *reboot_flags_to_C_names(unsigned int flags); 117 | 118 | int kevent_bulk_mod(struct kevent *kev, size_t kev_cnt); 119 | int kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata); 120 | void log_kevent_struct(int level, struct kevent *kev_base, int indx); 121 | 122 | pid_t runtime_fork(mach_port_t bsport); 123 | 124 | mach_msg_return_t launchd_exc_runtime_once(mach_port_t port, mach_msg_size_t rcv_msg_size, mach_msg_size_t send_msg_size, mig_reply_error_t *bufRequest, mig_reply_error_t *bufReply, mach_msg_timeout_t to); 125 | 126 | int64_t runtime_get_wall_time(void) __attribute__((warn_unused_result)); 127 | uint64_t runtime_get_opaque_time(void) __attribute__((warn_unused_result)); 128 | uint64_t runtime_get_opaque_time_of_event(void) __attribute__((pure, warn_unused_result)); 129 | uint64_t runtime_opaque_time_to_nano(uint64_t o) __attribute__((const, warn_unused_result)); 130 | uint64_t runtime_get_nanoseconds_since(uint64_t o) __attribute__((pure, warn_unused_result)); 131 | 132 | kern_return_t launchd_set_bport(mach_port_t name); 133 | kern_return_t launchd_get_bport(mach_port_t *name); 134 | kern_return_t launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which); 135 | kern_return_t launchd_mport_create_recv(mach_port_t *name); 136 | kern_return_t launchd_mport_deallocate(mach_port_t name); 137 | kern_return_t launchd_mport_make_send(mach_port_t name); 138 | kern_return_t launchd_mport_copy_send(mach_port_t name); 139 | kern_return_t launchd_mport_make_send_once(mach_port_t name, mach_port_t *so); 140 | kern_return_t launchd_mport_close_recv(mach_port_t name); 141 | 142 | uint64_t runtime_get_uniqueid(void); 143 | 144 | #endif /* __LAUNCHD_RUNTIME_H__ */ 145 | -------------------------------------------------------------------------------- /liblaunch/vproc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __VPROC_H__ 22 | #define __VPROC_H__ 23 | 24 | #include 25 | #include 26 | #include 27 | #ifdef __APPLE__ 28 | #include 29 | #else 30 | #include "shims/Availability.h" 31 | #endif 32 | 33 | #ifndef VPROC_HAS_TRANSACTIONS 34 | #define VPROC_HAS_TRANSACTIONS 35 | #endif 36 | 37 | __BEGIN_DECLS 38 | 39 | #pragma GCC visibility push(default) 40 | 41 | typedef void * vproc_err_t; 42 | 43 | typedef struct vproc_s * vproc_t; 44 | typedef void * vprocmgr_t; 45 | 46 | const char *vproc_strerror(vproc_err_t r); 47 | 48 | /*! 49 | * @header vproc 50 | * 51 | * Processes have two reference counts associated with them: 52 | * 53 | * Transactions Tracks unfinished work. For example: saving a modified 54 | * document. 55 | * Standby Tracks outstanding callbacks from external subsystems. 56 | * 57 | * Descriptive aliases: 58 | * 59 | * A process with no outstanding transactions is called "clean." 60 | * A process with outstanding transactions is called "dirty." 61 | * A process with no standby work is called "idle." 62 | * 63 | * Sometimes, the operating system needs processes to exit. Unix has two 64 | * primary signals to kill applications: 65 | * 66 | * SIGKILL Not catchable by the application. 67 | * SIGTERM Catchable by the application. 68 | * 69 | * If a process is clean, the operating system is free to SIGKILL it at 70 | * shutdown or logout. This behavior is opt in. 71 | * 72 | * If a process is clean and idle, the operating system may send SIGKILL after 73 | * a application specified timeout. This behavior is opt in. 74 | * 75 | * If a process is dirty and idle, the operating system may send SIGTERM after 76 | * a application specified timeout. This behavior is opt in. 77 | * 78 | * 79 | * launchd jobs should update their property lists accordingly. 80 | * 81 | * We plan to have LaunchServices use private methods to coordinate 82 | * whether GUI applications have opted into this design. 83 | */ 84 | 85 | /*! 86 | * @typedef vproc_transaction_t 87 | * 88 | * @abstract 89 | * An opaque handle used to track outstanding transactions. 90 | */ 91 | typedef struct vproc_transaction_s *vproc_transaction_t; 92 | 93 | /*! 94 | * @function vproc_transaction_begin 95 | * 96 | * @param virtual_proc 97 | * This is meant for future API improvements. Pass NULL for now. 98 | * 99 | * @result 100 | * Returns an opaque handle to be passed to vproc_transaction_end(). 101 | * 102 | * @abstract 103 | * Call this API before creating data that needs to be saved via I/O later. 104 | */ 105 | vproc_transaction_t 106 | vproc_transaction_begin(vproc_t virtual_proc) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 107 | 108 | /*! 109 | * @function vproc_transaction_end 110 | * 111 | * @param virtual_proc 112 | * This is meant for future API improvements. Pass NULL for now. 113 | * 114 | * @param handle 115 | * The handle previously created with vproc_transaction_begin(). 116 | * 117 | * @abstract 118 | * Call this API after the data has either been flushed or otherwise resolved. 119 | * 120 | * @discussion 121 | * Calling this API with the same handle more than once is undefined. 122 | */ 123 | void 124 | vproc_transaction_end(vproc_t virtual_proc, vproc_transaction_t handle) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0); 125 | 126 | /*! 127 | * @typedef vproc_standby_t 128 | * 129 | * @abstract 130 | * An opaque handle used to track outstanding standby requests. 131 | */ 132 | typedef struct vproc_standby_s *vproc_standby_t; 133 | 134 | /*! 135 | * @function vproc_standby_begin 136 | * 137 | * @param virtual_proc 138 | * This is meant for future API improvements. Pass NULL for now. 139 | * 140 | * @result 141 | * Returns an opaque handle to be passed to vproc_standby_end(). 142 | * 143 | * @abstract 144 | * Call this API before registering notifications. For example: timers network 145 | * state change, or when monitoring keyboard/mouse events. 146 | * 147 | * @discussion 148 | * This API is undefined and is currently a no-op. 149 | */ 150 | vproc_standby_t 151 | vproc_standby_begin(vproc_t virtual_proc) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_NA); 152 | 153 | /*! 154 | * @function vproc_standby_end 155 | * 156 | * @param virtual_proc 157 | * This is meant for future API improvements. Pass NULL for now. 158 | * 159 | * @param handle 160 | * The handle previously created with vproc_standby_begin(). 161 | * 162 | * @abstract 163 | * Call this API when deregistering notifications. 164 | * 165 | * @discussion 166 | * Calling this API with the same handle more than once is undefined. 167 | * This API is undefined and is currently a no-op. 168 | */ 169 | void 170 | vproc_standby_end(vproc_t virtual_proc, vproc_standby_t handle) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_NA); 171 | 172 | #pragma GCC visibility pop 173 | 174 | __END_DECLS 175 | 176 | #endif /* __VPROC_H__ */ 177 | -------------------------------------------------------------------------------- /rc/rc.netboot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | # Copyright 2002-2009 Apple Inc. 4 | # 5 | # This script configures NetBoot 6 | ## 7 | 8 | . /etc/rc.common 9 | 10 | # 11 | # Define: NETBOOT_SHADOW 12 | # Purpose: 13 | # To change the behavior of the system when choosing a netboot shadow 14 | # to use. 15 | # Values: 16 | # -NETWORK- Try to use the network for the shadow file, if 17 | # that fails, use the local drive 18 | # -NETWORK_ONLY- Only use the network, fail if not available 19 | # -LOCAL- Use the local drive for the shadow file, if that 20 | # fails, use the network 21 | # -LOCAL_ONLY- Only use the local drive for the shadow, fail if 22 | # not available 23 | 24 | NETBOOT_MOUNT=/var/netboot 25 | NETBOOT_SHADOW=${NETBOOT_SHADOW:-NETWORK-} 26 | 27 | Failed() 28 | { 29 | echo rc.netboot: $1 30 | echo rc.netboot: $1 > /dev/console 31 | sleep 5 32 | exit 1 33 | } 34 | 35 | common_start() 36 | { 37 | netboot_dir=$1 38 | netboot_shadow=$2 39 | if [ "${netboot_dir}" = "" ] ; then 40 | Failed "netboot_dir is empty" 41 | fi 42 | if [ "${netboot_shadow}" = "" ] ; then 43 | Failed "netboot_shadow is empty" 44 | fi 45 | netboot_shadow="${netboot_dir}/${netboot_shadow}" 46 | if ! mkdir -p "${netboot_dir}" ; then 47 | Failed "create ${netboot_dir} failed" 48 | fi 49 | chmod 700 "${netboot_dir}" 50 | mount -u -o ro / 51 | root_device=$(mount | sed -n 's:/dev/\(.*\) on / .*:\1:p') 52 | case "${root_device}" in 53 | vn*) 54 | if ! touch "${netboot_shadow}" ; then 55 | Failed "create ${netboot_shadow} failed" 56 | fi 57 | chmod 600 "${netboot_shadow}" 58 | if ! /usr/libexec/vndevice shadow "/dev/r${root_device}" "${netboot_shadow}" ; then 59 | Failed "vndevice shadow failed" 60 | fi 61 | ;; 62 | "") 63 | Failed "root device unknown" 64 | ;; 65 | *) 66 | if ! touch "${netboot_shadow}" ; then 67 | Failed "failed to create shadow ${netboot_shadow}" 68 | fi 69 | chmod 600 "${netboot_shadow}" 70 | if ! /usr/bin/nbdst -recycle "${root_device}" "${netboot_shadow}" ; then 71 | Failed "nbdst failed" 72 | fi 73 | ;; 74 | esac 75 | } 76 | 77 | local_mount() 78 | { 79 | tries=0 80 | limit=11 81 | while [ $tries -lt $limit ]; do 82 | tries=$(( tries + 1 )) 83 | volinfo=`autodiskmount -F 2>/dev/null` 84 | if [ $? -ne 0 ]; then 85 | if [ $tries -lt $limit ]; then 86 | echo "Waiting for local drives..." 87 | echo "Waiting for local drives (retry ${tries}/$(( limit - 1 )))..." > /dev/console 88 | sleep 5 89 | else 90 | echo "autodiskmount -F found no local drives" 91 | return 1 92 | fi 93 | else 94 | tries=$limit 95 | fi 96 | done 97 | set ${volinfo} 98 | devname=$1 99 | fstype=$2 100 | 101 | mount -t "${fstype}" -o nosuid,nodev "/dev/${devname}" "${NETBOOT_MOUNT}" 2>&1 102 | if [ $? -ne 0 ]; then 103 | echo "mount of ${devname} failed" 104 | return 1 105 | fi 106 | common_start "${NETBOOT_MOUNT}/.com.apple.NetBootX" shadowfile 107 | return 0 108 | } 109 | 110 | network_mount() 111 | { 112 | mount_from=$(ipconfig netbootoption shadow_mount_path 2>&1) 113 | if [ $? -ne 0 ]; then 114 | echo "no network shadow mount path available" 115 | return 1 116 | fi 117 | shadow_path=$(ipconfig netbootoption shadow_file_path 2>&1) 118 | if [ $? -ne 0 ]; then 119 | echo "no network shadow file path available" 120 | return 1 121 | fi 122 | case "${mount_from}" in 123 | afp:*) 124 | fstype=afp 125 | kextload -v 0 /System/Library/Filesystems/AppleShare/asp_tcp.kext 126 | kextload -v 0 /System/Library/Filesystems/AppleShare/afpfs.kext 127 | ;; 128 | nfs:*) fstype=nfs;; 129 | *) echo "unknown network filesystem mount from ${mount_from}" 130 | return 1 131 | ;; 132 | esac 133 | mount -t "${fstype}" -o nobrowse "${mount_from}" "${NETBOOT_MOUNT}" 134 | if [ $? -ne 0 ]; then 135 | echo "mount -t ${fstype} -o nobrowse ${mount_from} ${NETBOOT_MOUNT} failed" 136 | return 1 137 | fi 138 | common_start "${NETBOOT_MOUNT}" "${shadow_path}" 139 | return 0 140 | } 141 | 142 | do_start() 143 | { 144 | case "${NETBOOT_SHADOW}" in 145 | -LOCAL_ONLY-) 146 | err=$(local_mount) 147 | if [ $? -ne 0 ]; then 148 | Failed "${err}" 149 | fi 150 | ;; 151 | -LOCAL-) 152 | err=$(local_mount) 153 | if [ $? -ne 0 ]; then 154 | err=$(network_mount) 155 | if [ $? -ne 0 ]; then 156 | Failed "Could not find a local or network drive" 157 | fi 158 | fi 159 | ;; 160 | -NETWORK_ONLY-) 161 | err=$(network_mount) 162 | if [ $? -ne 0 ]; then 163 | Failed "${err}" 164 | fi 165 | ;; 166 | 167 | *) 168 | err=$(network_mount) 169 | if [ $? -ne 0 ]; then 170 | err=$(local_mount) 171 | if [ $? -ne 0 ]; then 172 | Failed "Could not find a network or local drive" 173 | fi 174 | fi 175 | ;; 176 | esac 177 | 178 | } 179 | 180 | do_init() 181 | { 182 | # attach the shadow file to the root disk image 183 | do_start 184 | 185 | # make sure the root filesystem is clean 186 | fsck -p || fsck -fy || Failed "Could not clean root filesystem" 187 | 188 | # make it writable 189 | mount -uw / 190 | 191 | # adjust /private/var/vm to point to the writable area (if not diskless) 192 | swapdir=/private/var/vm 193 | mounted_from=$(mount | sed -n 's:\(.*\) on .*/var/netboot.*:\1:p') 194 | case "${mounted_from}" in 195 | /dev/*) 196 | netboot_dir="${NETBOOT_MOUNT}/.com.apple.NetBootX" 197 | if [ -d "${netboot_dir}" ]; then 198 | rm -rf "${swapdir}" 199 | ln -s "${netboot_dir}" "${swapdir}" 200 | fi 201 | ;; 202 | *) 203 | ;; 204 | esac 205 | 206 | # set the ComputerName based on what the NetBoot server told us it was 207 | machine_name=$(ipconfig netbootoption machine_name 2>&1) 208 | if [ $? -ne 0 ]; then 209 | echo "no machine name option available" 210 | else 211 | echo "Setting ComputerName to ${machine_name}" 212 | scutil --set ComputerName "${machine_name}" 213 | fi 214 | } 215 | 216 | 217 | if [ $# -lt 1 ] ; then 218 | exit 0 219 | fi 220 | 221 | command=$1 222 | 223 | shift 224 | 225 | case "${command}" in 226 | init) 227 | do_init $@ 228 | ;; 229 | esac 230 | 231 | ## 232 | # Exit 233 | ## 234 | exit 0 235 | -------------------------------------------------------------------------------- /launchd/job.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | /* 21 | * bootstrap -- fundamental service initiator and port server 22 | * Mike DeMoney, NeXT, Inc. 23 | * Copyright, 1990. All rights reserved. 24 | */ 25 | 26 | subsystem job 400; 27 | 28 | #include 29 | #include 30 | #include "job_types.defs" 31 | import "vproc.h"; 32 | import "vproc_priv.h"; 33 | import "vproc_internal.h"; 34 | 35 | userprefix vproc_mig_; 36 | serverprefix job_mig_; 37 | 38 | routine 39 | create_server( 40 | j : job_t; 41 | servercmd : cmd_t; 42 | serveruid : uid_t; 43 | ondemand : boolean_t; 44 | out serverport : mach_port_make_send_t 45 | ); 46 | 47 | routine 48 | reboot2( 49 | j : job_t; 50 | flags : uint64_t 51 | ); 52 | 53 | routine 54 | check_in2( 55 | j : job_t; 56 | servicename : name_t; 57 | out serviceport : mach_port_move_receive_t; 58 | out instanceid : uuid_t; 59 | flags : uint64_t 60 | ); 61 | 62 | routine 63 | register2( 64 | j : job_t; 65 | servicename : name_t; 66 | serviceport : mach_port_t; 67 | flags : uint64_t 68 | ); 69 | 70 | routine 71 | look_up2( 72 | j : job_t; 73 | sreplyport rp : mach_port_make_send_once_t; 74 | servicename : name_t; 75 | out serviceport : mach_port_t; 76 | UserAuditToken servercreds : audit_token_t; 77 | targetpid : pid_t; 78 | instanceid : uuid_t; 79 | flags : uint64_t 80 | ); 81 | 82 | routine 83 | send_signal( 84 | j : job_t; 85 | sreplyport rp : mach_port_make_send_once_t; 86 | label : name_t; 87 | sig : integer_t 88 | ); 89 | 90 | routine 91 | parent( 92 | j : job_t; 93 | sreplyport rp : mach_port_make_send_once_t; 94 | out parentport : mach_port_make_send_t 95 | ); 96 | 97 | routine 98 | post_fork_ping( 99 | j : job_t; 100 | taskport : task_t; 101 | out asport : mach_port_t 102 | ); 103 | 104 | routine 105 | info( 106 | j : job_t; 107 | out names : name_array_t, dealloc; 108 | out jobs : name_array_t, dealloc; 109 | out actives : bootstrap_status_array_t, dealloc; 110 | flags : uint64_t 111 | ); 112 | 113 | routine 114 | subset( 115 | j : job_t; 116 | reqport : mach_port_t; 117 | out subsetport : mach_port_make_send_t 118 | ); 119 | 120 | skip; /* Formerly setup_shmem. */ 121 | 122 | routine 123 | take_subset( 124 | j : job_t; 125 | out reqport : mach_port_move_send_t; 126 | out recvport : mach_port_move_receive_t; 127 | out jobs : pointer_t, dealloc; 128 | out ports : mach_port_move_send_array_t, dealloc 129 | ); 130 | 131 | routine 132 | getsocket( 133 | j : job_t; 134 | out sockpath : name_t 135 | ); 136 | 137 | skip; /* Formerly spawn. */ 138 | 139 | skip; /* Formerly wait. */ 140 | 141 | skip; /* Formerly uncork_fork. */ 142 | 143 | routine 144 | swap_integer( 145 | j : job_t; 146 | inkey : vproc_gsk_t; 147 | outkey : vproc_gsk_t; 148 | inval : int64_t; 149 | out outval : int64_t 150 | ); 151 | 152 | routine 153 | log( 154 | j : job_t; 155 | pri : integer_t; 156 | err : integer_t; 157 | message : logmsg_t 158 | ); 159 | 160 | routine 161 | lookup_per_user_context( 162 | j : job_t; 163 | uid : uid_t; 164 | out userbport : mach_port_t 165 | ); 166 | 167 | routine 168 | move_subset( 169 | j : job_t; 170 | targetport : mach_port_t; 171 | session : name_t; 172 | asport : mach_port_t; 173 | flags : uint64_t 174 | ); 175 | 176 | routine 177 | swap_complex( 178 | j : job_t; 179 | inkey : vproc_gsk_t; 180 | outkey : vproc_gsk_t; 181 | inval : pointer_t; 182 | out outval : pointer_t, dealloc 183 | ); 184 | 185 | routine 186 | log_drain( 187 | j : job_t; 188 | sreplyport rp : mach_port_make_send_once_t; 189 | out outval : pointer_t, dealloc 190 | ); 191 | 192 | routine 193 | log_forward( 194 | j : job_t; 195 | inval : pointer_t 196 | ); 197 | 198 | routine 199 | kickstart( 200 | j : job_t; 201 | label : name_t; 202 | out pid : pid_t; 203 | flags : natural_t 204 | ); 205 | 206 | skip; /* Formerly embedded_wait. */ 207 | 208 | routine 209 | lookup_children( 210 | j : job_t; 211 | out childports : mach_port_move_send_array_t, dealloc; 212 | out childnames : name_array_t, dealloc; 213 | out childprops : bootstrap_property_array_t, dealloc 214 | ); 215 | 216 | routine 217 | switch_to_session( 218 | j : job_t; 219 | reqport : mach_port_t; 220 | session : name_t; 221 | asport : mach_port_t; 222 | out newbsport : mach_port_make_send_t 223 | ); 224 | 225 | skip; /* Formerly transaction_count_for_pid. */ 226 | 227 | routine 228 | pid_is_managed( 229 | j : job_t; 230 | pid : pid_t; 231 | out managed : boolean_t 232 | ); 233 | 234 | routine 235 | port_for_label( 236 | j : job_t; 237 | label : name_t; 238 | out jport : mach_port_make_send_t 239 | ); 240 | 241 | routine 242 | init_session( 243 | j : job_t; 244 | session : name_t; 245 | asport : mach_port_t 246 | ); 247 | 248 | routine 249 | set_security_session( 250 | j : job_t; 251 | uuid : uuid_t; 252 | asport : mach_port_t 253 | ); 254 | 255 | skip; /* Formerly wait2. */ 256 | 257 | skip; /* Formerly event_source_check_in. */ 258 | 259 | skip; /* Formerly event_set_state. */ 260 | 261 | routine 262 | spawn2( 263 | j : job_t; 264 | sreplyport rp : mach_port_make_send_once_t; 265 | job : pointer_t; 266 | asport : mach_port_t; 267 | out outpid : pid_t; 268 | out obsrvport : mach_port_move_receive_t 269 | ); 270 | 271 | routine 272 | get_root_bootstrap( 273 | j : job_t; 274 | out rootbs : mach_port_move_send_t 275 | ); 276 | 277 | routine 278 | legacy_ipc_request( 279 | j : job_t; 280 | request : pointer_t; 281 | request_fds : mach_port_move_send_array_t; 282 | out reply : pointer_t, dealloc; 283 | out reply_fds : mach_port_move_send_array_t, dealloc; 284 | asport : mach_port_t 285 | ); 286 | 287 | routine 288 | get_listener_port_rights( 289 | j : job_t; 290 | out sports : mach_port_make_send_array_t, dealloc 291 | ); 292 | 293 | routine 294 | register_gui_session( 295 | j : job_t; 296 | asport : mach_port_t 297 | ); 298 | -------------------------------------------------------------------------------- /liblaunch/vproc_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2012 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __VPROC_PRIVATE_H__ 22 | #define __VPROC_PRIVATE_H__ 23 | 24 | #ifdef __APPLE__ 25 | #include 26 | #else 27 | #include "shims/Availability.h" 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "launch.h" 36 | #include "vproc.h" 37 | #include 38 | 39 | #ifdef __APPLE__ 40 | /* NOTE: bootstrap is an Apple OS Mach port initiator */ 41 | #include 42 | #endif 43 | 44 | /* Pull in libdispatch for Grand Central Dispatch */ 45 | #include 46 | 47 | #ifndef VPROC_HAS_TRANSACTIONS 48 | #define VPROC_HAS_TRANSACTIONS 1 49 | #endif 50 | 51 | __BEGIN_DECLS 52 | 53 | #define VPROCMGR_SESSION_LOGINWINDOW "LoginWindow" 54 | #define VPROCMGR_SESSION_BACKGROUND "Background" 55 | #define VPROCMGR_SESSION_AQUA "Aqua" 56 | #define VPROCMGR_SESSION_STANDARDIO "StandardIO" 57 | #define VPROCMGR_SESSION_SYSTEM "System" 58 | 59 | #define XPC_DOMAIN_TYPE_SYSTEM "XPCSystem" 60 | #define XPC_DOMAIN_TYPE_PERUSER "XPCPerUser" 61 | #define XPC_DOMAIN_TYPE_PERSESSION "XPCPerSession" 62 | #define XPC_DOMAIN_TYPE_PERAPPLICATION "XPCPerApplication" 63 | 64 | #pragma GCC visibility push(default) 65 | 66 | /* DO NOT use this. This is a hack for 'launchctl' */ 67 | #define VPROC_MAGIC_UNLOAD_SIGNAL 0x4141504C 68 | 69 | typedef void (*_vproc_transaction_callout)(void *); 70 | 71 | typedef enum { 72 | VPROC_GSK_ZERO, 73 | VPROC_GSK_LAST_EXIT_STATUS, 74 | VPROC_GSK_GLOBAL_ON_DEMAND, 75 | VPROC_GSK_MGR_UID, 76 | VPROC_GSK_MGR_PID, 77 | VPROC_GSK_IS_MANAGED, 78 | VPROC_GSK_MGR_NAME, 79 | VPROC_GSK_BASIC_KEEPALIVE, 80 | VPROC_GSK_START_INTERVAL, 81 | VPROC_GSK_IDLE_TIMEOUT, 82 | VPROC_GSK_EXIT_TIMEOUT, 83 | VPROC_GSK_ENVIRONMENT, 84 | VPROC_GSK_ALLJOBS, 85 | VPROC_GSK_GLOBAL_LOG_MASK, 86 | VPROC_GSK_GLOBAL_UMASK, 87 | VPROC_GSK_ABANDON_PROCESS_GROUP, 88 | VPROC_GSK_TRANSACTIONS_ENABLED, 89 | VPROC_GSK_WEIRD_BOOTSTRAP, 90 | VPROC_GSK_WAITFORDEBUGGER, 91 | VPROC_GSK_SECURITYSESSION, 92 | VPROC_GSK_SHUTDOWN_DEBUGGING, 93 | VPROC_GSK_VERBOSE_BOOT, 94 | VPROC_GSK_PERUSER_SUSPEND, 95 | VPROC_GSK_PERUSER_RESUME, 96 | VPROC_GSK_JOB_OVERRIDES_DB, 97 | VPROC_GSK_JOB_CACHE_DB, 98 | VPROC_GSK_EMBEDDEDROOTEQUIVALENT, 99 | } vproc_gsk_t; 100 | 101 | typedef unsigned int vproc_flags_t; 102 | /* For _vproc_kickstart_by_label() -- instructs launchd to kickstart the job to stall before exec(2). */ 103 | #define VPROCFLAG_STALL_JOB_EXEC 1 << 1 104 | 105 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0) 106 | vproc_t 107 | vprocmgr_lookup_vproc(const char *label); 108 | 109 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0) 110 | vproc_t 111 | vproc_retain(vproc_t vp); 112 | 113 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0) 114 | void 115 | vproc_release(vproc_t vp); 116 | 117 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0) 118 | vproc_err_t 119 | vproc_swap_integer(vproc_t vp, vproc_gsk_t key, 120 | int64_t *inval, int64_t *outval); 121 | 122 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0) 123 | vproc_err_t 124 | vproc_swap_complex(vproc_t vp, vproc_gsk_t key, 125 | launch_data_t inval, launch_data_t *outval); 126 | 127 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_4_0) 128 | vproc_err_t 129 | vproc_swap_string(vproc_t vp, vproc_gsk_t key, 130 | const char *instr, char **outstr); 131 | 132 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) 133 | vproc_err_t 134 | _vproc_get_last_exit_status(int *wstatus); 135 | 136 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0) 137 | vproc_err_t 138 | _vproc_set_global_on_demand(bool val); 139 | 140 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0) 141 | vproc_err_t 142 | _vproc_send_signal_by_label(const char *label, int sig); 143 | 144 | #if HAS_MACH 145 | __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0) 146 | vproc_err_t 147 | _vproc_kickstart_by_label(const char *label, pid_t *out_pid, 148 | mach_port_t *out_port_name, mach_port_t *out_obsrvr_port, 149 | vproc_flags_t flags); 150 | #endif 151 | 152 | /* _vprocmgr_log_drain() is specific to syslogd. It is not for general use. */ 153 | typedef void (*_vprocmgr_log_drain_callback_t)(struct timeval *when, pid_t 154 | from_pid, pid_t about_pid, uid_t sender_uid, gid_t sender_gid, int priority, 155 | const char *from_name, const char *about_name, const char *session_name, 156 | const char *msg); 157 | 158 | vproc_err_t 159 | _vprocmgr_log_drain(vproc_t vp, pthread_mutex_t *optional_mutex_around_callback, 160 | _vprocmgr_log_drain_callback_t func); 161 | 162 | __attribute__((format(printf, 2, 3))) 163 | void 164 | _vproc_log(int pri, const char *msg, ...); 165 | 166 | __attribute__((format(printf, 2, 3))) 167 | void 168 | _vproc_log_error(int pri, const char *msg, ...); 169 | 170 | __attribute__((format(printf, 3, 0))) 171 | void 172 | _vproc_logv(int pri, int err, const char *msg, va_list ap); 173 | 174 | /* One day, we'll be able to get rid of this... */ 175 | vproc_err_t 176 | _vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type, 177 | uint64_t flags); 178 | 179 | vproc_err_t 180 | _vprocmgr_switch_to_session(const char *target_session, vproc_flags_t flags); 181 | 182 | vproc_err_t 183 | _vprocmgr_detach_from_console(vproc_flags_t flags); 184 | 185 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 186 | void 187 | _vproc_standby_begin(void); 188 | 189 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 190 | void 191 | _vproc_standby_end(void); 192 | 193 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 194 | size_t 195 | _vproc_standby_count(void); 196 | 197 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 198 | size_t 199 | _vproc_standby_timeout(void); 200 | 201 | #ifdef __APPLE__ 202 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 203 | kern_return_t 204 | _vproc_transaction_count_for_pid(pid_t p, int32_t *count, bool *condemned); 205 | #endif 206 | 207 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 208 | bool 209 | _vproc_pid_is_managed(pid_t p); 210 | 211 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 212 | void 213 | _vproc_transaction_try_exit(int status); 214 | 215 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) 216 | void 217 | _vproc_transaction_begin(void); 218 | 219 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) 220 | void 221 | _vproc_transaction_end(void); 222 | 223 | __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA) 224 | size_t 225 | _vproc_transaction_count(void); 226 | 227 | void 228 | _vproc_transaction_set_clean_callback(dispatch_queue_t targetq, void *ctx, 229 | dispatch_function_t func); 230 | 231 | void 232 | _vproc_transactions_enable(void); 233 | 234 | #pragma GCC visibility pop 235 | 236 | __END_DECLS 237 | 238 | #endif /* __VPROC_PRIVATE_H__ */ 239 | -------------------------------------------------------------------------------- /launchproxy/launchproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | #include "config.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #if !TARGET_OS_EMBEDDED 40 | #include 41 | #if __APPLE__ 42 | /* 43 | * None of the functions or enums declared in bsm/audit_session.h are used in 44 | * launchproxy. It does not in fact exist in any shape inside of OpenBSM 45 | * 46 | * 47 | */ 48 | #include 49 | #endif 50 | #endif // !TARGET_OS_EMBEDDED 51 | 52 | #include "launch.h" 53 | 54 | #ifndef __APPLE__ 55 | /* 56 | * Since launchd is core to Apple operating systems, they've got a 57 | * system-specified syslog(3) facility defined *just* for launchd. Non-Apple 58 | * OSes lack this system defined facility, but have local use facilities 59 | * available 60 | */ 61 | #define LOG_LAUNCHD (23<<3) 62 | #endif 63 | 64 | static int kq = 0; 65 | 66 | static void find_fds(launch_data_t o, const char *key __attribute__((unused)), void *context __attribute__((unused))) 67 | { 68 | struct kevent kev; 69 | size_t i; 70 | int fd; 71 | 72 | switch (launch_data_get_type(o)) { 73 | case LAUNCH_DATA_FD: 74 | fd = launch_data_get_fd(o); 75 | if (-1 == fd) 76 | break; 77 | fcntl(fd, F_SETFD, 1); 78 | EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 79 | if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) 80 | syslog(LOG_DEBUG, "kevent(%d): %m", fd); 81 | break; 82 | case LAUNCH_DATA_ARRAY: 83 | for (i = 0; i < launch_data_array_get_count(o); i++) 84 | find_fds(launch_data_array_get_index(o, i), NULL, NULL); 85 | break; 86 | case LAUNCH_DATA_DICTIONARY: 87 | launch_data_dict_iterate(o, find_fds, NULL); 88 | break; 89 | default: 90 | break; 91 | } 92 | } 93 | 94 | int main(int argc __attribute__((unused)), char *argv[]) 95 | { 96 | struct timespec timeout = { 10, 0 }; 97 | struct sockaddr_storage ss; 98 | socklen_t slen = (socklen_t)sizeof ss; 99 | struct kevent kev; 100 | int r, ec = EXIT_FAILURE; 101 | launch_data_t tmp, resp, msg = launch_data_alloc(LAUNCH_DATA_STRING); 102 | const char *prog = argv[1]; 103 | bool w = false, dupstdout = true, dupstderr = true; 104 | 105 | launch_data_set_string(msg, LAUNCH_KEY_CHECKIN); 106 | 107 | openlog(getprogname(), LOG_PERROR|LOG_PID|LOG_CONS, LOG_LAUNCHD); 108 | 109 | kq = kqueue(); 110 | 111 | if ((resp = launch_msg(msg)) == NULL) { 112 | syslog(LOG_ERR, "launch_msg(%s): %m", LAUNCH_KEY_CHECKIN); 113 | goto out; 114 | } 115 | 116 | launch_data_free(msg); 117 | 118 | tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS); 119 | if (tmp) { 120 | find_fds(tmp, NULL, NULL); 121 | } else { 122 | syslog(LOG_ERR, "No FDs found to answer requests on!"); 123 | goto out; 124 | } 125 | 126 | tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_TIMEOUT); 127 | if (tmp) 128 | timeout.tv_sec = (int)launch_data_get_integer(tmp); 129 | 130 | tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_PROGRAM); 131 | if (tmp) 132 | prog = launch_data_get_string(tmp); 133 | 134 | tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_INETDCOMPATIBILITY); 135 | if (tmp) { 136 | tmp = launch_data_dict_lookup(tmp, LAUNCH_JOBINETDCOMPATIBILITY_WAIT); 137 | if (tmp) 138 | w = launch_data_get_bool(tmp); 139 | } 140 | 141 | if (launch_data_dict_lookup(resp, LAUNCH_JOBKEY_STANDARDOUTPATH)) 142 | dupstdout = false; 143 | 144 | if (launch_data_dict_lookup(resp, LAUNCH_JOBKEY_STANDARDERRORPATH)) 145 | dupstderr = false; 146 | 147 | if (!w) 148 | signal(SIGCHLD, SIG_IGN); 149 | 150 | for (;;) { 151 | if ((r = kevent(kq, NULL, 0, &kev, 1, &timeout)) == -1) { 152 | syslog(LOG_DEBUG, "kevent(): %m"); 153 | goto out; 154 | } else if (r == 0) { 155 | ec = EXIT_SUCCESS; 156 | goto out; 157 | } 158 | 159 | if (w) { 160 | dup2((int)kev.ident, STDIN_FILENO); 161 | if (dupstdout) 162 | dup2((int)kev.ident, STDOUT_FILENO); 163 | if (dupstderr) 164 | dup2((int)kev.ident, STDERR_FILENO); 165 | execv(prog, argv + 1); 166 | syslog(LOG_ERR, "execv(): %m"); 167 | exit(EXIT_FAILURE); 168 | } 169 | 170 | if ((r = accept((int)kev.ident, (struct sockaddr *)&ss, &slen)) == -1) { 171 | if (errno == EWOULDBLOCK) 172 | continue; 173 | syslog(LOG_WARNING, "accept(): %m"); 174 | goto out; 175 | } else { 176 | if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) { 177 | char fromhost[NI_MAXHOST]; 178 | char fromport[NI_MAXSERV]; 179 | int gni_r; 180 | 181 | gni_r = getnameinfo((struct sockaddr *)&ss, slen, 182 | fromhost, (socklen_t) sizeof fromhost, 183 | fromport, (socklen_t) sizeof fromport, 184 | NI_NUMERICHOST | NI_NUMERICSERV); 185 | 186 | if (gni_r) { 187 | syslog(LOG_WARNING, "%s: getnameinfo(): %s", prog, gai_strerror(gni_r)); 188 | } else { 189 | syslog(LOG_INFO, "%s: Connection from: %s on port: %s", prog, fromhost, fromport); 190 | } 191 | } else { 192 | syslog(LOG_WARNING, "%s: getnameinfo() only supports IPv4/IPv6. Connection from address family: %u", prog, ss.ss_family); 193 | } 194 | 195 | switch (fork()) { 196 | case -1: 197 | syslog(LOG_WARNING, "fork(): %m"); 198 | if (errno != ENOMEM) { 199 | continue; 200 | } 201 | goto out; 202 | case 0: 203 | break; 204 | default: 205 | close(r); 206 | continue; 207 | } 208 | 209 | setpgid(0, 0); 210 | 211 | #if !TARGET_OS_EMBEDDED 212 | if ((tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SESSIONCREATE)) && launch_data_get_bool(tmp)) { 213 | auditinfo_addr_t auinfo = { 214 | .ai_termid = { .at_type = AU_IPv4 }, 215 | .ai_asid = AU_ASSIGN_ASID, 216 | .ai_auid = getuid(), 217 | .ai_flags = 0, 218 | }; 219 | if (setaudit_addr(&auinfo, sizeof(auinfo)) == 0) { 220 | char session[16]; 221 | snprintf(session, sizeof(session), "%x", auinfo.ai_asid); 222 | setenv("SECURITYSESSIONID", session, 1); 223 | } else { 224 | syslog(LOG_NOTICE, "%s: Setting Audit Session ID failed: %d", prog, errno); 225 | } 226 | } 227 | #endif // !TARGET_OS_EMBEDDED 228 | fcntl(r, F_SETFL, 0); 229 | fcntl(r, F_SETFD, 1); 230 | dup2(r, STDIN_FILENO); 231 | if (dupstdout) 232 | dup2(r, STDOUT_FILENO); 233 | if (dupstderr) 234 | dup2(r, STDERR_FILENO); 235 | signal(SIGCHLD, SIG_DFL); 236 | execv(prog, argv + 1); 237 | syslog(LOG_ERR, "execv(): %m"); 238 | exit(EXIT_FAILURE); 239 | } 240 | } 241 | 242 | out: 243 | exit(ec); 244 | } 245 | -------------------------------------------------------------------------------- /liblaunch/launch_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCH_PRIVATE_H__ 22 | #define __LAUNCH_PRIVATE_H__ 23 | 24 | #if HAS_MACH 25 | #include 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "launch.h" 33 | 34 | #pragma GCC visibility push(default) 35 | 36 | __BEGIN_DECLS 37 | 38 | #define LAUNCH_EXITSTATUS_FAIRPLAY_FAIL (INT64_MAX) 39 | 40 | #define LAUNCH_KEY_SETUSERENVIRONMENT "SetUserEnvironment" 41 | #define LAUNCH_KEY_UNSETUSERENVIRONMENT "UnsetUserEnvironment" 42 | #define LAUNCH_KEY_SHUTDOWN "Shutdown" 43 | #define LAUNCH_KEY_SINGLEUSER "SingleUser" 44 | #define LAUNCH_KEY_GETRESOURCELIMITS "GetResourceLimits" 45 | #define LAUNCH_KEY_SETRESOURCELIMITS "SetResourceLimits" 46 | #define LAUNCH_KEY_GETRUSAGESELF "GetResourceUsageSelf" 47 | #define LAUNCH_KEY_GETRUSAGECHILDREN "GetResourceUsageChildren" 48 | 49 | #define LAUNCHD_SOCKET_ENV "LAUNCHD_SOCKET" 50 | #define LAUNCHD_SOCK_PREFIX _PATH_VARTMP "launchd" 51 | #define LAUNCHD_TRUSTED_FD_ENV "__LAUNCHD_FD" 52 | #define LAUNCHD_ASYNC_MSG_KEY "_AsyncMessage" 53 | #define LAUNCH_KEY_BATCHCONTROL "BatchControl" 54 | #define LAUNCH_KEY_BATCHQUERY "BatchQuery" 55 | 56 | #define LAUNCH_JOBKEY_TRANSACTIONCOUNT "TransactionCount" 57 | #define LAUNCH_JOBKEY_QUARANTINEDATA "QuarantineData" 58 | #define LAUNCH_JOBKEY_SANDBOXPROFILE "SandboxProfile" 59 | #define LAUNCH_JOBKEY_SANDBOXFLAGS "SandboxFlags" 60 | #define LAUNCH_JOBKEY_SANDBOX_NAMED "Named" 61 | #define LAUNCH_JOBKEY_SANDBOXCONTAINER "SandboxContainer" 62 | #define LAUNCH_JOBKEY_JETSAMPROPERTIES "JetsamProperties" 63 | #define LAUNCH_JOBKEY_JETSAMPRIORITY "JetsamPriority" 64 | #define LAUNCH_JOBKEY_JETSAMMEMORYLIMIT "JetsamMemoryLimit" 65 | #define LAUNCH_JOBKEY_JETSAMMEMORYLIMITBACKGROUND "JetsamMemoryLimitBackground" 66 | #define LAUNCH_JOBKEY_SECURITYSESSIONUUID "SecuritySessionUUID" 67 | #define LAUNCH_JOBKEY_DISABLEASLR "DisableASLR" 68 | #define LAUNCH_JOBKEY_XPCDOMAIN "XPCDomain" 69 | #define LAUNCH_JOBKEY_POSIXSPAWNTYPE "POSIXSpawnType" 70 | 71 | #define LAUNCH_KEY_JETSAMLABEL "JetsamLabel" 72 | #define LAUNCH_KEY_JETSAMFRONTMOST "JetsamFrontmost" 73 | #define LAUNCH_KEY_JETSAMACTIVE "JetsamActive" 74 | #define LAUNCH_KEY_JETSAMPRIORITY LAUNCH_JOBKEY_JETSAMPRIORITY 75 | #define LAUNCH_KEY_JETSAMMEMORYLIMIT LAUNCH_JOBKEY_JETSAMMEMORYLIMIT 76 | 77 | #define LAUNCH_KEY_POSIXSPAWNTYPE_APP LAUNCH_KEY_PROCESSTYPE_APP 78 | #define LAUNCH_KEY_POSIXSPAWNTYPE_SYSTEMAPP "SystemApp" 79 | #define LAUNCH_KEY_POSIXSPAWNTYPE_STANDARD LAUNCH_KEY_PROCESSTYPE_STANDARD 80 | #define LAUNCH_KEY_POSIXSPAWNTYPE_BACKGROUND LAUNCH_KEY_PROCESSTYPE_BACKGROUND 81 | #define LAUNCH_KEY_POSIXSPAWNTYPE_INTERACTIVE LAUNCH_KEY_PROCESSTYPE_INTERACTIVE 82 | #define LAUNCH_KEY_POSIXSPAWNTYPE_ADAPTIVE LAUNCH_KEY_PROCESSTYPE_ADAPTIVE 83 | #define LAUNCH_KEY_POSIXSPAWNTYPE_TALAPP "TALApp" 84 | 85 | #define LAUNCH_JOBKEY_EMBEDDEDPRIVILEGEDISPENSATION "EmbeddedPrivilegeDispensation" 86 | #define LAUNCH_JOBKEY_EMBEDDEDHOMESCREEN "EmbeddedHomeScreen" 87 | #define LAUNCH_JOBKEY_EMBEDDEDMAINTHREADPRIORITY "EmbeddedMainThreadPriority" 88 | 89 | #define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL "EnterKernelDebuggerBeforeKill" 90 | #define LAUNCH_JOBKEY_PERJOBMACHSERVICES "PerJobMachServices" 91 | #define LAUNCH_JOBKEY_SERVICEIPC "ServiceIPC" 92 | #define LAUNCH_JOBKEY_BINARYORDERPREFERENCE "BinaryOrderPreference" 93 | #define LAUNCH_JOBKEY_MACHEXCEPTIONHANDLER "MachExceptionHandler" 94 | #define LAUNCH_JOBKEY_MULTIPLEINSTANCES "MultipleInstances" 95 | #define LAUNCH_JOBKEY_EVENTMONITOR "EventMonitor" 96 | #define LAUNCH_JOBKEY_SHUTDOWNMONITOR "ShutdownMonitor" 97 | #define LAUNCH_JOBKEY_BEGINTRANSACTIONATSHUTDOWN "BeginTransactionAtShutdown" 98 | #define LAUNCH_JOBKEY_XPCDOMAINBOOTSTRAPPER "XPCDomainBootstrapper" 99 | #define LAUNCH_JOBKEY_ASID "AuditSessionID" 100 | #define LAUNCH_JOBKEY_JOINGUISESSION "JoinGUISession" 101 | 102 | #define LAUNCH_JOBKEY_MACH_KUNCSERVER "kUNCServer" 103 | #define LAUNCH_JOBKEY_MACH_EXCEPTIONSERVER "ExceptionServer" 104 | #define LAUNCH_JOBKEY_MACH_TASKSPECIALPORT "TaskSpecialPort" 105 | #define LAUNCH_JOBKEY_MACH_HOSTSPECIALPORT "HostSpecialPort" 106 | #define LAUNCH_JOBKEY_MACH_ENTERKERNELDEBUGGERONCLOSE "EnterKernelDebuggerOnClose" 107 | #define LAUNCH_JOBKEY_LOWPRIORITYBACKGROUNDIO "LowPriorityBackgroundIO" 108 | #define LAUNCH_JOBKEY_LEGACYTIMERS "LegacyTimers" 109 | 110 | #define LAUNCH_ENV_INSTANCEID "LaunchInstanceID" 111 | 112 | #define JETSAM_PROPERTY_PRIORITY "Priority" 113 | #define JETSAM_PROPERTY_MEMORYLIMIT "MemoryLimitMB" 114 | 115 | /* For LoginWindow. 116 | * 117 | * After this call, the task's bootstrap port is set to the per session launchd. 118 | * 119 | * This returns 1 on success (it used to return otherwise), and -1 on failure. 120 | */ 121 | #define LOAD_ONLY_SAFEMODE_LAUNCHAGENTS (1 << 0) 122 | #define LAUNCH_GLOBAL_ON_DEMAND (1 << 1) 123 | pid_t 124 | create_and_switch_to_per_session_launchd(const char *, int flags, ...); 125 | 126 | /* Also for LoginWindow. 127 | * 128 | * This is will load jobs at the LoginWindow prompt. 129 | */ 130 | void 131 | load_launchd_jobs_at_loginwindow_prompt(int flags, ...); 132 | 133 | /* For CoreProcesses */ 134 | #define SPAWN_VIA_LAUNCHD_STOPPED 0x0001 135 | #define SPAWN_VIA_LAUNCHD_TALAPP 0x0002 136 | #define SPAWN_VIA_LAUNCHD_WIDGET 0x0004 137 | #define SPAWN_VIA_LAUNCHD_DISABLE_ASLR 0x0008 138 | 139 | struct spawn_via_launchd_attr { 140 | uint64_t spawn_flags; 141 | const char *spawn_path; 142 | const char *spawn_chdir; 143 | const char * const * spawn_env; 144 | const mode_t *spawn_umask; 145 | #if HAS_MACH 146 | /* XXX: It's unclear to me at this point how important a mach port 147 | * reference might be within the context of this data structure */ 148 | mach_port_t *spawn_observer_port; 149 | /* NOTE: cpu_type_t is defined by osfmk/mach/machine.h */ 150 | const cpu_type_t *spawn_binpref; 151 | #endif 152 | size_t spawn_binpref_cnt; 153 | void * spawn_quarantine; 154 | const char *spawn_seatbelt_profile; 155 | const uint64_t *spawn_seatbelt_flags; 156 | }; 157 | 158 | #define spawn_via_launchd(a, b, c) _spawn_via_launchd(a, b, c, 3) 159 | pid_t 160 | _spawn_via_launchd(const char *label, const char * const *argv, 161 | const struct spawn_via_launchd_attr *spawn_attrs, int struct_version); 162 | 163 | #if HAS_MACH 164 | /* It would appear that launch_wait is never referenced anywhere in launchd */ 165 | int 166 | launch_wait(mach_port_t port) __attribute__(("deprecated")); 167 | #endif 168 | 169 | #ifdef __APPLE__ 170 | /* The mpm_*() APIs no longer do anything. */ 171 | kern_return_t 172 | mpm_wait(mach_port_t ajob, int *wstatus); 173 | 174 | kern_return_t 175 | mpm_uncork_fork(mach_port_t ajob); 176 | #endif 177 | 178 | launch_data_t 179 | launch_socket_service_check_in(void); 180 | 181 | __END_DECLS 182 | 183 | #pragma GCC visibility pop 184 | 185 | 186 | #endif /* __LAUNCH_PRIVATE_H__ */ 187 | -------------------------------------------------------------------------------- /liblaunch/libbootstrap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | 22 | /* 23 | * Only Apple OSes contain `bootstrap` 24 | */ 25 | #ifdef __APPLE__ 26 | 27 | #include "config.h" 28 | #include "launch.h" 29 | #include "launch_priv.h" 30 | #include "bootstrap.h" 31 | #include "bootstrap_priv.h" 32 | #include "vproc.h" 33 | #include "vproc_priv.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "job.h" 44 | 45 | void 46 | bootstrap_init(void) 47 | { 48 | kern_return_t kr = task_get_special_port(task_self_trap(), TASK_BOOTSTRAP_PORT, &bootstrap_port); 49 | if (kr != KERN_SUCCESS) { 50 | abort(); 51 | } 52 | } 53 | 54 | kern_return_t 55 | bootstrap_create_server(mach_port_t bp, cmd_t server_cmd, uid_t server_uid, boolean_t on_demand, mach_port_t *server_port) 56 | { 57 | kern_return_t kr; 58 | 59 | kr = vproc_mig_create_server(bp, server_cmd, server_uid, on_demand, server_port); 60 | 61 | if (kr == VPROC_ERR_TRY_PER_USER) { 62 | mach_port_t puc; 63 | 64 | if (vproc_mig_lookup_per_user_context(bp, 0, &puc) == 0) { 65 | kr = vproc_mig_create_server(puc, server_cmd, server_uid, on_demand, server_port); 66 | mach_port_deallocate(mach_task_self(), puc); 67 | } 68 | } 69 | 70 | return kr; 71 | } 72 | 73 | kern_return_t 74 | bootstrap_subset(mach_port_t bp, mach_port_t requestor_port, mach_port_t *subset_port) 75 | { 76 | return vproc_mig_subset(bp, requestor_port, subset_port); 77 | } 78 | 79 | kern_return_t 80 | bootstrap_unprivileged(mach_port_t bp, mach_port_t *unpriv_port) 81 | { 82 | kern_return_t kr; 83 | 84 | *unpriv_port = MACH_PORT_NULL; 85 | 86 | kr = mach_port_mod_refs(mach_task_self(), bp, MACH_PORT_RIGHT_SEND, 1); 87 | 88 | if (kr == KERN_SUCCESS) { 89 | *unpriv_port = bp; 90 | } 91 | 92 | return kr; 93 | } 94 | 95 | kern_return_t 96 | bootstrap_parent(mach_port_t bp, mach_port_t *parent_port) 97 | { 98 | return vproc_mig_parent(bp, parent_port); 99 | } 100 | 101 | kern_return_t 102 | bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp) 103 | { 104 | return bootstrap_register2(bp, service_name, sp, 0); 105 | } 106 | 107 | kern_return_t 108 | bootstrap_register2(mach_port_t bp, name_t service_name, mach_port_t sp, uint64_t flags) 109 | { 110 | kern_return_t kr = vproc_mig_register2(bp, service_name, sp, flags); 111 | 112 | if (kr == VPROC_ERR_TRY_PER_USER) { 113 | mach_port_t puc; 114 | 115 | if (vproc_mig_lookup_per_user_context(bp, 0, &puc) == 0) { 116 | kr = vproc_mig_register2(puc, service_name, sp, flags); 117 | mach_port_deallocate(mach_task_self(), puc); 118 | } 119 | } 120 | 121 | return kr; 122 | } 123 | 124 | kern_return_t 125 | bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp) 126 | { 127 | kern_return_t kr; 128 | 129 | if ((kr = bootstrap_check_in(bp, service_name, sp))) { 130 | return kr; 131 | } 132 | 133 | if ((kr = mach_port_mod_refs(mach_task_self(), *sp, MACH_PORT_RIGHT_RECEIVE, -1))) { 134 | return kr; 135 | } 136 | 137 | return bootstrap_look_up(bp, service_name, sp); 138 | } 139 | 140 | kern_return_t 141 | bootstrap_check_in(mach_port_t bp, const name_t service_name, mach_port_t *sp) 142 | { 143 | uuid_t junk; 144 | (void)bzero(junk, sizeof(junk)); 145 | return vproc_mig_check_in2(bp, (char *)service_name, sp, junk, 0); 146 | } 147 | 148 | kern_return_t 149 | bootstrap_check_in2(mach_port_t bp, const name_t service_name, mach_port_t *sp, uint64_t flags) 150 | { 151 | uuid_t junk; 152 | (void)bzero(junk, sizeof(junk)); 153 | return vproc_mig_check_in2(bp, (char *)service_name, sp, junk, flags); 154 | } 155 | 156 | kern_return_t 157 | bootstrap_look_up_per_user(mach_port_t bp, const name_t service_name, uid_t target_user, mach_port_t *sp) 158 | { 159 | audit_token_t au_tok; 160 | kern_return_t kr; 161 | mach_port_t puc; 162 | 163 | /* See rdar://problem/4890134. */ 164 | 165 | if ((kr = vproc_mig_lookup_per_user_context(bp, target_user, &puc)) != 0) { 166 | return kr; 167 | } 168 | 169 | if (!service_name) { 170 | *sp = puc; 171 | } else { 172 | uuid_t junk; 173 | kr = vproc_mig_look_up2(puc, (char *)service_name, sp, &au_tok, 0, junk, 0); 174 | mach_port_deallocate(mach_task_self(), puc); 175 | } 176 | 177 | return kr; 178 | } 179 | 180 | kern_return_t 181 | bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, bootstrap_property_array_t *properties, mach_msg_type_number_t *n_children) 182 | { 183 | mach_msg_type_number_t junk = 0; 184 | return vproc_mig_lookup_children(bp, children, &junk, names, n_children, properties, &junk); 185 | } 186 | 187 | kern_return_t 188 | bootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp) 189 | { 190 | return bootstrap_look_up2(bp, service_name, sp, 0, 0); 191 | } 192 | 193 | kern_return_t 194 | bootstrap_look_up2(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, uint64_t flags) 195 | { 196 | uuid_t instance_id; 197 | return bootstrap_look_up3(bp, service_name, sp, target_pid, instance_id, flags); 198 | } 199 | 200 | kern_return_t 201 | bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags) 202 | { 203 | audit_token_t au_tok; 204 | bool privileged_server_lookup = flags & BOOTSTRAP_PRIVILEGED_SERVER; 205 | kern_return_t kr = 0; 206 | mach_port_t puc; 207 | 208 | // We have to cast instance_id here because the MIG-generated method 209 | // doesn't expect a const parameter. 210 | if ((kr = vproc_mig_look_up2(bp, (char *)service_name, sp, &au_tok, target_pid, (unsigned char*)instance_id, flags)) != VPROC_ERR_TRY_PER_USER) { 211 | goto out; 212 | } 213 | 214 | if ((kr = vproc_mig_lookup_per_user_context(bp, 0, &puc)) != 0) { 215 | goto out; 216 | } 217 | 218 | kr = vproc_mig_look_up2(puc, (char *)service_name, sp, &au_tok, target_pid, (unsigned char*)instance_id, flags); 219 | mach_port_deallocate(mach_task_self(), puc); 220 | 221 | out: 222 | if ((kr == 0) && privileged_server_lookup) { 223 | uid_t server_euid; 224 | 225 | /* 226 | * The audit token magic is dependent on the per-user launchd 227 | * forwarding MIG requests to the root launchd when it cannot 228 | * find the answer locally. 229 | */ 230 | 231 | /* This API should be in Libsystem, but is not */ 232 | //audit_token_to_au32(au_tok, NULL, &server_euid, NULL, NULL, NULL, NULL, NULL, NULL); 233 | 234 | server_euid = au_tok.val[1]; 235 | 236 | if (server_euid) { 237 | mach_port_deallocate(mach_task_self(), *sp); 238 | *sp = MACH_PORT_NULL; 239 | kr = BOOTSTRAP_NOT_PRIVILEGED; 240 | } 241 | } 242 | 243 | return kr; 244 | } 245 | 246 | kern_return_t 247 | bootstrap_check_in3(mach_port_t bp, const name_t service_name, mach_port_t *sp, uuid_t instance_id, uint64_t flags) 248 | { 249 | return vproc_mig_check_in2(bp, (char *)service_name, sp, instance_id, flags); 250 | } 251 | 252 | kern_return_t 253 | bootstrap_get_root(mach_port_t bp, mach_port_t *root) 254 | { 255 | return vproc_mig_get_root_bootstrap(bp, root); 256 | } 257 | 258 | kern_return_t 259 | bootstrap_status(mach_port_t bp, name_t service_name, bootstrap_status_t *service_active) 260 | { 261 | kern_return_t kr; 262 | mach_port_t p; 263 | 264 | if ((kr = bootstrap_look_up(bp, service_name, &p))) { 265 | return kr; 266 | } 267 | 268 | mach_port_deallocate(mach_task_self(), p); 269 | *service_active = BOOTSTRAP_STATUS_ACTIVE; 270 | 271 | if (bootstrap_check_in(bp, service_name, &p) == BOOTSTRAP_SUCCESS) { 272 | mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1); 273 | *service_active = BOOTSTRAP_STATUS_ON_DEMAND; 274 | } 275 | 276 | return BOOTSTRAP_SUCCESS; 277 | } 278 | 279 | kern_return_t 280 | bootstrap_info(mach_port_t bp, 281 | name_array_t *service_names, mach_msg_type_number_t *service_namesCnt, 282 | name_array_t *service_jobs, mach_msg_type_number_t *service_jobsCnt, 283 | bootstrap_status_array_t *service_active, mach_msg_type_number_t *service_activeCnt, 284 | uint64_t flags) 285 | { 286 | return vproc_mig_info(bp, service_names, service_namesCnt, service_jobs, service_jobsCnt, service_active, service_activeCnt, flags); 287 | } 288 | 289 | const char * 290 | bootstrap_strerror(kern_return_t r) 291 | { 292 | switch (r) { 293 | case BOOTSTRAP_SUCCESS: 294 | return "Success"; 295 | case BOOTSTRAP_NOT_PRIVILEGED: 296 | return "Permission denied"; 297 | case BOOTSTRAP_NAME_IN_USE: 298 | case BOOTSTRAP_SERVICE_ACTIVE: 299 | return "Service name already exists"; 300 | case BOOTSTRAP_UNKNOWN_SERVICE: 301 | return "Unknown service name"; 302 | case BOOTSTRAP_BAD_COUNT: 303 | return "Too many lookups were requested in one request"; 304 | case BOOTSTRAP_NO_MEMORY: 305 | return "Out of memory"; 306 | default: 307 | return mach_error_string(r); 308 | } 309 | } 310 | #endif 311 | -------------------------------------------------------------------------------- /launchctl/launchctl.1: -------------------------------------------------------------------------------- 1 | .Dd 1 May, 2009 2 | .Dt launchctl 1 3 | .Os Darwin 4 | .Sh NAME 5 | .Nm launchctl 6 | .Nd Interfaces with launchd 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar subcommand Op Ar arguments ... 10 | .Sh DESCRIPTION 11 | .Nm 12 | interfaces with 13 | .Nm launchd 14 | to load, unload daemons/agents and generally control 15 | .Nm launchd . 16 | .Nm 17 | supports taking subcommands on the command line, interactively or even redirected from standard input. 18 | These commands can be stored in 19 | .Nm $HOME/.launchd.conf 20 | or 21 | .Nm /etc/launchd.conf 22 | to be read at the time 23 | .Nm launchd 24 | starts. 25 | .Sh SUBCOMMANDS 26 | .Bl -tag -width -indent 27 | .It Xo Ar load Op Fl wF 28 | .Op Fl S Ar sessiontype 29 | .Op Fl D Ar domain 30 | .Ar paths ... 31 | .Xc 32 | Load the specified configuration files or directories of configuration files. 33 | Jobs that are not on-demand will be started as soon as possible. 34 | All specified jobs will be loaded before any of them are allowed to start. 35 | Note that per-user configuration files (LaunchAgents) must be owned by the user 36 | loading them. All system-wide daemons (LaunchDaemons) must be owned by root. Configuration files 37 | must not be group- or world-writable. These restrictions are in place for security reasons, 38 | as allowing writability to a launchd configuration file allows one to specify which executable 39 | will be launched. 40 | .Pp 41 | Note that allowing non-root write access to the /System/Library/LaunchDaemons directory WILL render your system unbootable. 42 | .Bl -tag -width -indent 43 | .It Fl w 44 | Overrides the Disabled key and sets it to false. In previous versions, this option 45 | would modify the configuration file. Now the state of the Disabled key is stored 46 | elsewhere on-disk. 47 | .It Fl F 48 | Force the loading of the plist. Ignore the Disabled key. 49 | .It Fl S Ar sessiontype 50 | Some jobs only make sense in certain contexts. This flag instructs 51 | .Nm launchctl 52 | to look for jobs in a different location when using the -D flag, and allows 53 | .Nm launchctl 54 | to restrict which jobs are loaded into which session types. Currently known 55 | session types include: Aqua, LoginWindow, Background, StandardIO and System. 56 | .It Fl D Ar domain 57 | Look for 58 | .Xr plist 5 files ending in *.plist in the domain given. Valid domains include 59 | "system," "local," "network" and "all." When providing a session type, an additional 60 | domain is available for use called "user." For example, without a session type given, 61 | "-D system" would load from property list files from /System/Library/LaunchDaemons. 62 | With a session type passed, it would load from /System/Library/LaunchAgents. 63 | .El 64 | .It Xo Ar unload Op Fl w 65 | .Op Fl S Ar sessiontype 66 | .Op Fl D Ar domain 67 | .Ar paths ... 68 | .Xc 69 | Unload the specified configuration files or directories of configuration files. 70 | This will also stop the job if it is running. 71 | .Bl -tag -width -indent 72 | .It Fl w 73 | Overrides the Disabled key and sets it to true. In previous versions, this option 74 | would modify the configuration file. Now the state of the Disabled key is stored 75 | elsewhere on-disk. 76 | .It Fl S Ar sessiontype 77 | Some jobs only make sense in certain contexts. This flag instructs 78 | .Nm launchctl 79 | to look for jobs in a different location when using the -D flag, and allows 80 | .Nm launchctl 81 | to restrict which jobs are loaded into which session types. Currently known 82 | session types include: Aqua, LoginWindow, Background, StandardIO and System. 83 | .It Fl D Ar domain 84 | Look for 85 | .Xr plist 5 files ending in *.plist in the domain given. Valid domains include 86 | "system," "local," "network" and "all." When providing a session type, an additional 87 | domain is available for use called "user." For example, without a session type given, 88 | "-D system" would load from property list files from /System/Library/LaunchDaemons. 89 | With a session type passed, it would load from /System/Library/LaunchAgents. 90 | .El 91 | .It Xo Ar submit Fl l Ar label 92 | .Op Fl p Ar executable 93 | .Op Fl o Ar path 94 | .Op Fl e Ar path 95 | .Ar -- command 96 | .Op Ar args 97 | .Xc 98 | A simple way of submitting a program to run without a configuration file. This mechanism also tells launchd to keep the program alive in the event of failure. 99 | .Bl -tag -width -indent 100 | .It Fl l Ar label 101 | What unique label to assign this job to launchd. 102 | .It Fl p Ar program 103 | What program to really execute, regardless of what follows the -- in the submit sub-command. 104 | .It Fl o Ar path 105 | Where to send the stdout of the program. 106 | .It Fl e Ar path 107 | Where to send the stderr of the program. 108 | .El 109 | .It Ar remove Ar job_label 110 | Remove the job from launchd by label. 111 | .It Ar start Ar job_label 112 | Start the specified job by label. The expected use of this subcommand is for 113 | debugging and testing so that one can manually kick-start an on-demand server. 114 | .It Ar stop Ar job_label 115 | Stop the specified job by label. If a job is on-demand, launchd may immediately 116 | restart the job if launchd finds any criteria that is satisfied. 117 | Non-demand based jobs will always be restarted. Use of this subcommand is discouraged. 118 | Jobs should ideally idle timeout by themselves. 119 | .It Xo Ar list 120 | .Op Ar -x 121 | .Op Ar label 122 | .Xc 123 | With no arguments, list all of the jobs loaded into 124 | .Nm launchd 125 | in three columns. The first column displays the PID of the job if it is running. 126 | The second column displays the last exit status of the job. If the number in this 127 | column is negative, it represents the negative of the signal which killed the job. 128 | Thus, "-15" would indicate that the job was terminated with SIGTERM. The third column 129 | is the job's label. 130 | .Pp 131 | Note that you may see some jobs in the list whose labels are in the style "0xdeadbeef.anonymous.program". 132 | These are jobs which are not managed by 133 | .Nm launchd , 134 | but, at one point, made a request to it. 135 | .Nm launchd 136 | claims no ownership and makes no guarantees regarding these jobs. They are stored purely for 137 | bookkeeping purposes. 138 | .Pp 139 | Similarly, you may see labels of the style "0xdeadbeef.mach_init.program". These are legacy jobs that run 140 | under mach_init emulation. This mechanism will be removed in future versions, and all remaining mach_init 141 | jobs should be converted over to 142 | .Nm launchd . 143 | .Pp 144 | If 145 | .Op Ar label 146 | is specified, prints information about the requested job. If 147 | .Op Ar -x 148 | is specified, the information for the specified job is output as an XML property list. 149 | .It Ar setenv Ar key Ar value 150 | Set an environmental variable inside of 151 | .Nm launchd . 152 | .It Ar unsetenv Ar key 153 | Unset an environmental variable inside of 154 | .Nm launchd . 155 | .It Ar getenv Ar key 156 | Get an environmental variable inside of 157 | .Nm launchd . 158 | .It Ar export 159 | Export all of the environmental variables of 160 | .Nm launchd 161 | for use in a shell eval statement. 162 | .It Ar getrusage self | children 163 | Get the resource utilization statistics for 164 | .Nm launchd 165 | or the children of 166 | .Nm launchd . 167 | .It Xo Ar log 168 | .Op Ar level loglevel 169 | .Op Ar only | mask loglevels... 170 | .Xc 171 | Get and set the 172 | .Xr syslog 3 173 | log level mask. The available log levels are: debug, info, notice, warning, error, critical, alert and emergency. 174 | .It Xo Ar limit 175 | .Op Ar cpu | filesize | data | stack | core | rss | memlock | maxproc | maxfiles 176 | .Op Ar both Op Ar soft | hard 177 | .Xc 178 | With no arguments, this command prints all the resource limits of 179 | .Nm launchd 180 | as found via 181 | .Xr getrlimit 2 . 182 | When a given resource is specified, it prints the limits for that resource. 183 | With a third argument, it sets both the hard and soft limits to that value. 184 | With four arguments, the third and forth argument represent the soft and hard limits respectively. 185 | See 186 | .Xr setrlimit 2 . 187 | .It Ar shutdown 188 | Tell 189 | .Nm launchd 190 | to prepare for shutdown by removing all jobs. 191 | .It Ar umask Op Ar newmask 192 | Get or optionally set the 193 | .Xr umask 2 194 | of 195 | .Nm launchd . 196 | .It Xo Ar bslist 197 | .Op Ar PID | .. 198 | .Op Ar -j 199 | .Xc 200 | This prints out Mach bootstrap services and their respective states. While the 201 | namespace appears flat, it is in fact hierarchical, thus allowing for certain 202 | services to be only available to a subset of processes. The three states a 203 | service can be in are active ("A"), inactive ("I") and on-demand ("D"). 204 | .Pp 205 | If 206 | .Op Ar PID 207 | is specified, print the Mach bootstrap services available to that PID. If 208 | .Op Ar .. 209 | is specified, print the Mach bootstrap services available in the parent of the 210 | current bootstrap. Note that in Mac OS X v10.6, the per-user Mach bootstrap namespace 211 | is flat, so you will only see a different set of services in a per-user bootstrap 212 | if you are in an explicitly-created bootstrap subset. 213 | .Pp 214 | If 215 | .Op Ar -j 216 | is specified, each service name will be followed by the name of the job which registered 217 | it. 218 | .It Ar bsexec Ar PID command Op Ar args 219 | This executes the given command in the same Mach bootstrap namespace hierachy 220 | as the given PID. 221 | .It Ar bstree Op Ar -j 222 | This prints a hierarchical view of the entire Mach bootstrap tree. If 223 | .Op Ar -j 224 | is specified, each service name will be followed by the name of the job which registered it. 225 | Requires root 226 | privileges. 227 | .It Ar managerpid 228 | This prints the PID of the launchd which manages the current bootstrap. 229 | .It Ar manageruid 230 | This prints the UID of the launchd which manages the current bootstrap. 231 | .It Ar managername 232 | This prints the name of the launchd job manager which manages the current bootstrap. 233 | See LimitLoadToSessionType in 234 | .Xr launchd.plist 5 235 | for more details. 236 | .It Ar help 237 | Print out a quick usage statement. 238 | .El 239 | .Sh ENVIRONMENTAL VARIABLES 240 | .Bl -tag -width -indent 241 | .It Pa LAUNCHD_SOCKET 242 | This variable informs launchctl how to find the correct launchd to talk to. If it is missing, launchctl will use a built-in default. 243 | .El 244 | .Sh FILES 245 | .Bl -tag -width "/System/Library/LaunchDaemons" -compact 246 | .It Pa ~/Library/LaunchAgents 247 | Per-user agents provided by the user. 248 | .It Pa /Library/LaunchAgents 249 | Per-user agents provided by the administrator. 250 | .It Pa /Library/LaunchDaemons 251 | System wide daemons provided by the administrator. 252 | .It Pa /System/Library/LaunchAgents 253 | Mac OS X Per-user agents. 254 | .It Pa /System/Library/LaunchDaemons 255 | Mac OS X System wide daemons. 256 | .El 257 | .Sh SEE ALSO 258 | .Xr launchd.plist 5 , 259 | .Xr launchd.conf 5 , 260 | .Xr launchd 8 261 | -------------------------------------------------------------------------------- /support/roundup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # [r5]: roundup.5.html 3 | # [r1t]: roundup-1-test.sh.html 4 | # [r5t]: roundup-5-test.sh.html 5 | # 6 | # _(c) 2010 Blake Mizerany - MIT License_ 7 | # 8 | # Spray **roundup** on your shells to eliminate weeds and bugs. If your shells 9 | # survive **roundup**'s deathly toxic properties, they are considered 10 | # roundup-ready. 11 | # 12 | # **roundup** reads shell scripts to form test plans. Each 13 | # test plan is sourced into a sandbox where each test is executed. 14 | # 15 | # See [roundup-1-test.sh.html][r1t] or [roundup-5-test.sh.html][r5t] for example 16 | # test plans. 17 | # 18 | # __Install__ 19 | # 20 | # git clone http://github.com/bmizerany/roundup.git 21 | # cd roundup 22 | # make 23 | # sudo make install 24 | # # Alternatively, copy `roundup` wherever you like. 25 | # 26 | # __NOTE__: Because test plans are sourced into roundup, roundup prefixes its 27 | # variable and function names with `roundup_` to avoid name collisions. See 28 | # "Sandbox Test Runs" below for more insight. 29 | 30 | # Usage and Prerequisites 31 | # ----------------------- 32 | 33 | # Exit if any following command exits with a non-zero status. 34 | set -e 35 | 36 | # The current version is set during `make version`. Do not modify this line in 37 | # anyway unless you know what you're doing. 38 | ROUNDUP_VERSION="0.0.5" 39 | export ROUNDUP_VERSION 40 | 41 | # Usage is defined in a specific comment syntax. It is `grep`ed out of this file 42 | # when needed (i.e. The Tomayko Method). See 43 | # [shocco](http://rtomayko.heroku.com/shocco) for more detail. 44 | #/ usage: roundup [--help|-h] [--version|-v] [plan ...] 45 | 46 | roundup_usage() { 47 | grep '^#/' <"$0" | cut -c4- 48 | } 49 | 50 | while test "$#" -gt 0 51 | do 52 | case "$1" in 53 | --help|-h) 54 | roundup_usage 55 | exit 0 56 | ;; 57 | --version|-v) 58 | echo "roundup version $ROUNDUP_VERSION" 59 | exit 0 60 | ;; 61 | --color) 62 | color=always 63 | shift 64 | ;; 65 | -) 66 | echo >&2 "roundup: unknown switch $1" 67 | exit 1 68 | ;; 69 | *) 70 | break 71 | ;; 72 | esac 73 | done 74 | 75 | # Consider all scripts with names matching `*-test.sh` the plans to run unless 76 | # otherwise specified as arguments. 77 | if [ "$#" -gt "0" ] 78 | then 79 | roundup_plans="$@" 80 | else 81 | roundup_plans="$(ls *-test.sh)" 82 | fi 83 | 84 | : ${color:="auto"} 85 | 86 | # Create a temporary storage place for test output to be retrieved for display 87 | # after failing tests. 88 | roundup_tmp="$PWD/.roundup.$$" 89 | mkdir -p "$roundup_tmp" 90 | 91 | trap "rm -rf \"$roundup_tmp\"" EXIT INT 92 | 93 | # __Tracing failures__ 94 | roundup_trace() { 95 | # Delete the first two lines that represent roundups execution of the 96 | # test function. They are useless to the user. 97 | sed '1d' | 98 | # Delete the last line which is the "set +x" of the error trap 99 | sed '$d' | 100 | # Replace the rc=$? of the error trap with an verbose string appended 101 | # to the failing command trace line. 102 | sed '$s/.*rc=/exit code /' | 103 | # Trim the two left most `+` signs. They represent the depth at which 104 | # roundup executed the function. They also, are useless and confusing. 105 | sed 's/^++//' | 106 | # Indent the output by 4 spaces to align under the test name in the 107 | # summary. 108 | sed 's/^/ /' | 109 | # Highlight the last line in front of the exit code to bring notice to 110 | # where the error occurred. 111 | # 112 | # The sed magic puts every line into the hold buffer first, then 113 | # substitutes in the previous hold buffer content, prints that and starts 114 | # with the next cycle. At the end the last line (in the hold buffer) 115 | # is printed without substitution. 116 | sed -n "x;1!{ \$s/\(.*\)/$mag\1$clr/; };1!p;\$x;\$p" 117 | } 118 | 119 | # __Other helpers__ 120 | 121 | # Track the test stats while outputting a real-time report. This takes input on 122 | # **stdin**. Each input line must come in the format of: 123 | # 124 | # # The plan description to be displayed 125 | # d 126 | # 127 | # # A passing test 128 | # p 129 | # 130 | # # A failed test 131 | # f 132 | roundup_summarize() { 133 | set -e 134 | 135 | # __Colors for output__ 136 | 137 | # Use colors if we are writing to a tty device. 138 | if (test -t 1) || (test $color = always) 139 | then 140 | red=$(printf "\033[31m") 141 | grn=$(printf "\033[32m") 142 | mag=$(printf "\033[35m") 143 | clr=$(printf "\033[m") 144 | cols=$(tput cols) 145 | fi 146 | 147 | # Make these available to `roundup_trace`. 148 | export red grn mag clr 149 | 150 | ntests=0 151 | passed=0 152 | failed=0 153 | 154 | : ${cols:=10} 155 | 156 | while read status name 157 | do 158 | case $status in 159 | p) 160 | ntests=$(expr $ntests + 1) 161 | passed=$(expr $passed + 1) 162 | printf " %-48s " "$name:" 163 | printf "$grn[PASS]$clr\n" 164 | ;; 165 | f) 166 | ntests=$(expr $ntests + 1) 167 | failed=$(expr $failed + 1) 168 | printf " %-48s " "$name:" 169 | printf "$red[FAIL]$clr\n" 170 | roundup_trace < "$roundup_tmp/$name" 171 | ;; 172 | d) 173 | printf "%s\n" "$name" 174 | ;; 175 | esac 176 | done 177 | # __Test Summary__ 178 | # 179 | # Display the summary now that all tests are finished. 180 | yes = | head -n 57 | tr -d '\n' 181 | printf "\n" 182 | printf "Tests: %3d | " $ntests 183 | printf "Passed: %3d | " $passed 184 | printf "Failed: %3d" $failed 185 | printf "\n" 186 | 187 | # Exit with an error if any tests failed 188 | test $failed -eq 0 || exit 2 189 | } 190 | 191 | # Sandbox Test Runs 192 | # ----------------- 193 | 194 | # The above checks guarantee we have at least one test. We can now move through 195 | # each specified test plan, determine its test plan, and administer each test 196 | # listed in a isolated sandbox. 197 | for roundup_p in $roundup_plans 198 | do 199 | # Create a sandbox, source the test plan, run the tests, then leave 200 | # without a trace. 201 | ( 202 | # Consider the description to be the `basename` of the plan minus the 203 | # tailing -test.sh. 204 | roundup_desc=$(basename "$roundup_p" -test.sh) 205 | 206 | # Define functions for 207 | # [roundup(5)][r5] 208 | 209 | # A custom description is recommended, but optional. Use `describe` to 210 | # set the description to something more meaningful. 211 | # TODO: reimplement this. 212 | describe() { 213 | roundup_desc="$*" 214 | } 215 | 216 | # Provide default `before` and `after` functions that run only `:`, a 217 | # no-op. They may or may not be redefined by the test plan. 218 | before() { :; } 219 | after() { :; } 220 | 221 | # Seek test methods and aggregate their names, forming a test plan. 222 | # This is done before populating the sandbox with tests to avoid odd 223 | # conflicts. 224 | 225 | # TODO: I want to do this with sed only. Please send a patch if you 226 | # know a cleaner way. 227 | roundup_plan=$( 228 | grep "^it_.*()" $roundup_p | 229 | sed "s/\(it_[a-zA-Z0-9_]*\).*$/\1/g" 230 | ) 231 | 232 | # We have the test plan and are in our sandbox with [roundup(5)][r5] 233 | # defined. Now we source the plan to bring its tests into scope. 234 | . ./$roundup_p 235 | 236 | # Output the description signal 237 | printf "d %s" "$roundup_desc" | tr "\n" " " 238 | printf "\n" 239 | 240 | for roundup_test_name in $roundup_plan 241 | do 242 | # Any number of things are possible in `before`, `after`, and the 243 | # test. Drop into an subshell to contain operations that may throw 244 | # off roundup; such as `cd`. 245 | ( 246 | # Output `before` trace to temporary file. If `before` runs cleanly, 247 | # the trace will be overwritten by the actual test case below. 248 | { 249 | # redirect tracing output of `before` into file. 250 | { 251 | set -x 252 | # If `before` wasn't redefined, then this is `:`. 253 | before 254 | } &>"$roundup_tmp/$roundup_test_name" 255 | # disable tracing again. Its trace output goes to /dev/null. 256 | set +x 257 | } &>/dev/null 258 | 259 | # exit subshell with return code of last failing command. This 260 | # is needed to see the return code 253 on failed assumptions. 261 | # But, only do this if the error handling is activated. 262 | set -E 263 | trap 'rc=$?; set +x; set -o | grep "errexit.*on" >/dev/null && exit $rc' ERR 264 | 265 | # If `before` wasn't redefined, then this is `:`. 266 | before 267 | 268 | # Momentarily turn off auto-fail to give us access to the tests 269 | # exit status in `$?` for capturing. 270 | set +e 271 | ( 272 | # Set `-xe` before the test in the subshell. We want the 273 | # test to fail fast to allow for more accurate output of 274 | # where things went wrong but not in _our_ process because a 275 | # failed test should not immediately fail roundup. Each 276 | # tests trace output is saved in temporary storage. 277 | set -xe 278 | $roundup_test_name 279 | ) >"$roundup_tmp/$roundup_test_name" 2>&1 280 | 281 | # We need to capture the exit status before returning the `set 282 | # -e` mode. Returning with `set -e` before we capture the exit 283 | # status will result in `$?` being set with `set`'s status 284 | # instead. 285 | roundup_result=$? 286 | 287 | # It's safe to return to normal operation. 288 | set -e 289 | 290 | # If `after` wasn't redefined, then this runs `:`. 291 | after 292 | 293 | # This is the final step of a test. Print its pass/fail signal 294 | # and name. 295 | if [ "$roundup_result" -ne 0 ] 296 | then printf "f" 297 | else printf "p" 298 | fi 299 | 300 | printf " $roundup_test_name\n" 301 | ) 302 | done 303 | ) 304 | done | 305 | 306 | # All signals are piped to this for summary. 307 | roundup_summarize 308 | -------------------------------------------------------------------------------- /liblaunch/launch_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005-2012 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | #include "launch.h" 21 | #include "byteswap.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* NOTE: defined temporarily in liblaunch.c */ 29 | extern int _fd(int fd); 30 | 31 | launch_data_t 32 | launch_data_alloc(launch_data_type_t t) 33 | { 34 | launch_data_t d = calloc(1, sizeof(struct _launch_data)); 35 | assert(NULL != d); 36 | 37 | if (d) { 38 | d->type = t; 39 | switch (t) { 40 | case LAUNCH_DATA_DICTIONARY: 41 | case LAUNCH_DATA_ARRAY: 42 | d->_array = malloc(0); 43 | break; 44 | case LAUNCH_DATA_OPAQUE: 45 | d->opaque = malloc(0); 46 | default: 47 | break; 48 | } 49 | } 50 | 51 | return d; 52 | } 53 | 54 | launch_data_type_t 55 | launch_data_get_type(launch_data_t d) 56 | { 57 | return d->type; 58 | } 59 | 60 | void 61 | launch_data_free(launch_data_t d) 62 | { 63 | size_t i; 64 | 65 | switch (d->type) { 66 | case LAUNCH_DATA_DICTIONARY: 67 | case LAUNCH_DATA_ARRAY: 68 | for (i = 0; i < d->_array_cnt; i++) { 69 | if (d->_array[i]) { 70 | launch_data_free(d->_array[i]); 71 | } 72 | } 73 | free(d->_array); 74 | break; 75 | case LAUNCH_DATA_STRING: 76 | if (d->string) 77 | free(d->string); 78 | break; 79 | case LAUNCH_DATA_OPAQUE: 80 | if (d->opaque) 81 | free(d->opaque); 82 | break; 83 | default: 84 | break; 85 | } 86 | free(d); 87 | } 88 | 89 | size_t 90 | launch_data_dict_get_count(launch_data_t dict) 91 | { 92 | return dict->_array_cnt / 2; 93 | } 94 | 95 | bool 96 | launch_data_dict_insert(launch_data_t dict, launch_data_t what, const char *key) 97 | { 98 | size_t i; 99 | launch_data_t thekey = launch_data_alloc(LAUNCH_DATA_STRING); 100 | 101 | launch_data_set_string(thekey, key); 102 | 103 | for (i = 0; i < dict->_array_cnt; i += 2) { 104 | if (!strcasecmp(key, dict->_array[i]->string)) { 105 | launch_data_array_set_index(dict, thekey, i); 106 | launch_data_array_set_index(dict, what, i + 1); 107 | return true; 108 | } 109 | } 110 | launch_data_array_set_index(dict, thekey, i); 111 | launch_data_array_set_index(dict, what, i + 1); 112 | return true; 113 | } 114 | 115 | launch_data_t 116 | launch_data_dict_lookup(launch_data_t dict, const char *key) 117 | { 118 | size_t i; 119 | 120 | if (LAUNCH_DATA_DICTIONARY != dict->type) 121 | return NULL; 122 | 123 | for (i = 0; i < dict->_array_cnt; i += 2) { 124 | if (!strcasecmp(key, dict->_array[i]->string)) 125 | return dict->_array[i + 1]; 126 | } 127 | 128 | return NULL; 129 | } 130 | 131 | bool 132 | launch_data_dict_remove(launch_data_t dict, const char *key) 133 | { 134 | size_t i; 135 | 136 | for (i = 0; i < dict->_array_cnt; i += 2) { 137 | if (!strcasecmp(key, dict->_array[i]->string)) 138 | break; 139 | } 140 | if (i == dict->_array_cnt) 141 | return false; 142 | launch_data_free(dict->_array[i]); 143 | launch_data_free(dict->_array[i + 1]); 144 | memmove(dict->_array + i, dict->_array + i + 2, (dict->_array_cnt - (i + 2)) * sizeof(launch_data_t)); 145 | dict->_array_cnt -= 2; 146 | return true; 147 | } 148 | 149 | void 150 | launch_data_dict_iterate(launch_data_t dict, void (*cb)(launch_data_t, const char *, void *), void *context) 151 | { 152 | size_t i; 153 | 154 | if (LAUNCH_DATA_DICTIONARY != dict->type) { 155 | return; 156 | } 157 | 158 | for (i = 0; i < dict->_array_cnt; i += 2) { 159 | cb(dict->_array[i + 1], dict->_array[i]->string, context); 160 | } 161 | } 162 | 163 | bool 164 | launch_data_array_set_index(launch_data_t where, launch_data_t what, size_t ind) 165 | { 166 | if ((ind + 1) >= where->_array_cnt) { 167 | where->_array = reallocf(where->_array, (ind + 1) * sizeof(launch_data_t)); 168 | memset(where->_array + where->_array_cnt, 0, (ind + 1 - where->_array_cnt) * sizeof(launch_data_t)); 169 | where->_array_cnt = ind + 1; 170 | } 171 | 172 | if (where->_array[ind]) { 173 | launch_data_free(where->_array[ind]); 174 | } 175 | 176 | where->_array[ind] = what; 177 | return true; 178 | } 179 | 180 | launch_data_t 181 | launch_data_array_get_index(launch_data_t where, size_t ind) 182 | { 183 | if (LAUNCH_DATA_ARRAY != where->type || ind >= where->_array_cnt) { 184 | return NULL; 185 | } else { 186 | return where->_array[ind]; 187 | } 188 | } 189 | 190 | launch_data_t 191 | launch_data_array_pop_first(launch_data_t where) 192 | { 193 | launch_data_t r = NULL; 194 | 195 | if (where->_array_cnt > 0) { 196 | r = where->_array[0]; 197 | memmove(where->_array, where->_array + 1, (where->_array_cnt - 1) * sizeof(launch_data_t)); 198 | where->_array_cnt--; 199 | } 200 | return r; 201 | } 202 | 203 | size_t 204 | launch_data_array_get_count(launch_data_t where) 205 | { 206 | if (LAUNCH_DATA_ARRAY != where->type) 207 | return 0; 208 | return where->_array_cnt; 209 | } 210 | 211 | bool 212 | launch_data_set_errno(launch_data_t d, int e) 213 | { 214 | d->err = e; 215 | return true; 216 | } 217 | 218 | bool 219 | launch_data_set_fd(launch_data_t d, int fd) 220 | { 221 | d->fd = fd; 222 | return true; 223 | } 224 | 225 | bool 226 | launch_data_set_integer(launch_data_t d, long long n) 227 | { 228 | d->number = n; 229 | return true; 230 | } 231 | 232 | bool 233 | launch_data_set_bool(launch_data_t d, bool b) 234 | { 235 | d->boolean = b; 236 | return true; 237 | } 238 | 239 | bool 240 | launch_data_set_real(launch_data_t d, double n) 241 | { 242 | d->float_num = n; 243 | return true; 244 | } 245 | 246 | bool 247 | launch_data_set_string(launch_data_t d, const char *s) 248 | { 249 | if (d->string) 250 | free(d->string); 251 | d->string = strdup(s); 252 | if (d->string) { 253 | d->string_len = strlen(d->string); 254 | return true; 255 | } 256 | return false; 257 | } 258 | 259 | bool 260 | launch_data_set_opaque(launch_data_t d, const void *o, size_t os) 261 | { 262 | d->opaque_size = os; 263 | if (d->opaque) 264 | free(d->opaque); 265 | d->opaque = malloc(os); 266 | if (d->opaque) { 267 | memcpy(d->opaque, o, os); 268 | return true; 269 | } 270 | return false; 271 | } 272 | 273 | 274 | #if HAS_MACH 275 | bool 276 | launch_data_set_machport(launch_data_t d, mach_port_t p) 277 | { 278 | d->mp = p; 279 | return true; 280 | } 281 | #endif 282 | 283 | #define ROUND_TO_64BIT_WORD_SIZE(x) ((x + 7) & ~7) 284 | 285 | size_t 286 | launch_data_pack(launch_data_t d, void *where, size_t len, int *fd_where, size_t *fd_cnt) 287 | { 288 | launch_data_t o_in_w = where; 289 | size_t i, rsz, node_data_len = sizeof(struct _launch_data); 290 | 291 | if (node_data_len > len) { 292 | return 0; 293 | } 294 | 295 | where += node_data_len; 296 | 297 | o_in_w->type = host2wire(d->type); 298 | 299 | size_t pad_len = 0; 300 | switch (d->type) { 301 | case LAUNCH_DATA_INTEGER: 302 | o_in_w->number = host2wire(d->number); 303 | break; 304 | case LAUNCH_DATA_REAL: 305 | o_in_w->float_num = host2wire_f(d->float_num); 306 | break; 307 | case LAUNCH_DATA_BOOL: 308 | o_in_w->boolean = host2wire(d->boolean); 309 | break; 310 | case LAUNCH_DATA_ERRNO: 311 | o_in_w->err = host2wire(d->err); 312 | break; 313 | case LAUNCH_DATA_FD: 314 | o_in_w->fd = host2wire(d->fd); 315 | if (fd_where && d->fd != -1) { 316 | fd_where[*fd_cnt] = d->fd; 317 | (*fd_cnt)++; 318 | } 319 | break; 320 | case LAUNCH_DATA_STRING: 321 | o_in_w->string_len = host2wire(d->string_len); 322 | node_data_len += ROUND_TO_64BIT_WORD_SIZE(d->string_len + 1); 323 | 324 | if (node_data_len > len) { 325 | return 0; 326 | } 327 | memcpy(where, d->string, d->string_len + 1); 328 | 329 | /* Zero padded data. */ 330 | pad_len = ROUND_TO_64BIT_WORD_SIZE(d->string_len + 1) - (d->string_len + 1); 331 | bzero(where + d->string_len + 1, pad_len); 332 | 333 | break; 334 | case LAUNCH_DATA_OPAQUE: 335 | o_in_w->opaque_size = host2wire(d->opaque_size); 336 | node_data_len += ROUND_TO_64BIT_WORD_SIZE(d->opaque_size); 337 | if (node_data_len > len) { 338 | return 0; 339 | } 340 | memcpy(where, d->opaque, d->opaque_size); 341 | 342 | /* Zero padded data. */ 343 | pad_len = ROUND_TO_64BIT_WORD_SIZE(d->opaque_size) - d->opaque_size; 344 | bzero(where + d->opaque_size, pad_len); 345 | 346 | break; 347 | case LAUNCH_DATA_DICTIONARY: 348 | case LAUNCH_DATA_ARRAY: 349 | o_in_w->_array_cnt = host2wire(d->_array_cnt); 350 | node_data_len += d->_array_cnt * sizeof(uint64_t); 351 | if (node_data_len > len) { 352 | return 0; 353 | } 354 | 355 | where += d->_array_cnt * sizeof(uint64_t); 356 | 357 | for (i = 0; i < d->_array_cnt; i++) { 358 | rsz = launch_data_pack(d->_array[i], where, len - node_data_len, fd_where, fd_cnt); 359 | if (rsz == 0) { 360 | return 0; 361 | } 362 | where += rsz; 363 | node_data_len += rsz; 364 | } 365 | break; 366 | default: 367 | break; 368 | } 369 | 370 | return node_data_len; 371 | } 372 | 373 | launch_data_t 374 | launch_data_unpack(void *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset) 375 | { 376 | launch_data_t r = data + *data_offset; 377 | size_t i, tmpcnt; 378 | 379 | if ((data_size - *data_offset) < sizeof(struct _launch_data)) 380 | return NULL; 381 | *data_offset += sizeof(struct _launch_data); 382 | 383 | switch (wire2host(r->type)) { 384 | case LAUNCH_DATA_DICTIONARY: 385 | case LAUNCH_DATA_ARRAY: 386 | tmpcnt = wire2host(r->_array_cnt); 387 | if ((data_size - *data_offset) < (tmpcnt * sizeof(uint64_t))) { 388 | errno = EAGAIN; 389 | return NULL; 390 | } 391 | r->_array = data + *data_offset; 392 | *data_offset += tmpcnt * sizeof(uint64_t); 393 | for (i = 0; i < tmpcnt; i++) { 394 | r->_array[i] = launch_data_unpack(data, data_size, fds, fd_cnt, data_offset, fdoffset); 395 | if (r->_array[i] == NULL) 396 | return NULL; 397 | } 398 | r->_array_cnt = tmpcnt; 399 | break; 400 | case LAUNCH_DATA_STRING: 401 | tmpcnt = wire2host(r->string_len); 402 | if ((data_size - *data_offset) < (tmpcnt + 1)) { 403 | errno = EAGAIN; 404 | return NULL; 405 | } 406 | r->string = data + *data_offset; 407 | r->string_len = tmpcnt; 408 | *data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt + 1); 409 | break; 410 | case LAUNCH_DATA_OPAQUE: 411 | tmpcnt = wire2host(r->opaque_size); 412 | if ((data_size - *data_offset) < tmpcnt) { 413 | errno = EAGAIN; 414 | return NULL; 415 | } 416 | r->opaque = data + *data_offset; 417 | r->opaque_size = tmpcnt; 418 | *data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt); 419 | break; 420 | case LAUNCH_DATA_FD: 421 | if (r->fd != -1 && fd_cnt > *fdoffset) { 422 | r->fd = _fd(fds[*fdoffset]); 423 | *fdoffset += 1; 424 | } 425 | break; 426 | case LAUNCH_DATA_INTEGER: 427 | r->number = wire2host(r->number); 428 | break; 429 | case LAUNCH_DATA_REAL: 430 | r->float_num = wire2host_f(r->float_num); 431 | break; 432 | case LAUNCH_DATA_BOOL: 433 | r->boolean = wire2host(r->boolean); 434 | break; 435 | case LAUNCH_DATA_ERRNO: 436 | r->err = wire2host(r->err); 437 | #if HAS_MACH 438 | case LAUNCH_DATA_MACHPORT: 439 | break; 440 | #endif 441 | default: 442 | errno = EINVAL; 443 | return NULL; 444 | break; 445 | } 446 | 447 | r->type = wire2host(r->type); 448 | 449 | return r; 450 | } 451 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /launchd/log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "job_reply.h" 4 | 5 | #include "launchd.h" 6 | #include "launch_internal.h" 7 | #include "vproc_internal.h" 8 | #include "log.h" 9 | 10 | #define ROUND_TO_64BIT_WORD_SIZE(x) ((x + 7) & ~7) 11 | #define LAUNCHD_DEBUG_LOG "launchd-debug.%s.log" 12 | #define LAUNCHD_PERF_LOG "launchd-perf.%s.log" 13 | #define LAUNCHD_SHUTDOWN_LOG "launchd-shutdown.%s.log" 14 | #define LAUNCHD_LOWLEVEL_LOG "launchd-lowlevel.%s.log" 15 | 16 | os_redirect_assumes(_launchd_os_redirect); 17 | 18 | char *launchd_username = "unknown"; 19 | char *launchd_label = "com.apple.launchd.unknown"; 20 | mach_port_t launchd_drain_reply_port; 21 | bool launchd_var_available = false; 22 | int64_t launchd_system_start; 23 | 24 | static FILE *_launchd_shutdown_log; 25 | static FILE *_launchd_debug_log; 26 | static FILE *_launchd_perf_log; 27 | static STAILQ_HEAD(, logmsg_s) _launchd_logq = STAILQ_HEAD_INITIALIZER(_launchd_logq); 28 | static size_t _launchd_logq_sz; 29 | static size_t _launchd_logq_cnt; 30 | static int _launchd_log_up2 = LOG_UPTO(LOG_NOTICE); 31 | 32 | static int64_t _launchd_shutdown_start; 33 | 34 | struct _launchd_open_log_ctx_s { 35 | const char *path; 36 | FILE **filep; 37 | }; 38 | 39 | static void 40 | _launchd_open_log_once(void *ctx) 41 | { 42 | struct _launchd_open_log_ctx_s *ctx2 = ctx; 43 | const char *path = ctx2->path; 44 | FILE **filep = ctx2->filep; 45 | 46 | char saved[PATH_MAX]; 47 | snprintf(saved, sizeof(saved), "%s.1", path); 48 | (void)rename(path, saved); 49 | 50 | FILE *file = fopen(path, "w"); 51 | if (file) { 52 | (void)_fd(fileno(file)); 53 | *filep = file; 54 | } else if (launchd_console) { 55 | fprintf(launchd_console, "Could not open %s: %d: %s\n", path, errno, strerror(errno)); 56 | } 57 | } 58 | 59 | static void 60 | _launchd_shutdown_start_once(void *ctx __attribute__((unused))) 61 | { 62 | _launchd_shutdown_start = runtime_get_wall_time(); 63 | } 64 | 65 | int 66 | runtime_setlogmask(int maskpri) 67 | { 68 | _launchd_log_up2 = maskpri; 69 | return _launchd_log_up2; 70 | } 71 | 72 | static bool 73 | _logmsg_add(struct launchd_syslog_attr *attr, int err_num, const char *msg) 74 | { 75 | size_t lm_sz = sizeof(struct logmsg_s) + strlen(msg) + strlen(attr->from_name) + strlen(attr->about_name) + strlen(attr->session_name) + 4; 76 | char *data_off; 77 | struct logmsg_s *lm; 78 | 79 | /* Force the unpacking for the log_drain cause unalignment faults. */ 80 | lm_sz = ROUND_TO_64BIT_WORD_SIZE(lm_sz); 81 | 82 | if (unlikely((lm = calloc(1, lm_sz)) == NULL)) { 83 | return false; 84 | } 85 | 86 | data_off = lm->data; 87 | 88 | lm->when = runtime_get_wall_time(); 89 | lm->from_pid = attr->from_pid; 90 | lm->about_pid = attr->about_pid; 91 | lm->err_num = err_num; 92 | lm->pri = attr->priority; 93 | lm->obj_sz = lm_sz; 94 | lm->msg = data_off; 95 | data_off += sprintf(data_off, "%s", msg) + 1; 96 | lm->from_name = data_off; 97 | data_off += sprintf(data_off, "%s", attr->from_name) + 1; 98 | lm->about_name = data_off; 99 | data_off += sprintf(data_off, "%s", attr->about_name) + 1; 100 | lm->session_name = data_off; 101 | data_off += sprintf(data_off, "%s", attr->session_name) + 1; 102 | 103 | STAILQ_INSERT_TAIL(&_launchd_logq, lm, sqe); 104 | _launchd_logq_sz += lm_sz; 105 | _launchd_logq_cnt++; 106 | 107 | return true; 108 | } 109 | 110 | static void 111 | _logmsg_remove(struct logmsg_s *lm) 112 | { 113 | STAILQ_REMOVE(&_launchd_logq, lm, logmsg_s, sqe); 114 | _launchd_logq_sz -= lm->obj_sz; 115 | _launchd_logq_cnt--; 116 | 117 | free(lm); 118 | } 119 | 120 | bool 121 | _launchd_os_redirect(const char *message) 122 | { 123 | launchd_syslog(LOG_ERR, "%s", message); 124 | return true; 125 | } 126 | 127 | void 128 | launchd_syslog(int pri, const char *message, ...) 129 | { 130 | struct launchd_syslog_attr attr = { 131 | .from_name = launchd_label, 132 | .about_name = launchd_label, 133 | .session_name = pid1_magic ? "System" : "Background", 134 | .priority = pri, 135 | .from_uid = launchd_uid, 136 | .from_pid = getpid(), 137 | .about_pid = getpid(), 138 | }; 139 | 140 | va_list ap; 141 | 142 | va_start(ap, message); 143 | launchd_vsyslog(&attr, message, ap); 144 | va_end(ap); 145 | } 146 | 147 | void 148 | launchd_vsyslog(struct launchd_syslog_attr *attr, const char *fmt, va_list args) 149 | { 150 | int saved_errno = errno; 151 | char message[2048]; 152 | 153 | static dispatch_once_t perf_once = 0; 154 | static dispatch_once_t shutdown_once = 0; 155 | static dispatch_once_t shutdown_start_once = 0; 156 | static dispatch_once_t debug_once = 0; 157 | 158 | bool echo2console = (attr->priority & LOG_CONSOLE); 159 | attr->priority &= ~LOG_CONSOLE; 160 | if (attr->priority == LOG_APPLEONLY && launchd_apple_internal) { 161 | attr->priority = LOG_NOTICE; 162 | } 163 | 164 | FILE *log2here = NULL; 165 | 166 | /* launchctl is responsible for mounting /var as read-write. So we need to 167 | * wait until /var/log is available before trying to log anything to our log 168 | * anything to our auxilliary log files. This is kind of a hack because 169 | * we'll lose the first few relevant messages at boot for debug and 170 | * performance logging, but the loss isn't too bad. 171 | */ 172 | if (launchd_var_available) { 173 | /* This file is for logging low-level errors where we can't necessarily be 174 | * assured that we can write to the console or use syslog. 175 | */ 176 | char *store = launchd_copy_persistent_store(LAUNCHD_PERSISTENT_STORE_LOGS, NULL); 177 | char path[PATH_MAX]; 178 | 179 | if (attr->priority == LOG_PERF) { 180 | if (launchd_log_perf) { 181 | (void)snprintf(path, sizeof(path), "%s" LAUNCHD_PERF_LOG, store, launchd_username); 182 | 183 | struct _launchd_open_log_ctx_s ctx2 = { 184 | .path = path, 185 | .filep = &_launchd_perf_log, 186 | }; 187 | dispatch_once_f(&perf_once, &ctx2, _launchd_open_log_once); 188 | log2here = _launchd_perf_log; 189 | } 190 | 191 | // Don't log performance messages to the normal syslog store. 192 | attr->priority = LOG_DEBUG + 1; 193 | } else { 194 | if (launchd_shutting_down && launchd_log_shutdown) { 195 | dispatch_once_f(&shutdown_start_once, NULL, _launchd_shutdown_start_once); 196 | 197 | (void)snprintf(path, sizeof(path), "%s" LAUNCHD_SHUTDOWN_LOG, store, launchd_username); 198 | 199 | struct _launchd_open_log_ctx_s ctx2 = { 200 | .path = path, 201 | .filep = &_launchd_shutdown_log, 202 | }; 203 | dispatch_once_f(&shutdown_once, &ctx2, _launchd_open_log_once); 204 | log2here = _launchd_shutdown_log; 205 | } else if (launchd_log_debug) { 206 | (void)snprintf(path, sizeof(path), "%s" LAUNCHD_DEBUG_LOG, store, launchd_username); 207 | 208 | struct _launchd_open_log_ctx_s ctx2 = { 209 | .path = path, 210 | .filep = &_launchd_debug_log, 211 | }; 212 | dispatch_once_f(&debug_once, &ctx2, _launchd_open_log_once); 213 | log2here = _launchd_debug_log; 214 | } 215 | } 216 | 217 | free(store); 218 | 219 | } 220 | 221 | vsnprintf(message, sizeof(message), fmt, args); 222 | if (echo2console && launchd_console) { 223 | fprintf(launchd_console, "%-32s %-8u %-64s %-8u %s\n", attr->from_name, attr->from_pid, attr->about_name, attr->about_pid, message); 224 | } 225 | 226 | if (log2here) { 227 | int64_t delta = 0; 228 | if (log2here == _launchd_shutdown_log) { 229 | delta = runtime_get_wall_time() - _launchd_shutdown_start; 230 | } else { 231 | delta = runtime_get_wall_time() - launchd_system_start; 232 | } 233 | 234 | fprintf(log2here, "%-8lld %-32s %-8u %-24s %-8u %s\n", delta, attr->from_name, attr->from_pid, attr->about_name, attr->about_pid, message); 235 | } 236 | 237 | if ((LOG_MASK(attr->priority) & _launchd_log_up2)) { 238 | _logmsg_add(attr, saved_errno, message); 239 | } 240 | } 241 | 242 | static kern_return_t 243 | _launchd_log_pack(vm_offset_t *outval, mach_msg_type_number_t *outvalCnt) 244 | { 245 | struct logmsg_s *lm; 246 | void *offset; 247 | 248 | *outvalCnt = _launchd_logq_sz; 249 | 250 | mig_allocate(outval, *outvalCnt); 251 | 252 | if (unlikely(*outval == 0)) { 253 | return 1; 254 | } 255 | 256 | offset = (void *)*outval; 257 | while ((lm = STAILQ_FIRST(&_launchd_logq))) { 258 | lm->from_name_offset = lm->from_name - (char *)lm; 259 | lm->about_name_offset = lm->about_name - (char *)lm; 260 | lm->msg_offset = lm->msg - (char *)lm; 261 | lm->session_name_offset = lm->session_name - (char *)lm; 262 | 263 | memcpy(offset, lm, lm->obj_sz); 264 | 265 | offset += lm->obj_sz; 266 | 267 | _logmsg_remove(lm); 268 | } 269 | 270 | return 0; 271 | } 272 | 273 | static void 274 | _launchd_log_uncork_pending_drain(void) 275 | { 276 | mach_msg_type_number_t outvalCnt; 277 | mach_port_t tmp_port; 278 | vm_offset_t outval; 279 | 280 | if (!launchd_drain_reply_port) { 281 | return; 282 | } 283 | 284 | if (_launchd_logq_cnt == 0) { 285 | return; 286 | } 287 | 288 | if (_launchd_log_pack(&outval, &outvalCnt) != 0) { 289 | return; 290 | } 291 | 292 | tmp_port = launchd_drain_reply_port; 293 | launchd_drain_reply_port = MACH_PORT_NULL; 294 | 295 | if (unlikely(errno = job_mig_log_drain_reply(tmp_port, 0, outval, outvalCnt))) { 296 | if (errno != MACH_SEND_INVALID_DEST) { 297 | (void)os_assumes_zero(errno); 298 | } 299 | (void)os_assumes_zero(launchd_mport_deallocate(tmp_port)); 300 | } 301 | 302 | mig_deallocate(outval, outvalCnt); 303 | } 304 | 305 | void 306 | launchd_log_push(void) 307 | { 308 | vm_offset_t outval = 0; 309 | mach_msg_type_number_t outvalCnt = 0; 310 | 311 | if (!pid1_magic) { 312 | if (_launchd_perf_log) { 313 | (void)fflush(_launchd_perf_log); 314 | } 315 | if (_launchd_shutdown_log) { 316 | (void)fflush(_launchd_shutdown_log); 317 | } 318 | if (_launchd_debug_log) { 319 | (void)fflush(_launchd_debug_log); 320 | } 321 | 322 | if (_launchd_logq_cnt && _launchd_log_pack(&outval, &outvalCnt) == 0) { 323 | (void)_vprocmgr_log_forward(inherited_bootstrap_port, (void *)outval, outvalCnt); 324 | mig_deallocate(outval, outvalCnt); 325 | } 326 | } else { 327 | _launchd_log_uncork_pending_drain(); 328 | } 329 | } 330 | 331 | kern_return_t 332 | launchd_log_forward(uid_t forward_uid, gid_t forward_gid, vm_offset_t inval, mach_msg_type_number_t invalCnt) 333 | { 334 | struct logmsg_s *lm, *lm_walk; 335 | mach_msg_type_number_t data_left = invalCnt; 336 | 337 | if (inval == 0) { 338 | return 0; 339 | } 340 | 341 | for (lm_walk = (struct logmsg_s *)inval; (data_left > 0) && (lm_walk->obj_sz <= data_left); lm_walk = ((void *)lm_walk + lm_walk->obj_sz)) { 342 | /* malloc(3) returns non-NULL when you ask for zero bytes. If our object 343 | * is zero bytes, something is wrong. 344 | */ 345 | if (lm_walk->obj_sz == 0) { 346 | launchd_syslog(LOG_WARNING, "Encountered a log message of size 0 with %u bytes left in forwarded data. Ignoring remaining messages.", data_left); 347 | break; 348 | } 349 | 350 | if (!(lm = malloc(lm_walk->obj_sz))) { 351 | launchd_syslog(LOG_WARNING, "Failed to allocate %llu bytes for log message with %u bytes left in forwarded data. Ignoring remaining messages.", lm_walk->obj_sz, data_left); 352 | break; 353 | } 354 | 355 | memcpy(lm, lm_walk, lm_walk->obj_sz); 356 | lm->sender_uid = forward_uid; 357 | lm->sender_gid = forward_gid; 358 | 359 | lm->from_name += (size_t)lm; 360 | lm->about_name += (size_t)lm; 361 | lm->msg += (size_t)lm; 362 | lm->session_name += (size_t)lm; 363 | 364 | STAILQ_INSERT_TAIL(&_launchd_logq, lm, sqe); 365 | _launchd_logq_sz += lm->obj_sz; 366 | _launchd_logq_cnt++; 367 | 368 | data_left -= lm->obj_sz; 369 | } 370 | 371 | mig_deallocate(inval, invalCnt); 372 | 373 | return 0; 374 | } 375 | 376 | kern_return_t 377 | launchd_log_drain(mach_port_t srp, vm_offset_t *outval, mach_msg_type_number_t *outvalCnt) 378 | { 379 | (void)os_assumes_zero(launchd_drain_reply_port); 380 | 381 | if ((_launchd_logq_cnt == 0) || launchd_shutting_down) { 382 | launchd_drain_reply_port = srp; 383 | (void)os_assumes_zero(launchd_mport_notify_req(launchd_drain_reply_port, MACH_NOTIFY_DEAD_NAME)); 384 | 385 | return MIG_NO_REPLY; 386 | } 387 | 388 | return _launchd_log_pack(outval, outvalCnt); 389 | } 390 | 391 | void 392 | launchd_closelog(void) 393 | { 394 | launchd_log_push(); 395 | 396 | if (_launchd_shutdown_log) { 397 | (void)fflush(_launchd_shutdown_log); 398 | (void)runtime_fsync(fileno(_launchd_shutdown_log)); 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /liblaunch/launch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __LAUNCH_H__ 22 | #define __LAUNCH_H__ 23 | 24 | #ifdef __APPLE__ 25 | #define HAS_MACH true 26 | #else 27 | #define HAS_MACH false 28 | #endif 29 | 30 | #if HAS_MACH 31 | #include 32 | #endif 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #pragma GCC visibility push(default) 39 | 40 | __BEGIN_DECLS 41 | 42 | #ifdef __GNUC__ 43 | #define __ld_normal __attribute__((__nothrow__)) 44 | #define __ld_setter __attribute__((__nothrow__, __nonnull__)) 45 | #define __ld_getter __attribute__((__nothrow__, __nonnull__, __pure__, __warn_unused_result__)) 46 | #define __ld_iterator(x, y) __attribute__((__nonnull__(x, y))) 47 | #define __ld_allocator __attribute__((__nothrow__, __malloc__, __nonnull__, __warn_unused_result__)) 48 | #else 49 | #define __ld_normal 50 | #define __ld_setter 51 | #define __ld_getter 52 | #define __ld_iterator(x, y) 53 | #define __ld_allocator 54 | #endif 55 | 56 | #define LAUNCH_KEY_SUBMITJOB "SubmitJob" 57 | #define LAUNCH_KEY_REMOVEJOB "RemoveJob" 58 | #define LAUNCH_KEY_STARTJOB "StartJob" 59 | #define LAUNCH_KEY_STOPJOB "StopJob" 60 | #define LAUNCH_KEY_GETJOB "GetJob" 61 | #define LAUNCH_KEY_GETJOBS "GetJobs" 62 | #define LAUNCH_KEY_CHECKIN "CheckIn" 63 | 64 | #define LAUNCH_JOBKEY_DEFAULTS "__Defaults" 65 | 66 | #define LAUNCH_JOBKEY_LABEL "Label" 67 | #define LAUNCH_JOBKEY_DISABLED "Disabled" 68 | #define LAUNCH_JOBKEY_USERNAME "UserName" 69 | #define LAUNCH_JOBKEY_GROUPNAME "GroupName" 70 | #define LAUNCH_JOBKEY_TIMEOUT "TimeOut" 71 | #define LAUNCH_JOBKEY_EXITTIMEOUT "ExitTimeOut" 72 | #define LAUNCH_JOBKEY_INITGROUPS "InitGroups" 73 | #define LAUNCH_JOBKEY_SOCKETS "Sockets" 74 | #define LAUNCH_JOBKEY_MACHSERVICES "MachServices" 75 | #define LAUNCH_JOBKEY_MACHSERVICELOOKUPPOLICIES "MachServiceLookupPolicies" 76 | #define LAUNCH_JOBKEY_INETDCOMPATIBILITY "inetdCompatibility" 77 | #define LAUNCH_JOBKEY_ENABLEGLOBBING "EnableGlobbing" 78 | #define LAUNCH_JOBKEY_PROGRAMARGUMENTS "ProgramArguments" 79 | #define LAUNCH_JOBKEY_PROGRAM "Program" 80 | #define LAUNCH_JOBKEY_ONDEMAND "OnDemand" 81 | #define LAUNCH_JOBKEY_KEEPALIVE "KeepAlive" 82 | #define LAUNCH_JOBKEY_LIMITLOADTOHOSTS "LimitLoadToHosts" 83 | #define LAUNCH_JOBKEY_LIMITLOADFROMHOSTS "LimitLoadFromHosts" 84 | #define LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE "LimitLoadToSessionType" 85 | #define LAUNCH_JOBKEY_LIMITLOADTOHARDWARE "LimitLoadToHardware" 86 | #define LAUNCH_JOBKEY_LIMITLOADFROMHARDWARE "LimitLoadFromHardware" 87 | #define LAUNCH_JOBKEY_RUNATLOAD "RunAtLoad" 88 | #define LAUNCH_JOBKEY_ROOTDIRECTORY "RootDirectory" 89 | #define LAUNCH_JOBKEY_WORKINGDIRECTORY "WorkingDirectory" 90 | #define LAUNCH_JOBKEY_ENVIRONMENTVARIABLES "EnvironmentVariables" 91 | #define LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES "UserEnvironmentVariables" 92 | #define LAUNCH_JOBKEY_UMASK "Umask" 93 | #define LAUNCH_JOBKEY_NICE "Nice" 94 | #define LAUNCH_JOBKEY_HOPEFULLYEXITSFIRST "HopefullyExitsFirst" 95 | #define LAUNCH_JOBKEY_HOPEFULLYEXITSLAST "HopefullyExitsLast" 96 | #define LAUNCH_JOBKEY_LOWPRIORITYIO "LowPriorityIO" 97 | #define LAUNCH_JOBKEY_SESSIONCREATE "SessionCreate" 98 | #define LAUNCH_JOBKEY_STARTONMOUNT "StartOnMount" 99 | #define LAUNCH_JOBKEY_SOFTRESOURCELIMITS "SoftResourceLimits" 100 | #define LAUNCH_JOBKEY_HARDRESOURCELIMITS "HardResourceLimits" 101 | #define LAUNCH_JOBKEY_STANDARDINPATH "StandardInPath" 102 | #define LAUNCH_JOBKEY_STANDARDOUTPATH "StandardOutPath" 103 | #define LAUNCH_JOBKEY_STANDARDERRORPATH "StandardErrorPath" 104 | #define LAUNCH_JOBKEY_DEBUG "Debug" 105 | #define LAUNCH_JOBKEY_WAITFORDEBUGGER "WaitForDebugger" 106 | #define LAUNCH_JOBKEY_QUEUEDIRECTORIES "QueueDirectories" 107 | #define LAUNCH_JOBKEY_WATCHPATHS "WatchPaths" 108 | #define LAUNCH_JOBKEY_STARTINTERVAL "StartInterval" 109 | #define LAUNCH_JOBKEY_STARTCALENDARINTERVAL "StartCalendarInterval" 110 | #define LAUNCH_JOBKEY_BONJOURFDS "BonjourFDs" 111 | #define LAUNCH_JOBKEY_LASTEXITSTATUS "LastExitStatus" 112 | #define LAUNCH_JOBKEY_PID "PID" 113 | #define LAUNCH_JOBKEY_THROTTLEINTERVAL "ThrottleInterval" 114 | #define LAUNCH_JOBKEY_LAUNCHONLYONCE "LaunchOnlyOnce" 115 | #define LAUNCH_JOBKEY_ABANDONPROCESSGROUP "AbandonProcessGroup" 116 | #define LAUNCH_JOBKEY_IGNOREPROCESSGROUPATSHUTDOWN "IgnoreProcessGroupAtShutdown" 117 | #define LAUNCH_JOBKEY_POLICIES "Policies" 118 | #define LAUNCH_JOBKEY_ENABLETRANSACTIONS "EnableTransactions" 119 | #define LAUNCH_JOBKEY_CFBUNDLEIDENTIFIER "CFBundleIdentifier" 120 | #define LAUNCH_JOBKEY_PROCESSTYPE "ProcessType" 121 | #define LAUNCH_KEY_PROCESSTYPE_APP "App" 122 | #define LAUNCH_KEY_PROCESSTYPE_STANDARD "Standard" 123 | #define LAUNCH_KEY_PROCESSTYPE_BACKGROUND "Background" 124 | #define LAUNCH_KEY_PROCESSTYPE_INTERACTIVE "Interactive" 125 | #define LAUNCH_KEY_PROCESSTYPE_ADAPTIVE "Adaptive" 126 | 127 | #define LAUNCH_JOBPOLICY_DENYCREATINGOTHERJOBS "DenyCreatingOtherJobs" 128 | 129 | #define LAUNCH_JOBINETDCOMPATIBILITY_WAIT "Wait" 130 | 131 | #define LAUNCH_JOBKEY_MACH_RESETATCLOSE "ResetAtClose" 132 | #define LAUNCH_JOBKEY_MACH_HIDEUNTILCHECKIN "HideUntilCheckIn" 133 | #define LAUNCH_JOBKEY_MACH_DRAINMESSAGESONCRASH "DrainMessagesOnCrash" 134 | #define LAUNCH_JOBKEY_MACH_PINGEVENTUPDATES "PingEventUpdates" 135 | 136 | #define LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT "SuccessfulExit" 137 | #define LAUNCH_JOBKEY_KEEPALIVE_NETWORKSTATE "NetworkState" 138 | #define LAUNCH_JOBKEY_KEEPALIVE_PATHSTATE "PathState" 139 | #define LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBACTIVE "OtherJobActive" 140 | #define LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBENABLED "OtherJobEnabled" 141 | #define LAUNCH_JOBKEY_KEEPALIVE_AFTERINITIALDEMAND "AfterInitialDemand" 142 | #define LAUNCH_JOBKEY_KEEPALIVE_CRASHED "Crashed" 143 | 144 | #define LAUNCH_JOBKEY_LAUNCHEVENTS "LaunchEvents" 145 | 146 | #define LAUNCH_JOBKEY_CAL_MINUTE "Minute" 147 | #define LAUNCH_JOBKEY_CAL_HOUR "Hour" 148 | #define LAUNCH_JOBKEY_CAL_DAY "Day" 149 | #define LAUNCH_JOBKEY_CAL_WEEKDAY "Weekday" 150 | #define LAUNCH_JOBKEY_CAL_MONTH "Month" 151 | 152 | #define LAUNCH_JOBKEY_RESOURCELIMIT_CORE "Core" 153 | #define LAUNCH_JOBKEY_RESOURCELIMIT_CPU "CPU" 154 | #define LAUNCH_JOBKEY_RESOURCELIMIT_DATA "Data" 155 | #define LAUNCH_JOBKEY_RESOURCELIMIT_FSIZE "FileSize" 156 | #define LAUNCH_JOBKEY_RESOURCELIMIT_MEMLOCK "MemoryLock" 157 | #define LAUNCH_JOBKEY_RESOURCELIMIT_NOFILE "NumberOfFiles" 158 | #define LAUNCH_JOBKEY_RESOURCELIMIT_NPROC "NumberOfProcesses" 159 | #define LAUNCH_JOBKEY_RESOURCELIMIT_RSS "ResidentSetSize" 160 | #define LAUNCH_JOBKEY_RESOURCELIMIT_STACK "Stack" 161 | 162 | #define LAUNCH_JOBKEY_DISABLED_MACHINETYPE "MachineType" 163 | #define LAUNCH_JOBKEY_DISABLED_MODELNAME "ModelName" 164 | 165 | #define LAUNCH_JOBSOCKETKEY_TYPE "SockType" 166 | #define LAUNCH_JOBSOCKETKEY_PASSIVE "SockPassive" 167 | #define LAUNCH_JOBSOCKETKEY_BONJOUR "Bonjour" 168 | #define LAUNCH_JOBSOCKETKEY_SECUREWITHKEY "SecureSocketWithKey" 169 | #define LAUNCH_JOBSOCKETKEY_PATHNAME "SockPathName" 170 | #define LAUNCH_JOBSOCKETKEY_PATHMODE "SockPathMode" 171 | #define LAUNCH_JOBSOCKETKEY_NODENAME "SockNodeName" 172 | #define LAUNCH_JOBSOCKETKEY_SERVICENAME "SockServiceName" 173 | #define LAUNCH_JOBSOCKETKEY_FAMILY "SockFamily" 174 | #define LAUNCH_JOBSOCKETKEY_PROTOCOL "SockProtocol" 175 | #define LAUNCH_JOBSOCKETKEY_MULTICASTGROUP "MulticastGroup" 176 | 177 | /* These APIs are NOT suitable for general use. Their use should be constrained 178 | * to checking into launchd to obtain socket file descriptors using the 179 | * LAUNCH_CHECK_IN message type. 180 | */ 181 | typedef struct _launch_data *launch_data_t; 182 | struct _launch_data { 183 | uint64_t type; 184 | union { 185 | struct { 186 | union { 187 | launch_data_t *_array; 188 | char *string; 189 | void *opaque; 190 | int64_t __junk; 191 | }; 192 | union { 193 | uint64_t _array_cnt; 194 | uint64_t string_len; 195 | uint64_t opaque_size; 196 | }; 197 | }; 198 | int64_t fd; 199 | uint64_t mp; 200 | uint64_t err; 201 | int64_t number; 202 | uint64_t boolean; /* We'd use 'bool' but this struct needs to be used under Rosetta, and sizeof(bool) is different between PowerPC and Intel */ 203 | double float_num; 204 | }; 205 | }; 206 | 207 | typedef enum { 208 | LAUNCH_DATA_DICTIONARY = 1, 209 | LAUNCH_DATA_ARRAY, 210 | LAUNCH_DATA_FD, 211 | LAUNCH_DATA_INTEGER, 212 | LAUNCH_DATA_REAL, 213 | LAUNCH_DATA_BOOL, 214 | LAUNCH_DATA_STRING, 215 | LAUNCH_DATA_OPAQUE, 216 | LAUNCH_DATA_ERRNO, 217 | #if HAS_MACH 218 | LAUNCH_DATA_MACHPORT, 219 | #endif 220 | } launch_data_type_t; 221 | 222 | __ld_allocator 223 | launch_data_t 224 | launch_data_alloc(launch_data_type_t); 225 | 226 | __ld_allocator 227 | launch_data_t 228 | launch_data_copy(launch_data_t); 229 | 230 | __ld_getter 231 | launch_data_type_t 232 | launch_data_get_type(const launch_data_t); 233 | 234 | __ld_setter 235 | void 236 | launch_data_free(launch_data_t); 237 | 238 | __ld_setter 239 | bool 240 | launch_data_dict_insert(launch_data_t, const launch_data_t, const char *); 241 | 242 | __ld_getter 243 | launch_data_t 244 | launch_data_dict_lookup(const launch_data_t, const char *); 245 | 246 | __ld_setter 247 | bool 248 | launch_data_dict_remove(launch_data_t, const char *); 249 | 250 | __ld_iterator(1, 2) 251 | void 252 | launch_data_dict_iterate(const launch_data_t, 253 | void (*)(const launch_data_t, const char *, void *), void *); 254 | 255 | __ld_getter 256 | size_t 257 | launch_data_dict_get_count(const launch_data_t); 258 | 259 | __ld_setter 260 | bool 261 | launch_data_array_set_index(launch_data_t, const launch_data_t, size_t); 262 | 263 | __ld_getter 264 | launch_data_t 265 | launch_data_array_get_index(const launch_data_t, size_t); 266 | 267 | __ld_getter 268 | size_t 269 | launch_data_array_get_count(const launch_data_t); 270 | 271 | __ld_allocator 272 | launch_data_t 273 | launch_data_new_fd(int); 274 | 275 | #if HAS_MACH 276 | __ld_allocator 277 | launch_data_t 278 | launch_data_new_machport(mach_port_t); 279 | 280 | __ld_setter 281 | bool 282 | launch_data_set_machport(launch_data_t, mach_port_t); 283 | 284 | __ld_getter 285 | mach_port_t 286 | launch_data_get_machport(const launch_data_t); 287 | #endif 288 | 289 | __ld_allocator 290 | launch_data_t 291 | launch_data_new_integer(long long); 292 | 293 | __ld_allocator 294 | launch_data_t 295 | launch_data_new_bool(bool); 296 | 297 | __ld_allocator 298 | launch_data_t 299 | launch_data_new_real(double); 300 | 301 | __ld_allocator 302 | launch_data_t 303 | launch_data_new_string(const char *); 304 | 305 | __ld_allocator 306 | launch_data_t 307 | launch_data_new_opaque(const void *, size_t); 308 | 309 | __ld_setter 310 | bool 311 | launch_data_set_fd(launch_data_t, int); 312 | 313 | __ld_setter 314 | bool 315 | launch_data_set_integer(launch_data_t, long long); 316 | 317 | __ld_setter 318 | bool 319 | launch_data_set_bool(launch_data_t, bool); 320 | 321 | __ld_setter 322 | bool 323 | launch_data_set_real(launch_data_t, double); 324 | 325 | __ld_setter 326 | bool 327 | launch_data_set_string(launch_data_t, const char *); 328 | 329 | __ld_setter 330 | bool 331 | launch_data_set_opaque(launch_data_t, const void *, size_t); 332 | 333 | __ld_getter 334 | int 335 | launch_data_get_fd(const launch_data_t); 336 | 337 | __ld_getter 338 | long long 339 | launch_data_get_integer(const launch_data_t); 340 | 341 | __ld_getter 342 | bool 343 | launch_data_get_bool(const launch_data_t); 344 | 345 | __ld_getter 346 | double 347 | launch_data_get_real(const launch_data_t); 348 | 349 | __ld_getter 350 | const char * 351 | launch_data_get_string(const launch_data_t); 352 | 353 | __ld_getter 354 | void * 355 | launch_data_get_opaque(const launch_data_t); 356 | 357 | __ld_getter 358 | size_t 359 | launch_data_get_opaque_size(const launch_data_t); 360 | 361 | __ld_getter 362 | int 363 | launch_data_get_errno(const launch_data_t); 364 | 365 | 366 | /* launch_get_fd() 367 | * 368 | * Use this to get the FD if you're doing asynchronous I/O with select(), 369 | * poll() or kevent(). 370 | */ 371 | __ld_normal 372 | int 373 | launch_get_fd(void); 374 | 375 | /* launch_msg() 376 | * 377 | * Use this API to check in. Nothing else. 378 | */ 379 | __ld_normal 380 | launch_data_t 381 | launch_msg(const launch_data_t); 382 | 383 | __END_DECLS 384 | 385 | #pragma GCC visibility pop 386 | 387 | #endif /* __LAUNCH_H__ */ 388 | --------------------------------------------------------------------------------