Changeset View
Changeset View
Standalone View
Standalone View
sbin/init/init.c
Show First 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
#define GETTY_NSPACE 3 /* max. spacing count to bring reaction */ | #define GETTY_NSPACE 3 /* max. spacing count to bring reaction */ | ||||
#define WINDOW_WAIT 3 /* wait N secs after starting window */ | #define WINDOW_WAIT 3 /* wait N secs after starting window */ | ||||
#define STALL_TIMEOUT 30 /* wait N secs after warning */ | #define STALL_TIMEOUT 30 /* wait N secs after warning */ | ||||
#define DEATH_WATCH 10 /* wait N secs for procs to die */ | #define DEATH_WATCH 10 /* wait N secs for procs to die */ | ||||
#define DEATH_SCRIPT 120 /* wait for 2min for /etc/rc.shutdown */ | #define DEATH_SCRIPT 120 /* wait for 2min for /etc/rc.shutdown */ | ||||
#define RESOURCE_RC "daemon" | #define RESOURCE_RC "daemon" | ||||
#define RESOURCE_WINDOW "default" | #define RESOURCE_WINDOW "default" | ||||
#define RESOURCE_GETTY "default" | #define RESOURCE_GETTY "default" | ||||
#define SCRIPT_ARGV_SIZE 3 /* size of argv passed to execute_script, can be increased if needed */ | |||||
static void handle(sig_t, ...); | static void handle(sig_t, ...); | ||||
static void delset(sigset_t *, ...); | static void delset(sigset_t *, ...); | ||||
static void stall(const char *, ...) __printflike(1, 2); | static void stall(const char *, ...) __printflike(1, 2); | ||||
static void warning(const char *, ...) __printflike(1, 2); | static void warning(const char *, ...) __printflike(1, 2); | ||||
static void emergency(const char *, ...) __printflike(1, 2); | static void emergency(const char *, ...) __printflike(1, 2); | ||||
static void disaster(int); | static void disaster(int); | ||||
▲ Show 20 Lines • Show All 929 Lines • ▼ Show 20 Lines | runcom(void) | ||||
runcom_mode = AUTOBOOT; /* the default */ | runcom_mode = AUTOBOOT; /* the default */ | ||||
return (state_func_t) read_ttys; | return (state_func_t) read_ttys; | ||||
} | } | ||||
static void | static void | ||||
execute_script(char *argv[]) | execute_script(char *argv[]) | ||||
{ | { | ||||
struct sigaction sa; | struct sigaction sa; | ||||
char* sh_argv[3 + SCRIPT_ARGV_SIZE]; | |||||
const char *shell, *script; | const char *shell, *script; | ||||
int error; | int error, sh_argv_len, i; | ||||
bzero(&sa, sizeof(sa)); | bzero(&sa, sizeof(sa)); | ||||
sigemptyset(&sa.sa_mask); | sigemptyset(&sa.sa_mask); | ||||
sa.sa_handler = SIG_IGN; | sa.sa_handler = SIG_IGN; | ||||
sigaction(SIGTSTP, &sa, NULL); | sigaction(SIGTSTP, &sa, NULL); | ||||
sigaction(SIGHUP, &sa, NULL); | sigaction(SIGHUP, &sa, NULL); | ||||
open_console(); | open_console(); | ||||
sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); | sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); | ||||
#ifdef LOGIN_CAP | #ifdef LOGIN_CAP | ||||
setprocresources(RESOURCE_RC); | setprocresources(RESOURCE_RC); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Try to directly execute the script first. If it | * Try to directly execute the script first. If it | ||||
* fails, try the old method of passing the script path | * fails, try the old method of passing the script path | ||||
* to sh(1). Don't complain if it fails because of | * to sh(1). Don't complain if it fails because of | ||||
* the missing execute bit. | * the missing execute bit. | ||||
*/ | */ | ||||
script = argv[1]; | script = argv[0]; | ||||
error = access(script, X_OK); | error = access(script, X_OK); | ||||
if (error == 0) { | if (error == 0) { | ||||
execv(script, argv + 1); | execv(script, argv); | ||||
warning("can't directly exec %s: %m", script); | warning("can't directly exec %s: %m", script); | ||||
} else if (errno != EACCES) { | } else if (errno != EACCES) { | ||||
warning("can't access %s: %m", script); | warning("can't access %s: %m", script); | ||||
} | } | ||||
shell = get_shell(); | shell = get_shell(); | ||||
execv(shell, argv); | sh_argv[0] = __DECONST(char*, shell); | ||||
sh_argv_len = 1; | |||||
#ifdef SECURE | |||||
if (strcmp(shell, _PATH_BSHELL) == 0) { | |||||
sh_argv[1] = __DECONST(char*, "-o"); | |||||
sjg: brace should be on previous line | |||||
sh_argv[2] = __DECONST(char*, "verify"); | |||||
sh_argv_len = 3; | |||||
} | |||||
#endif | |||||
for (i = 0; i != SCRIPT_ARGV_SIZE; ++i) | |||||
sh_argv[i + sh_argv_len] = argv[i]; | |||||
Done Inline Actionscan't say I'm crazy about his bit. sjg: can't say I'm crazy about his bit.
| |||||
execv(shell, sh_argv); | |||||
stall("can't exec %s for %s: %m", shell, script); | stall("can't exec %s for %s: %m", shell, script); | ||||
} | } | ||||
/* | /* | ||||
* Execute binary, replacing init(8) as PID 1. | * Execute binary, replacing init(8) as PID 1. | ||||
*/ | */ | ||||
static void | static void | ||||
replace_init(char *path) | replace_init(char *path) | ||||
{ | { | ||||
char *argv[3]; | char *argv[SCRIPT_ARGV_SIZE]; | ||||
char sh[] = "sh"; | |||||
argv[0] = sh; | argv[0] = path; | ||||
argv[1] = path; | argv[1] = NULL; | ||||
argv[2] = NULL; | |||||
execute_script(argv); | execute_script(argv); | ||||
} | } | ||||
/* | /* | ||||
* Run a shell script. | * Run a shell script. | ||||
* Returns 0 on success, otherwise the next transition to enter: | * Returns 0 on success, otherwise the next transition to enter: | ||||
* - single_user if fork/execv/waitpid failed, or if the script | * - single_user if fork/execv/waitpid failed, or if the script | ||||
* terminated with a signal or exit code != 0. | * terminated with a signal or exit code != 0. | ||||
* - death_single if a SIGTERM was delivered to init(8). | * - death_single if a SIGTERM was delivered to init(8). | ||||
*/ | */ | ||||
static state_func_t | static state_func_t | ||||
run_script(const char *script) | run_script(const char *script) | ||||
{ | { | ||||
pid_t pid, wpid; | pid_t pid, wpid; | ||||
int status; | int status; | ||||
char *argv[4]; | char *argv[SCRIPT_ARGV_SIZE]; | ||||
const char *shell; | const char *shell; | ||||
shell = get_shell(); | shell = get_shell(); | ||||
if ((pid = fork()) == 0) { | if ((pid = fork()) == 0) { | ||||
char _sh[] = "sh"; | |||||
char _autoboot[] = "autoboot"; | char _autoboot[] = "autoboot"; | ||||
argv[0] = _sh; | argv[0] = __DECONST(char *, script); | ||||
argv[1] = __DECONST(char *, script); | argv[1] = runcom_mode == AUTOBOOT ? _autoboot : NULL; | ||||
argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0; | argv[2] = NULL; | ||||
argv[3] = NULL; | |||||
execute_script(argv); | execute_script(argv); | ||||
sleep(STALL_TIMEOUT); | sleep(STALL_TIMEOUT); | ||||
_exit(1); /* force single user mode */ | _exit(1); /* force single user mode */ | ||||
} | } | ||||
if (pid == -1) { | if (pid == -1) { | ||||
emergency("can't fork for %s on %s: %m", shell, script); | emergency("can't fork for %s on %s: %m", shell, script); | ||||
▲ Show 20 Lines • Show All 819 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
runshutdown(void) | runshutdown(void) | ||||
{ | { | ||||
pid_t pid, wpid; | pid_t pid, wpid; | ||||
int status; | int status; | ||||
int shutdowntimeout; | int shutdowntimeout; | ||||
size_t len; | size_t len; | ||||
char *argv[4]; | char *argv[SCRIPT_ARGV_SIZE]; | ||||
struct stat sb; | struct stat sb; | ||||
BOOTTRACE("init(8): start rc.shutdown"); | BOOTTRACE("init(8): start rc.shutdown"); | ||||
/* | /* | ||||
* rc.shutdown is optional, so to prevent any unnecessary | * rc.shutdown is optional, so to prevent any unnecessary | ||||
* complaints from the shell we simply don't run it if the | * complaints from the shell we simply don't run it if the | ||||
* file does not exist. If the stat() here fails for other | * file does not exist. If the stat() here fails for other | ||||
* reasons, we'll let the shell complain. | * reasons, we'll let the shell complain. | ||||
*/ | */ | ||||
if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT) | if (stat(_PATH_RUNDOWN, &sb) == -1 && errno == ENOENT) | ||||
return 0; | return 0; | ||||
if ((pid = fork()) == 0) { | if ((pid = fork()) == 0) { | ||||
char _sh[] = "sh"; | |||||
char _reboot[] = "reboot"; | char _reboot[] = "reboot"; | ||||
char _single[] = "single"; | char _single[] = "single"; | ||||
char _path_rundown[] = _PATH_RUNDOWN; | char _path_rundown[] = _PATH_RUNDOWN; | ||||
argv[0] = _sh; | argv[0] = _path_rundown; | ||||
argv[1] = _path_rundown; | argv[1] = Reboot ? _reboot : _single; | ||||
argv[2] = Reboot ? _reboot : _single; | argv[2] = NULL; | ||||
argv[3] = NULL; | |||||
execute_script(argv); | execute_script(argv); | ||||
_exit(1); /* force single user mode */ | _exit(1); /* force single user mode */ | ||||
} | } | ||||
if (pid == -1) { | if (pid == -1) { | ||||
emergency("can't fork for %s: %m", _PATH_RUNDOWN); | emergency("can't fork for %s: %m", _PATH_RUNDOWN); | ||||
while (waitpid(-1, (int *) 0, WNOHANG) > 0) | while (waitpid(-1, (int *) 0, WNOHANG) > 0) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 170 Lines • Show Last 20 Lines |
brace should be on previous line