Index: init.c =================================================================== --- init.c (revision 258756) +++ init.c (working copy) @@ -1102,22 +1102,84 @@ } /* + * Do something for all defined TTYs + */ +static void +do_allttys(void (*callback)(struct ttyent *, void *), void *cookie) +{ + struct ttyent *typ; + char *buf, *cons, *nextcons; + size_t len; + + /* Loop through /etc/ttys */ + while ((typ = getttyent()) != NULL) { + if (strcmp(typ->ty_name, "console") == 0) + continue; + + callback(typ, cookie); + } + + /* Mix in any active console devices not in /etc/ttys */ + buf = NULL; + if (sysctlbyname("kern.console", NULL, &len, NULL, 0) == -1) + goto done; + buf = malloc(len); + if (sysctlbyname("kern.console", buf, &len, NULL, 0) == -1) + goto done; + + if ((cons = strchr(buf, '/')) == NULL) + goto done; + *cons = '\0'; + nextcons = buf; + while ((cons = strsep(&nextcons, ",")) != NULL && strlen(cons) != 0) { + typ = getttynam(cons); + if (typ != NULL) /* Skip terminals with known configs */ + continue; + typ = getttynam("console"); + typ->ty_name = cons; + + callback(typ, cookie); + } + +done: + if (buf != NULL) + free(buf); + endttyent(); +} + +/* * Walk the list of ttys and create sessions for each active line. */ +struct read_ttys_args { + int session_index; + session_t *sp; +}; + +static void +read_ttys_callback(struct ttyent *typ, void *cookie) +{ + struct read_ttys_args *args = cookie; + session_t *snext; + + if ((snext = new_session(args->sp, ++args->session_index, typ)) != NULL) + args->sp = snext; +} + static state_func_t read_ttys(void) { - int session_index = 0; - session_t *sp, *snext; - struct ttyent *typ; + struct read_ttys_args args; + session_t *snext; + args.session_index = 0; + /* * Destroy any previous session state. * There shouldn't be any, but just in case... */ - for (sp = sessions; sp; sp = snext) { - snext = sp->se_next; - free_session(sp); + for (args.sp = sessions; args.sp; args.sp = snext) { + snext = args.sp->se_next; + free_session(args.sp); } sessions = 0; if (start_session_db()) @@ -1127,12 +1189,8 @@ * Allocate a session entry for each active port. * Note that sp starts at 0. */ - while ((typ = getttyent()) != NULL) - if ((snext = new_session(sp, ++session_index, typ)) != NULL) - sp = snext; + do_allttys(read_ttys_callback, &args); - endttyent(); - return (state_func_t) multi_user; } @@ -1375,85 +1433,93 @@ /* * This is an (n*2)+(n^2) algorithm. We hope it isn't run often... */ -static state_func_t -clean_ttys(void) +static void +clean_ttys_callback(struct ttyent *typ, void *cookie) { + int *session_index = cookie; session_t *sp, *sprev; - struct ttyent *typ; - int session_index = 0; int devlen; char *old_getty, *old_window, *old_type; - /* - * mark all sessions for death, (!SE_PRESENT) - * as we find or create new ones they'll be marked as keepers, - * we'll later nuke all the ones not found in /etc/ttys - */ - for (sp = sessions; sp != NULL; sp = sp->se_next) - sp->se_flags &= ~SE_PRESENT; - devlen = sizeof(_PATH_DEV) - 1; - while ((typ = getttyent()) != NULL) { - ++session_index; + ++(*session_index); - for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) - if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) - break; + for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) + if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) + break; - if (sp) { - /* we want this one to live */ - sp->se_flags |= SE_PRESENT; - if (sp->se_index != session_index) { - warning("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) { - sp->se_flags |= SE_SHUTDOWN; - kill(sp->se_process, SIGHUP); - 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) - ) { + if (sp) { + /* we want this one to live */ + sp->se_flags |= SE_PRESENT; + if (sp->se_index != *session_index) { + warning("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) { + sp->se_flags |= SE_SHUTDOWN; + kill(sp->se_process, SIGHUP); + return; + } + 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_window) - free(old_window); - if (old_type) - free(old_type); - continue; } - - new_session(sprev, session_index, typ); + if (old_getty) + free(old_getty); + if (old_window) + free(old_window); + if (old_type) + free(old_type); + return; } - endttyent(); + new_session(sprev, *session_index, typ); +} +static state_func_t +clean_ttys(void) +{ + session_t *sp; + int session_index = 0; + /* + * mark all sessions for death, (!SE_PRESENT) + * as we find or create new ones they'll be marked as keepers, + * we'll later nuke all the ones not found in /etc/ttys + */ + for (sp = sessions; sp != NULL; sp = sp->se_next) + sp->se_flags &= ~SE_PRESENT; + + /* + * Loop over all TTYs and sync state + */ + do_allttys(clean_ttys_callback, &session_index); + + + /* * sweep through and kill all deleted sessions * ones who's /etc/ttys line was deleted (SE_PRESENT unset) */