diff options
Diffstat (limited to 'sbin/init.bsdi/init.c')
| -rw-r--r-- | sbin/init.bsdi/init.c | 114 |
1 files changed, 100 insertions, 14 deletions
diff --git a/sbin/init.bsdi/init.c b/sbin/init.bsdi/init.c index 0ba1b5a6aa14..aae219171070 100644 --- a/sbin/init.bsdi/init.c +++ b/sbin/init.bsdi/init.c @@ -61,6 +61,7 @@ static char sccsid[] = "@(#)init.c 6.22 (Berkeley) 6/2/93"; #include <time.h> #include <ttyent.h> #include <unistd.h> +#include <sys/reboot.h> #ifdef __STDC__ #include <stdarg.h> @@ -86,6 +87,7 @@ extern void logwtmp __P((const char *, const char *, const char *)); */ #define GETTY_SPACING 5 /* N secs minimum getty spacing */ #define GETTY_SLEEP 30 /* sleep N secs after spacing problem */ +#define GETTY_NSPACE 3 /* max. spacing count to bring reaction */ #define WINDOW_WAIT 3 /* wait N secs after starting window */ #define STALL_TIMEOUT 30 /* wait N secs after warning */ #define DEATH_WATCH 10 /* wait N secs for procs to die */ @@ -116,6 +118,7 @@ state_func_t catatonia __P((void)); state_func_t death __P((void)); enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; +int noreboot = 0; void transition __P((state_t)); state_t requested_transition = runcom; @@ -128,11 +131,15 @@ typedef struct init_session { time_t se_started; /* used to avoid thrashing */ int se_flags; /* status of session */ #define SE_SHUTDOWN 0x1 /* session won't be restarted */ + int se_nspace; /* spacing count */ char *se_device; /* filename of port */ - char *se_getty; /* what to run on that port */ + char *se_getty; /* what to run on that port */ + char *se_getty_argv_space; /* pre-parsed argument array space */ char **se_getty_argv; /* pre-parsed argument array */ - char *se_window; /* window system (started only once) */ + char *se_window; /* window system (started only once) */ + char *se_window_argv_space; /* pre-parsed argument array space */ char **se_window_argv; /* pre-parsed argument array */ + char *se_type; /* default terminal type */ struct init_session *se_prev; struct init_session *se_next; } session_t; @@ -224,11 +231,11 @@ main(argc, argv) handle(badsys, SIGSYS, 0); handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGXCPU, SIGXFSZ, 0); - handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0); + handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP, 0); handle(alrm_handler, SIGALRM, 0); sigfillset(&mask); delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, - SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0); + SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGTSTP, SIGALRM, 0); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; @@ -520,7 +527,9 @@ setctty(name) int fd; (void) revoke(name); +#ifdef BROKEN_DTR sleep (2); /* leave DTR low */ +#endif if ((fd = open(name, O_RDWR)) == -1) { stall("can't open %s: %m", name); _exit(1); @@ -556,6 +565,15 @@ single_user() if (getsecuritylevel() > 0) setsecuritylevel(0); + if ( noreboot > 0) { + /* Instead of going single user, let's halt the machine */ + sync(); + alarm(2); + pause(); + reboot(RB_HALT); + _exit(0); + } + if ((pid = fork()) == 0) { /* * Start the single user session. @@ -867,12 +885,16 @@ free_session(sp) free(sp->se_device); if (sp->se_getty) { free(sp->se_getty); + free(sp->se_getty_argv_space); free(sp->se_getty_argv); } if (sp->se_window) { free(sp->se_window); + free(sp->se_window_argv_space); free(sp->se_window_argv); } + if (sp->se_type) + free(sp->se_type); free(sp); } @@ -928,30 +950,43 @@ setupargv(sp, typ) if (sp->se_getty) { free(sp->se_getty); + free(sp->se_getty_argv_space); free(sp->se_getty_argv); } sp->se_getty = malloc(strlen(typ->ty_getty) + strlen(typ->ty_name) + 2); (void) sprintf(sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name); - sp->se_getty_argv = construct_argv(sp->se_getty); + sp->se_getty_argv_space = strdup(sp->se_getty); + sp->se_getty_argv = construct_argv(sp->se_getty_argv_space); if (sp->se_getty_argv == 0) { warning("can't parse getty for port %s", sp->se_device); free(sp->se_getty); - sp->se_getty = 0; + free(sp->se_getty_argv_space); + sp->se_getty = sp->se_getty_argv_space = 0; return (0); } + if (sp->se_window) { + free(sp->se_window); + free(sp->se_window_argv_space); + free(sp->se_window_argv); + } + sp->se_window = sp->se_window_argv_space = 0; + sp->se_window_argv = 0; if (typ->ty_window) { - if (sp->se_window) - free(sp->se_window); sp->se_window = strdup(typ->ty_window); - sp->se_window_argv = construct_argv(sp->se_window); + sp->se_window_argv_space = strdup(sp->se_window); + sp->se_window_argv = construct_argv(sp->se_window_argv_space); if (sp->se_window_argv == 0) { warning("can't parse window for port %s", sp->se_device); + free(sp->se_window_argv_space); free(sp->se_window); - sp->se_window = 0; + sp->se_window = sp->se_window_argv_space = 0; return (0); } } + if (sp->se_type) + free(sp->se_type); + sp->se_type = typ->ty_type ? strdup(typ->ty_type) : 0; return (1); } @@ -1001,6 +1036,7 @@ start_window_system(sp) { pid_t pid; sigset_t mask; + char term[64], *env[2]; if ((pid = fork()) == -1) { emergency("can't fork for window system on port %s: %m", @@ -1018,7 +1054,16 @@ start_window_system(sp) if (setsid() < 0) emergency("setsid failed (window) %m"); - execv(sp->se_window_argv[0], sp->se_window_argv); + if (sp->se_type) { + /* Don't use malloc after fork */ + strcpy(term, "TERM="); + strcat(term, sp->se_type); + env[0] = term; + env[1] = 0; + } + else + env[0] = 0; + execve(sp->se_window_argv[0], sp->se_window_argv, env); stall("can't exec window system '%s' for port %s: %m", sp->se_window_argv[0], sp->se_device); _exit(1); @@ -1034,6 +1079,7 @@ start_getty(sp) pid_t pid; sigset_t mask; time_t current_time = time((time_t *) 0); + char term[64], *env[2]; /* * fork(), not vfork() -- we can't afford to block. @@ -1048,10 +1094,15 @@ start_getty(sp) if (current_time > sp->se_started && current_time - sp->se_started < GETTY_SPACING) { - warning("getty repeating too quickly on port %s, sleeping", - sp->se_device); + if (++sp->se_nspace > GETTY_NSPACE) { + sp->se_nspace = 0; + warning("getty repeating too quickly on port %s, sleeping %d secs", + sp->se_device, GETTY_SLEEP); sleep((unsigned) GETTY_SLEEP); } + } + else + sp->se_nspace = 0; if (sp->se_window) { start_window_system(sp); @@ -1061,7 +1112,16 @@ start_getty(sp) sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); - execv(sp->se_getty_argv[0], sp->se_getty_argv); + if (sp->se_type) { + /* Don't use malloc after fork */ + strcpy(term, "TERM="); + strcat(term, sp->se_type); + env[0] = term; + env[1] = 0; + } + else + env[0] = 0; + execve(sp->se_getty_argv[0], sp->se_getty_argv, env); stall("can't exec getty '%s' for port %s: %m", sp->se_getty_argv[0], sp->se_device); _exit(1); @@ -1125,6 +1185,8 @@ transition_handler(sig) case SIGHUP: requested_transition = clean_ttys; break; + case SIGINT: + noreboot++; case SIGTERM: requested_transition = death; break; @@ -1187,6 +1249,7 @@ clean_ttys() register struct ttyent *typ; register int session_index = 0; register int devlen; + char *old_getty, *old_window, *old_type; if (! sessions) return (state_func_t) multi_user; @@ -1213,12 +1276,35 @@ clean_ttys() continue; } sp->se_flags &= ~SE_SHUTDOWN; + old_getty = sp->se_getty ? strdup(sp->se_getty) : 0; + old_window = sp->se_window ? strdup(sp->se_window) : 0; + old_type = sp->se_type ? strdup(sp->se_type) : 0; if (setupargv(sp, typ) == 0) { warning("can't parse getty for port %s", sp->se_device); sp->se_flags |= SE_SHUTDOWN; kill(sp->se_process, SIGHUP); } + else if ( !old_getty + || !old_type && sp->se_type + || old_type && !sp->se_type + || !old_window && sp->se_window + || old_window && !sp->se_window + || strcmp(old_getty, sp->se_getty) != 0 + || old_window && strcmp(old_window, sp->se_window) != 0 + || old_type && strcmp(old_type, sp->se_type) != 0 + ) { + /* Don't set SE_SHUTDOWN here */ + sp->se_nspace = 0; + sp->se_started = 0; + kill(sp->se_process, SIGHUP); + } + if (old_getty) + free(old_getty); + if (old_getty) + free(old_window); + if (old_type) + free(old_type); continue; } |
