Revision: 23025 http://trac.macosforge.org/projects/launchd/changeset/23025 Author: zarzycki@apple.com Date: 2007-01-28 13:15:53 -0800 (Sun, 28 Jan 2007) Log Message: ----------- The last remaining customer (loginwindow) of /etc/ttys has switched to launchd. This is the easy part or removing init.c. The next stage will be to deal with single-user-mode in launchd proper and clean up launchd's self-bootstrap logic. Then we can finally delete init.c. Modified Paths: -------------- trunk/launchd/src/init.c trunk/launchd/src/launchctl.1 trunk/launchd/src/launchctl.c trunk/launchd/src/launchd.c trunk/launchd/src/launchd.h trunk/launchd/src/launchd_unix_ipc.c trunk/launchd/src/liblaunch_private.h Modified: trunk/launchd/src/init.c =================================================================== --- trunk/launchd/src/init.c 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/init.c 2007-01-28 21:15:53 UTC (rev 23025) @@ -55,10 +55,6 @@ static const char *const __rcs_file_version__ = "$Revision$"; -#include <Security/Authorization.h> -#include <Security/AuthorizationTags.h> -#include <Security/AuthSession.h> - #include <sys/types.h> #include <sys/queue.h> #include <sys/param.h> @@ -91,14 +87,7 @@ #define _PATH_RUNCOM "/etc/rc" -/* - * Sleep times; used to prevent thrashing. - */ -#define GETTY_SPACING 5 /* N secs minimum getty spacing */ -#define GETTY_SLEEP 30 /* sleep N secs after spacing problem */ #define STALL_TIMEOUT 30 /* wait N secs after warning */ -#define DEATH_WATCH 10 /* wait N secs for procs to die */ -#define FAILED_HW_PASS 5 /* wait N secs before croaking user */ static void stall(char *, ...); @@ -117,58 +106,8 @@ static void setctty(const char *, int); -// gvdl@next.com 14 Aug 1995 -// - from ~apps/loginwindow_proj/loginwindow/common.h -#define REALLY_EXIT_TO_CONSOLE 229 - -// From old init.c -// These flags are used in the se_flags field of the init_session structure -#define SE_SHUTDOWN 0x1 /* session won't be restarted */ - -// The flags below control what sort of getty is launched. -#define SE_GETTY_LAUNCH 0x30 /* What type of getty to launch */ -#define SE_COMMON 0x00 /* Usual command that is run - getty */ -#define SE_ONERROR 0x10 /* Command to run if error condition occurs. - * This will almost always be the windowserver - * and loginwindow. This is so if the w.s. - * ever dies, that the naive user (stan) - * doesn't ever see the console window. */ -#define SE_ONOPTION 0x20 /* Command to run when loginwindow exits with - * special error code (229). This signifies - * that the user typed "console" at l.w. and - * l.w. wants to exit and have init run getty - * which will then put up a console window. */ - -typedef struct _se_command { - char *path; /* what to run on that port */ - char **argv; /* pre-parsed argument array */ -} se_cmd_t; - -typedef struct init_session { - kq_callback se_callback; /* run loop callback */ - int se_index; /* index of entry in ttys file */ - pid_t se_process; /* controlling process */ - time_t se_started; /* used to avoid thrashing */ - int se_flags; /* status of session */ - char *se_device; /* filename of port */ - se_cmd_t se_getty; /* what to run on that port */ - se_cmd_t se_onerror; /* See SE_ONERROR above */ - se_cmd_t se_onoption; /* See SE_ONOPTION above */ - TAILQ_ENTRY(init_session) tqe; -} *session_t; - -static TAILQ_HEAD(sessionshead, init_session) sessions = TAILQ_HEAD_INITIALIZER(sessions); - -static void session_new(int, struct ttyent *); -static void session_free(session_t); -static void session_launch(session_t); -static void session_reap(session_t); -static void session_callback(void *, struct kevent *); - -static char **construct_argv(char *); static void setsecuritylevel(int); static int getsecuritylevel(void); -static int setupargv(session_t, struct ttyent *); static bool should_fsck(void); void @@ -183,8 +122,6 @@ void init_pre_kevent(void) { - session_t s; - if (single_user_pid || runcom_pid) return; @@ -200,16 +137,12 @@ * mode, and the run script has not set a higher level of security * than level 1, then put the kernel into secure mode. */ - if (getsecuritylevel() == 0) + if (getsecuritylevel() == 0) { setsecuritylevel(1); - - TAILQ_FOREACH(s, &sessions, tqe) { - if (s->se_process == 0) - session_launch(s); } } -static void +void stall(char *message, ...) { va_list ap; @@ -220,7 +153,7 @@ sleep(STALL_TIMEOUT); } -static int +int getsecuritylevel(void) { int name[2], curlevel; @@ -236,7 +169,7 @@ return curlevel; } -static void +void setsecuritylevel(int newlevel) { int name[2], curlevel; @@ -259,7 +192,7 @@ * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ -static void +void setctty(const char *name, int flags) { int fd; @@ -275,7 +208,7 @@ } } -static void +void single_user(void) { bool runcom_fsck = should_fsck(); @@ -315,7 +248,7 @@ } } -static void +void single_user_callback(void *obj __attribute__((unused)), struct kevent *kev __attribute__((unused))) { int status; @@ -338,10 +271,11 @@ } static struct timeval runcom_start_tv = { 0, 0 }; + /* * Run the system startup script. */ -static void +void runcom(void) { char *argv[] = { "/bin/launchctl", "bootstrap", NULL }; @@ -389,7 +323,7 @@ exit(EXIT_FAILURE); } -static void +void runcom_callback(void *obj __attribute__((unused)), struct kevent *kev __attribute__((unused))) { int status; @@ -421,323 +355,9 @@ single_user_mode = true; } -/* - * Construct an argument vector from a command line. - */ -char ** -construct_argv(command) - char *command; +bool +init_check_pid(pid_t p) { - int argc = 0; - char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1) - * sizeof (char *)); - static const char separators[] = " \t"; - - if ((argv[argc++] = strtok(command, separators)) == 0) - return 0; - while ((argv[argc++] = strtok(NULL, separators))) - continue; - return argv; -} - -/* - * Deallocate a session descriptor. - */ - -static void free_command(se_cmd_t *se_cmd) -{ - if (se_cmd->path) { - free(se_cmd->path); - free(se_cmd->argv); - } -} - -void -session_free(session_t s) -{ - TAILQ_REMOVE(&sessions, s, tqe); - if (s->se_process) { - if (kevent_mod(s->se_process, EVFILT_PROC, EV_ADD, - NOTE_EXIT, 0, &kqsimple_zombie_reaper) == -1) - session_reap(s); - else - kill(s->se_process, SIGHUP); - } - free(s->se_device); - free_command(&s->se_getty); - free_command(&s->se_onerror); - free_command(&s->se_onoption); - free(s); -} - -static int setup_command(se_cmd_t *se_cmd, char *command, char *arg ) -{ - char *commandWithArg; - - asprintf(&commandWithArg, "%s %s", command, arg); - - free_command(se_cmd); - - se_cmd->path = commandWithArg; - se_cmd->argv = construct_argv(commandWithArg); - if (se_cmd->argv == NULL) { - free(se_cmd->path); - se_cmd->path = NULL; - return 0; - } - return 1; -} - -/* - * Calculate getty and if useful window argv vectors. - */ -static int -setupargv(sp, typ) - session_t sp; - struct ttyent *typ; -{ - char *type; - - if ( !setup_command(&sp->se_getty, typ->ty_getty, typ->ty_name) ) - { - type = "getty"; - goto bad_args; - } - - if (typ->ty_onerror - && !setup_command(&sp->se_onerror, typ->ty_onerror, typ->ty_name) ) - { - type = "onerror"; - goto bad_args; - } - - if (typ->ty_onoption - && !setup_command(&sp->se_onoption, typ->ty_onoption, typ->ty_name) ) - { - type = "onoption"; - goto bad_args; - } - - return 1; - -bad_args: - syslog(LOG_WARNING, "can't parse %s for port %s", type, sp->se_device); - return 0; -} - - -/* - * Allocate a new session descriptor. - */ -void -session_new(session_index, typ) - int session_index; - struct ttyent *typ; -{ - session_t s; - - if ((typ->ty_status & TTY_ON) == 0 || - typ->ty_name == 0 || - typ->ty_getty == 0) - return; - - s = calloc(1, sizeof(struct init_session)); - - s->se_callback = session_callback; - s->se_index = session_index; - - TAILQ_INSERT_TAIL(&sessions, s, tqe); - - asprintf(&s->se_device, "%s%s", _PATH_DEV, typ->ty_name); - - if (setupargv(s, typ) == 0) - session_free(s); -} - -static void -session_launch(session_t s) -{ - pid_t pid; - sigset_t mask; - se_cmd_t *se_cmd; - const char *session_type = NULL; - time_t current_time = time(NULL); - bool is_loginwindow = false; - - // Setup the default values; - switch (s->se_flags & SE_GETTY_LAUNCH) { - case SE_ONOPTION: - if (s->se_onoption.path) { - se_cmd = &s->se_onoption; - session_type = "onoption"; - break; - } - /* No break */ - case SE_ONERROR: - if (s->se_onerror.path) { - se_cmd = &s->se_onerror; - session_type = "onerror"; - break; - } - /* No break */ - case SE_COMMON: - default: - se_cmd = &s->se_getty; - session_type = "getty"; - break; - } - - if (strcmp(se_cmd->argv[0], "/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow") == 0) - is_loginwindow = true; - - pid = launchd_fork(); - - if (pid == -1) { - syslog(LOG_ERR, "can't fork for %s on port %s: %m", - session_type, s->se_device); - return; - } - - if (pid) { - s->se_process = pid; - s->se_started = time(NULL); - s->se_flags &= ~SE_GETTY_LAUNCH; // clear down getty launch type - if (kevent_mod(pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, &s->se_callback) == -1) - session_reap(s); - return; - } - - if (current_time > s->se_started && - current_time - s->se_started < GETTY_SPACING) { - syslog(LOG_WARNING, "%s repeating too quickly on port %s, sleeping", - session_type, s->se_device); - sleep(GETTY_SLEEP); - } - - sigemptyset(&mask); - sigprocmask(SIG_SETMASK, &mask, NULL); - - - if (!is_loginwindow) - launchd_SessionCreate(); - - execv(se_cmd->argv[0], se_cmd->argv); - stall("can't exec %s '%s' for port %s: %m", session_type, - se_cmd->argv[0], s->se_device); - exit(EXIT_FAILURE); -} - -static void -session_callback(void *obj, struct kevent *kev __attribute__((unused))) -{ - session_t s = obj; - - session_reap(s); - if (s->se_flags & SE_SHUTDOWN) { - session_free(s); - } else { - session_launch(s); - } -} - -static void -session_reap(session_t s) -{ - char *line; - int status; - - if (!launchd_assumes(waitpid(s->se_process, &status, 0) == s->se_process)) - return; - - if (WIFSIGNALED(status)) { - syslog(LOG_WARNING, "%s port %s exited abnormally: %s", - s->se_getty.path, s->se_device, strsignal(WTERMSIG(status))); - s->se_flags |= SE_ONERROR; - } else if (WEXITSTATUS(status) == REALLY_EXIT_TO_CONSOLE) { - /* WIFEXITED(status) assumed */ - s->se_flags |= SE_ONOPTION; - } else { - s->se_flags |= SE_ONERROR; - } - - s->se_process = 0; - line = s->se_device + sizeof(_PATH_DEV) - 1; - - if (logout(line)) - logwtmp(line, "", ""); -} - -/* - * This is an n-squared algorithm. We hope it isn't run often... - */ -void -update_ttys(void) -{ - session_t sp; - struct ttyent *typ; - int session_index = 0; - int devlen; - - devlen = sizeof(_PATH_DEV) - 1; - while ((typ = getttyent())) { - ++session_index; - - TAILQ_FOREACH(sp, &sessions, tqe) { - if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) - break; - } - - if (sp == NULL) { - session_new(session_index, typ); - continue; - } - - if (sp->se_index != session_index) { - syslog(LOG_INFO, "port %s changed utmp index from %d to %d", - sp->se_device, sp->se_index, - session_index); - sp->se_index = session_index; - } - - if ((typ->ty_status & TTY_ON) == 0 || - typ->ty_getty == 0) { - session_free(sp); - continue; - } - - sp->se_flags &= ~SE_SHUTDOWN; - - if (setupargv(sp, typ) == 0) { - syslog(LOG_WARNING, "can't parse getty for port %s", - sp->se_device); - session_free(sp); - } - } - - endttyent(); -} - -/* - * Block further logins. - */ -void -catatonia(void) -{ - session_t s; - - TAILQ_FOREACH(s, &sessions, tqe) - s->se_flags |= SE_SHUTDOWN; -} - -bool init_check_pid(pid_t p) -{ - session_t s; - - TAILQ_FOREACH(s, &sessions, tqe) { - if (s->se_process == p) - return true; - } - if (single_user_pid == p) return true; Modified: trunk/launchd/src/launchctl.1 =================================================================== --- trunk/launchd/src/launchctl.1 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/launchctl.1 2007-01-28 21:15:53 UTC (rev 23025) @@ -140,10 +140,6 @@ Tell .Nm launchd to prepare for shutdown by removing all jobs. -.It Ar reloadttys -Tell -.Nm launchd -to reread /etc/ttys. This option may go away in a future release. .It Ar umask Op Ar newmask Get or optionally set the .Xr umask 2 Modified: trunk/launchd/src/launchctl.c =================================================================== --- trunk/launchd/src/launchctl.c 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/launchctl.c 2007-01-28 21:15:53 UTC (rev 23025) @@ -134,7 +134,6 @@ static void empty_dir(const char *thedir, struct stat *psb); static int touch_file(const char *path, mode_t m); static void do_sysversion_sysctl(void); -static void workaround4465949(void); static void do_application_firewall_magic(int sfd, launch_data_t thejob); static void preheat_page_cache_hack(void); static void do_bootroot_magic(void); @@ -185,7 +184,6 @@ { "stderr", stdio_cmd, "Redirect launchd's standard error to the given path" }, { "shutdown", fyi_cmd, "Prepare for system shutdown" }, { "singleuser", fyi_cmd, "Switch to single-user mode" }, - { "reloadttys", fyi_cmd, "Reload /etc/ttys" }, { "getrusage", getrusage_cmd, "Get resource usage statistics from launchd" }, { "log", logupdate_cmd, "Adjust the logging level or mask of launchd" }, { "umask", umask_cmd, "Change launchd's umask" }, @@ -1279,8 +1277,6 @@ const char *SystemStarter_tool[] = { "SystemStarter", NULL }; assumes(fwexec(SystemStarter_tool, false) != -1); - workaround4465949(); - if (path_check("/etc/rc.local")) { const char *rc_local_tool[] = { _PATH_BSHELL, "/etc/rc.local", NULL }; assumes(fwexec(rc_local_tool, false) != -1); @@ -1289,32 +1285,6 @@ return 0; } -void -workaround4465949(void) -{ - const char *pbs_tool[] = { "/System/Library/CoreServices/pbs", NULL }; - const char *lca_tool[] = { "/System/Library/CoreServices/Language Chooser.app/Contents/MacOS/Language Chooser", NULL}; - char *const reloadttys_argv[] = { "reloadttys", NULL }; - int wstatus; - pid_t pbs_p; - - if (path_check("/System/Library/LaunchDaemons/com.apple.loginwindow.plist")) { - return; - } - - if (path_check(pbs_tool[0]) && path_check(lca_tool[0]) && - !path_check("/var/db/.AppleSetupDone") && - path_check("/var/db/.RunLanguageChooserToo")) { - if (assumes((pbs_p = fwexec(pbs_tool, false)) != -1)) { - assumes(fwexec(lca_tool, true) != -1); - assumes(kill(pbs_p, SIGTERM) != -1); - assumes(waitpid(pbs_p, &wstatus, 0) != -1); - } - } - - assumes(fyi_cmd(1, reloadttys_argv) == 0); -} - int load_and_unload_cmd(int argc, char *const argv[]) { @@ -1763,7 +1733,7 @@ fyi_cmd(int argc, char *const argv[]) { launch_data_t resp, msg; - const char *lmsgk = LAUNCH_KEY_RELOADTTYS; + const char *lmsgk = NULL; int e, r = 0; if (argc != 1) { @@ -1775,6 +1745,8 @@ lmsgk = LAUNCH_KEY_SHUTDOWN; } else if (!strcmp(argv[0], "singleuser")) { lmsgk = LAUNCH_KEY_SINGLEUSER; + } else { + return 1; } msg = launch_data_new_string(lmsgk); Modified: trunk/launchd/src/launchd.c =================================================================== --- trunk/launchd/src/launchd.c 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/launchd.c 2007-01-28 21:15:53 UTC (rev 23025) @@ -469,10 +469,6 @@ rlcj = NULL; jobmgr_remove_all_inactive(root_jobmgr); - - if (getpid() == 1) { - catatonia(); - } } void Modified: trunk/launchd/src/launchd.h =================================================================== --- trunk/launchd/src/launchd.h 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/launchd.h 2007-01-28 21:15:53 UTC (rev 23025) @@ -55,9 +55,6 @@ void init_boot(bool sflag); void init_pre_kevent(void); -void update_ttys(void); -void catatonia(void); - void mach_start_shutdown(void); void mach_init_init(mach_port_t); Modified: trunk/launchd/src/launchd_unix_ipc.c =================================================================== --- trunk/launchd/src/launchd_unix_ipc.c 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/launchd_unix_ipc.c 2007-01-28 21:15:53 UTC (rev 23025) @@ -352,9 +352,6 @@ } else { resp = launch_data_new_errno(EACCES); } - } else if (!strcmp(cmd, LAUNCH_KEY_RELOADTTYS)) { - update_ttys(); - resp = launch_data_new_errno(0); } else if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) { launchd_shutdown(); resp = launch_data_new_errno(0); Modified: trunk/launchd/src/liblaunch_private.h =================================================================== --- trunk/launchd/src/liblaunch_private.h 2007-01-26 23:45:13 UTC (rev 23024) +++ trunk/launchd/src/liblaunch_private.h 2007-01-28 21:15:53 UTC (rev 23025) @@ -37,7 +37,6 @@ #define LAUNCH_KEY_SINGLEUSER "SingleUser" #define LAUNCH_KEY_GETRESOURCELIMITS "GetResourceLimits" #define LAUNCH_KEY_SETRESOURCELIMITS "SetResourceLimits" -#define LAUNCH_KEY_RELOADTTYS "ReloadTTYS" #define LAUNCH_KEY_SETLOGMASK "SetLogMask" #define LAUNCH_KEY_GETLOGMASK "GetLogMask" #define LAUNCH_KEY_SETUMASK "SetUmask"