Changeset View
Changeset View
Standalone View
Standalone View
sbin/init/init.c
Show First 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
state_t initial_transition = runcom; | state_t initial_transition = runcom; | ||||
char kenv_value[PATH_MAX]; | char kenv_value[PATH_MAX]; | ||||
int c, error; | int c, error; | ||||
struct sigaction sa; | struct sigaction sa; | ||||
sigset_t mask; | sigset_t mask; | ||||
/* Dispose of random users. */ | /* Dispose of random users. */ | ||||
if (getuid() != 0) | if (getuid() != 0) | ||||
errx(1, "%s", strerror(EPERM)); | err(1, NULL); | ||||
/* System V users like to reexec init. */ | /* System V users like to reexec init. */ | ||||
if (getpid() != 1) { | if (getpid() != 1) { | ||||
#ifdef COMPAT_SYSV_INIT | #ifdef COMPAT_SYSV_INIT | ||||
/* So give them what they want */ | /* So give them what they want */ | ||||
if (argc > 1) { | if (argc > 1) { | ||||
if (strlen(argv[1]) == 1) { | if (strlen(argv[1]) == 1) { | ||||
char runlevel = *argv[1]; | char runlevel = *argv[1]; | ||||
▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | |||||
#ifdef KERN_SECURELVL | #ifdef KERN_SECURELVL | ||||
int name[2], curlevel; | int name[2], curlevel; | ||||
size_t len; | size_t len; | ||||
name[0] = CTL_KERN; | name[0] = CTL_KERN; | ||||
name[1] = KERN_SECURELVL; | name[1] = KERN_SECURELVL; | ||||
len = sizeof curlevel; | len = sizeof curlevel; | ||||
if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { | if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { | ||||
emergency("cannot get kernel security level: %s", | emergency("cannot get kernel security level: %m"); | ||||
strerror(errno)); | |||||
return (-1); | return (-1); | ||||
} | } | ||||
return (curlevel); | return (curlevel); | ||||
#else | #else | ||||
return (-1); | return (-1); | ||||
#endif | #endif | ||||
} | } | ||||
/* | /* | ||||
* Set the security level of the kernel. | * Set the security level of the kernel. | ||||
*/ | */ | ||||
static void | static void | ||||
setsecuritylevel(int newlevel) | setsecuritylevel(int newlevel) | ||||
{ | { | ||||
#ifdef KERN_SECURELVL | #ifdef KERN_SECURELVL | ||||
int name[2], curlevel; | int name[2], curlevel; | ||||
curlevel = getsecuritylevel(); | curlevel = getsecuritylevel(); | ||||
if (newlevel == curlevel) | if (newlevel == curlevel) | ||||
return; | return; | ||||
name[0] = CTL_KERN; | name[0] = CTL_KERN; | ||||
name[1] = KERN_SECURELVL; | name[1] = KERN_SECURELVL; | ||||
if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { | if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { | ||||
emergency( | emergency( | ||||
"cannot change kernel security level from %d to %d: %s", | "cannot change kernel security level from %d to %d: %m", | ||||
curlevel, newlevel, strerror(errno)); | curlevel, newlevel); | ||||
return; | return; | ||||
} | } | ||||
#ifdef SECURE | #ifdef SECURE | ||||
warning("kernel security level changed from %d to %d", | warning("kernel security level changed from %d to %d", | ||||
curlevel, newlevel); | curlevel, newlevel); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | read_file(const char *path, void **bufp, size_t *bufsizep) | ||||
struct stat sb; | struct stat sb; | ||||
size_t bufsize; | size_t bufsize; | ||||
void *buf; | void *buf; | ||||
ssize_t nbytes; | ssize_t nbytes; | ||||
int error, fd; | int error, fd; | ||||
fd = open(path, O_RDONLY); | fd = open(path, O_RDONLY); | ||||
if (fd < 0) { | if (fd < 0) { | ||||
emergency("%s: %s", path, strerror(errno)); | emergency("%s: %m", path); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
error = fstat(fd, &sb); | error = fstat(fd, &sb); | ||||
if (error != 0) { | if (error != 0) { | ||||
emergency("fstat: %s", strerror(errno)); | emergency("fstat: %m"); | ||||
kib: It would be useful to print path in the error message. | |||||
close(fd); | close(fd); | ||||
return (error); | return (error); | ||||
} | } | ||||
bufsize = sb.st_size; | bufsize = sb.st_size; | ||||
buf = malloc(bufsize); | buf = malloc(bufsize); | ||||
if (buf == NULL) { | if (buf == NULL) { | ||||
emergency("malloc: %s", strerror(errno)); | emergency("malloc: %m"); | ||||
close(fd); | close(fd); | ||||
return (error); | return (error); | ||||
} | } | ||||
nbytes = read(fd, buf, bufsize); | nbytes = read(fd, buf, bufsize); | ||||
if (nbytes != (ssize_t)bufsize) { | if (nbytes != (ssize_t)bufsize) { | ||||
emergency("read: %s", strerror(errno)); | emergency("read: %m"); | ||||
close(fd); | close(fd); | ||||
free(buf); | free(buf); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = close(fd); | error = close(fd); | ||||
if (error != 0) { | if (error != 0) { | ||||
emergency("close: %s", strerror(errno)); | emergency("close: %m"); | ||||
kibUnsubmitted Not Done Inline ActionsAnd there too. But, in fact, I do not see much sense in checking close(2) error. kib: And there too. But, in fact, I do not see much sense in checking close(2) error. | |||||
free(buf); | free(buf); | ||||
return (error); | return (error); | ||||
} | } | ||||
*bufp = buf; | *bufp = buf; | ||||
*bufsizep = bufsize; | *bufsizep = bufsize; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
create_file(const char *path, const void *buf, size_t bufsize) | create_file(const char *path, const void *buf, size_t bufsize) | ||||
{ | { | ||||
ssize_t nbytes; | ssize_t nbytes; | ||||
int error, fd; | int error, fd; | ||||
fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0700); | fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0700); | ||||
if (fd < 0) { | if (fd < 0) { | ||||
emergency("%s: %s", path, strerror(errno)); | emergency("%s: %m", path); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
nbytes = write(fd, buf, bufsize); | nbytes = write(fd, buf, bufsize); | ||||
if (nbytes != (ssize_t)bufsize) { | if (nbytes != (ssize_t)bufsize) { | ||||
emergency("write: %s", strerror(errno)); | emergency("write: %m"); | ||||
close(fd); | close(fd); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
error = close(fd); | error = close(fd); | ||||
if (error != 0) { | if (error != 0) { | ||||
emergency("close: %s", strerror(errno)); | emergency("close: %m"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
mount_tmpfs(const char *fspath) | mount_tmpfs(const char *fspath) | ||||
Show All 10 Lines | mount_tmpfs(const char *fspath) | ||||
build_iovec(&iov, &iovlen, "fspath", | build_iovec(&iov, &iovlen, "fspath", | ||||
__DECONST(void *, fspath), (size_t)-1); | __DECONST(void *, fspath), (size_t)-1); | ||||
build_iovec(&iov, &iovlen, "errmsg", | build_iovec(&iov, &iovlen, "errmsg", | ||||
errmsg, sizeof(errmsg)); | errmsg, sizeof(errmsg)); | ||||
error = nmount(iov, iovlen, 0); | error = nmount(iov, iovlen, 0); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (*errmsg != '\0') { | if (*errmsg != '\0') { | ||||
emergency("cannot mount tmpfs on %s: %s: %s", | emergency("cannot mount tmpfs on %s: %s: %m", | ||||
fspath, errmsg, strerror(errno)); | fspath, errmsg); | ||||
} else { | } else { | ||||
emergency("cannot mount tmpfs on %s: %s", | emergency("cannot mount tmpfs on %s: %m", | ||||
fspath, strerror(errno)); | fspath); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static state_func_t | static state_func_t | ||||
reroot(void) | reroot(void) | ||||
Show All 10 Lines | reroot(void) | ||||
/* | /* | ||||
* Make sure nobody can interfere with our scheme. | * Make sure nobody can interfere with our scheme. | ||||
* Ignore ESRCH, which can apparently happen when | * Ignore ESRCH, which can apparently happen when | ||||
* there are no processes to kill. | * there are no processes to kill. | ||||
*/ | */ | ||||
error = kill(-1, SIGKILL); | error = kill(-1, SIGKILL); | ||||
if (error != 0 && errno != ESRCH) { | if (error != 0 && errno != ESRCH) { | ||||
emergency("kill(2) failed: %s", strerror(errno)); | emergency("kill(2) failed: %m"); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Copy the init binary into tmpfs, so that we can unmount | * Copy the init binary into tmpfs, so that we can unmount | ||||
* the old rootfs without committing suicide. | * the old rootfs without committing suicide. | ||||
*/ | */ | ||||
error = read_file(init_path_argv0, &buf, &bufsize); | error = read_file(init_path_argv0, &buf, &bufsize); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
error = mount_tmpfs(_PATH_REROOT); | error = mount_tmpfs(_PATH_REROOT); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
error = create_file(_PATH_REROOT_INIT, buf, bufsize); | error = create_file(_PATH_REROOT_INIT, buf, bufsize); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
/* | /* | ||||
* Execute the temporary init. | * Execute the temporary init. | ||||
*/ | */ | ||||
execl(_PATH_REROOT_INIT, _PATH_REROOT_INIT, "-r", NULL); | execl(_PATH_REROOT_INIT, _PATH_REROOT_INIT, "-r", NULL); | ||||
emergency("cannot exec %s: %s", _PATH_REROOT_INIT, strerror(errno)); | emergency("cannot exec %s: %m", _PATH_REROOT_INIT); | ||||
out: | out: | ||||
emergency("reroot failed; going to single user mode"); | emergency("reroot failed; going to single user mode"); | ||||
free(buf); | free(buf); | ||||
return (state_func_t) single_user; | return (state_func_t) single_user; | ||||
} | } | ||||
static state_func_t | static state_func_t | ||||
reroot_phase_two(void) | reroot_phase_two(void) | ||||
{ | { | ||||
char init_path[PATH_MAX], *path, *path_component; | char init_path[PATH_MAX], *path, *path_component; | ||||
size_t init_path_len; | size_t init_path_len; | ||||
int nbytes, error; | int nbytes, error; | ||||
/* | /* | ||||
* Ask the kernel to mount the new rootfs. | * Ask the kernel to mount the new rootfs. | ||||
*/ | */ | ||||
error = reboot(RB_REROOT); | error = reboot(RB_REROOT); | ||||
if (error != 0) { | if (error != 0) { | ||||
emergency("RB_REBOOT failed: %s", strerror(errno)); | emergency("RB_REBOOT failed: %m"); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Figure out where the destination init(8) binary is. Note that | * Figure out where the destination init(8) binary is. Note that | ||||
* the path could be different than what we've started with. Use | * the path could be different than what we've started with. Use | ||||
* the value from kenv, if set, or the one from sysctl otherwise. | * the value from kenv, if set, or the one from sysctl otherwise. | ||||
* The latter defaults to a hardcoded value, but can be overridden | * The latter defaults to a hardcoded value, but can be overridden | ||||
* by a build time option. | * by a build time option. | ||||
*/ | */ | ||||
nbytes = kenv(KENV_GET, "init_path", init_path, sizeof(init_path)); | nbytes = kenv(KENV_GET, "init_path", init_path, sizeof(init_path)); | ||||
if (nbytes <= 0) { | if (nbytes <= 0) { | ||||
init_path_len = sizeof(init_path); | init_path_len = sizeof(init_path); | ||||
error = sysctlbyname("kern.init_path", | error = sysctlbyname("kern.init_path", | ||||
init_path, &init_path_len, NULL, 0); | init_path, &init_path_len, NULL, 0); | ||||
if (error != 0) { | if (error != 0) { | ||||
emergency("failed to retrieve kern.init_path: %s", | emergency("failed to retrieve kern.init_path: %m"); | ||||
strerror(errno)); | |||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Repeat the init search logic from sys/kern/init_path.c | * Repeat the init search logic from sys/kern/init_path.c | ||||
*/ | */ | ||||
path_component = init_path; | path_component = init_path; | ||||
while ((path = strsep(&path_component, ":")) != NULL) { | while ((path = strsep(&path_component, ":")) != NULL) { | ||||
/* | /* | ||||
* Execute init(8) from the new rootfs. | * Execute init(8) from the new rootfs. | ||||
*/ | */ | ||||
execl(path, path, NULL); | execl(path, path, NULL); | ||||
} | } | ||||
emergency("cannot exec init from %s: %s", init_path, strerror(errno)); | emergency("cannot exec init from %s: %m", init_path); | ||||
out: | out: | ||||
emergency("reroot failed; going to single user mode"); | emergency("reroot failed; going to single user mode"); | ||||
return (state_func_t) single_user; | return (state_func_t) single_user; | ||||
} | } | ||||
/* | /* | ||||
* Bring the system up single user. | * Bring the system up single user. | ||||
Show All 17 Lines | |||||
#ifdef DEBUGSHELL | #ifdef DEBUGSHELL | ||||
char altshell[128]; | char altshell[128]; | ||||
#endif | #endif | ||||
if (Reboot) { | if (Reboot) { | ||||
/* Instead of going single user, let's reboot the machine */ | /* Instead of going single user, let's reboot the machine */ | ||||
sync(); | sync(); | ||||
if (reboot(howto) == -1) { | if (reboot(howto) == -1) { | ||||
emergency("reboot(%#x) failed, %s", howto, | emergency("reboot(%#x) failed, %m", howto); | ||||
strerror(errno)); | |||||
_exit(1); /* panic and reboot */ | _exit(1); /* panic and reboot */ | ||||
} | } | ||||
warning("reboot(%#x) returned", howto); | warning("reboot(%#x) returned", howto); | ||||
_exit(0); /* panic as well */ | _exit(0); /* panic as well */ | ||||
} | } | ||||
shell = get_shell(); | shell = get_shell(); | ||||
▲ Show 20 Lines • Show All 247 Lines • ▼ Show 20 Lines | |||||
* Open the session database. | * Open the session database. | ||||
* | * | ||||
* NB: We could pass in the size here; is it necessary? | * NB: We could pass in the size here; is it necessary? | ||||
*/ | */ | ||||
static int | static int | ||||
start_session_db(void) | start_session_db(void) | ||||
{ | { | ||||
if (session_db && (*session_db->close)(session_db)) | if (session_db && (*session_db->close)(session_db)) | ||||
emergency("session database close: %s", strerror(errno)); | emergency("session database close: %m"); | ||||
if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == NULL) { | if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == NULL) { | ||||
emergency("session database open: %s", strerror(errno)); | emergency("session database open: %m"); | ||||
return (1); | return (1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Add a new login session. | * Add a new login session. | ||||
*/ | */ | ||||
static void | static void | ||||
add_session(session_t *sp) | add_session(session_t *sp) | ||||
{ | { | ||||
DBT key; | DBT key; | ||||
DBT data; | DBT data; | ||||
key.data = &sp->se_process; | key.data = &sp->se_process; | ||||
key.size = sizeof sp->se_process; | key.size = sizeof sp->se_process; | ||||
data.data = &sp; | data.data = &sp; | ||||
data.size = sizeof sp; | data.size = sizeof sp; | ||||
if ((*session_db->put)(session_db, &key, &data, 0)) | if ((*session_db->put)(session_db, &key, &data, 0)) | ||||
emergency("insert %d: %s", sp->se_process, strerror(errno)); | emergency("insert %d: %m", sp->se_process); | ||||
} | } | ||||
/* | /* | ||||
* Delete an old login session. | * Delete an old login session. | ||||
*/ | */ | ||||
static void | static void | ||||
del_session(session_t *sp) | del_session(session_t *sp) | ||||
{ | { | ||||
DBT key; | DBT key; | ||||
key.data = &sp->se_process; | key.data = &sp->se_process; | ||||
key.size = sizeof sp->se_process; | key.size = sizeof sp->se_process; | ||||
if ((*session_db->del)(session_db, &key, 0)) | if ((*session_db->del)(session_db, &key, 0)) | ||||
emergency("delete %d: %s", sp->se_process, strerror(errno)); | emergency("delete %d: %m", sp->se_process); | ||||
} | } | ||||
/* | /* | ||||
* Look up a login session by pid. | * Look up a login session by pid. | ||||
*/ | */ | ||||
static session_t * | static session_t * | ||||
find_session(pid_t pid) | find_session(pid_t pid) | ||||
{ | { | ||||
Show All 29 Lines | |||||
} | } | ||||
/* | /* | ||||
* Deallocate a session descriptor. | * Deallocate a session descriptor. | ||||
*/ | */ | ||||
static void | static void | ||||
free_session(session_t *sp) | free_session(session_t *sp) | ||||
{ | { | ||||
free(sp->se_device); | free(sp->se_device); | ||||
if (sp->se_getty) { | sp->se_device = NULL; | ||||
if (sp->se_getty != NULL) { | |||||
free(sp->se_getty); | free(sp->se_getty); | ||||
free(sp->se_getty_argv_space); | free(sp->se_getty_argv_space); | ||||
free(sp->se_getty_argv); | free(sp->se_getty_argv); | ||||
sp->se_getty = NULL; | |||||
sp->se_getty_argv_space = NULL; | |||||
sp->se_getty_argv = NULL; | |||||
} | } | ||||
if (sp->se_window) { | if (sp->se_window != NULL) { | ||||
free(sp->se_window); | free(sp->se_window); | ||||
free(sp->se_window_argv_space); | free(sp->se_window_argv_space); | ||||
free(sp->se_window_argv); | free(sp->se_window_argv); | ||||
sp->se_window = NULL; | |||||
sp->se_window_argv_space = NULL; | |||||
sp->se_window_argv = NULL; | |||||
} | } | ||||
if (sp->se_type) | if (sp->se_type != NULL) { | ||||
free(sp->se_type); | free(sp->se_type); | ||||
sp->se_type = NULL; | |||||
} | |||||
free(sp); | free(sp); | ||||
kibUnsubmitted Not Done Inline ActionsThe added NULL assignments above the free() line are pointless, the memory is freed. kib: The added NULL assignments above the free() line are pointless, the memory is freed. | |||||
} | } | ||||
/* | /* | ||||
* Allocate a new session descriptor. | * Allocate a new session descriptor. | ||||
* Mark it SE_PRESENT. | * Mark it SE_PRESENT. | ||||
*/ | */ | ||||
static session_t * | static session_t * | ||||
new_session(session_t *sprev, struct ttyent *typ) | new_session(session_t *sprev, struct ttyent *typ) | ||||
{ | { | ||||
session_t *sp; | session_t *sp; | ||||
int fd; | int fd; | ||||
if ((typ->ty_status & TTY_ON) == 0 || | if ((typ->ty_status & TTY_ON) == 0 || | ||||
typ->ty_name == 0 || | typ->ty_name == NULL || | ||||
typ->ty_getty == 0) | typ->ty_getty == NULL) | ||||
return 0; | return (NULL); | ||||
sp = (session_t *) calloc(1, sizeof (session_t)); | sp = (session_t *) calloc(1, sizeof (session_t)); | ||||
if (sp == NULL) { | |||||
emergency("calloc: %m"); | |||||
return (NULL); | |||||
} | |||||
sp->se_flags |= SE_PRESENT; | sp->se_flags |= SE_PRESENT; | ||||
if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) < 0) | if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) < 0) { | ||||
err(1, "asprintf"); | emergency("asprintf: %m"); | ||||
kibUnsubmitted Not Done Inline ActionsIt would be useful to printf line which asprintf() was unable to handle. kib: It would be useful to printf line which asprintf() was unable to handle. | |||||
free(sp); | |||||
return (NULL); | |||||
} | |||||
/* | /* | ||||
* Attempt to open the device, if we get "device not configured" | * Attempt to open the device, if we get "device not configured" | ||||
* then don't add the device to the session list. | * then don't add the device to the session list. | ||||
*/ | */ | ||||
if ((fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0)) < 0) { | if ((fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0)) < 0) { | ||||
if (errno == ENXIO) { | if (errno == ENXIO) { | ||||
free_session(sp); | free_session(sp); | ||||
return (0); | return (NULL); | ||||
} | } | ||||
} else | } else | ||||
close(fd); | close(fd); | ||||
if (setupargv(sp, typ) == 0) { | if (setupargv(sp, typ) == 0) { | ||||
free_session(sp); | free_session(sp); | ||||
return (0); | return (NULL); | ||||
} | } | ||||
sp->se_next = 0; | sp->se_next = NULL; | ||||
if (sprev == NULL) { | if (sprev == NULL) { | ||||
sessions = sp; | sessions = sp; | ||||
sp->se_prev = 0; | sp->se_prev = NULL; | ||||
} else { | } else { | ||||
sprev->se_next = sp; | sprev->se_next = sp; | ||||
sp->se_prev = sprev; | sp->se_prev = sprev; | ||||
} | } | ||||
return sp; | return (sp); | ||||
} | } | ||||
/* | /* | ||||
* Calculate getty and if useful window argv vectors. | * Calculate getty and if useful window argv vectors. | ||||
*/ | */ | ||||
static int | static int | ||||
setupargv(session_t *sp, struct ttyent *typ) | setupargv(session_t *sp, struct ttyent *typ) | ||||
{ | { | ||||
if (sp->se_getty) { | if (sp->se_getty != NULL) { | ||||
free(sp->se_getty); | free(sp->se_getty); | ||||
free(sp->se_getty_argv_space); | free(sp->se_getty_argv_space); | ||||
free(sp->se_getty_argv); | free(sp->se_getty_argv); | ||||
sp->se_getty = NULL; | |||||
sp->se_getty_argv_space = NULL; | |||||
sp->se_getty_argv = NULL; | |||||
} | } | ||||
if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) < 0) | if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) < 0) { | ||||
err(1, "asprintf"); | emergency("asprintf: %m"); | ||||
return (0); | |||||
} | |||||
sp->se_getty_argv_space = strdup(sp->se_getty); | sp->se_getty_argv_space = strdup(sp->se_getty); | ||||
if (sp->se_getty_argv_space == NULL) { | |||||
emergency("strdup: %m"); | |||||
free(sp->se_getty); | |||||
sp->se_getty = NULL; | |||||
return (0); | |||||
} | |||||
sp->se_getty_argv = construct_argv(sp->se_getty_argv_space); | sp->se_getty_argv = construct_argv(sp->se_getty_argv_space); | ||||
if (sp->se_getty_argv == NULL) { | if (sp->se_getty_argv == NULL) { | ||||
warning("can't parse getty for port %s", sp->se_device); | warning("can't parse getty for port %s", sp->se_device); | ||||
free(sp->se_getty); | free(sp->se_getty); | ||||
free(sp->se_getty_argv_space); | free(sp->se_getty_argv_space); | ||||
sp->se_getty = sp->se_getty_argv_space = 0; | sp->se_getty = NULL; | ||||
sp->se_getty_argv_space = NULL; | |||||
return (0); | return (0); | ||||
} | } | ||||
if (sp->se_window) { | if (sp->se_window != NULL) { | ||||
free(sp->se_window); | free(sp->se_window); | ||||
free(sp->se_window_argv_space); | free(sp->se_window_argv_space); | ||||
free(sp->se_window_argv); | free(sp->se_window_argv); | ||||
sp->se_window = NULL; | |||||
sp->se_window_argv_space = NULL; | |||||
sp->se_window_argv = NULL; | |||||
} | } | ||||
sp->se_window = sp->se_window_argv_space = 0; | |||||
sp->se_window_argv = 0; | |||||
if (typ->ty_window) { | if (typ->ty_window) { | ||||
sp->se_window = strdup(typ->ty_window); | sp->se_window = strdup(typ->ty_window); | ||||
if (sp->se_window == NULL) { | |||||
emergency("strdup: %m"); | |||||
return (0); | |||||
} | |||||
sp->se_window_argv_space = strdup(sp->se_window); | sp->se_window_argv_space = strdup(sp->se_window); | ||||
if (sp->se_window_argv_space == NULL) { | |||||
emergency("strdup: %m"); | |||||
free(sp->se_window); | |||||
sp->se_window = NULL; | |||||
return (0); | |||||
} | |||||
sp->se_window_argv = construct_argv(sp->se_window_argv_space); | sp->se_window_argv = construct_argv(sp->se_window_argv_space); | ||||
if (sp->se_window_argv == NULL) { | if (sp->se_window_argv == NULL) { | ||||
warning("can't parse window for port %s", | warning("can't parse window for port %s", | ||||
sp->se_device); | sp->se_device); | ||||
free(sp->se_window_argv_space); | free(sp->se_window_argv_space); | ||||
free(sp->se_window); | free(sp->se_window); | ||||
sp->se_window = sp->se_window_argv_space = 0; | sp->se_window = NULL; | ||||
sp->se_window_argv_space = NULL; | |||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
if (sp->se_type) | if (sp->se_type) | ||||
free(sp->se_type); | free(sp->se_type); | ||||
sp->se_type = typ->ty_type ? strdup(typ->ty_type) : 0; | sp->se_type = typ->ty_type ? strdup(typ->ty_type) : NULL; | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* Walk the list of ttys and create sessions for each active line. | * Walk the list of ttys and create sessions for each active line. | ||||
*/ | */ | ||||
static state_func_t | static state_func_t | ||||
read_ttys(void) | read_ttys(void) | ||||
{ | { | ||||
session_t *sp, *snext; | session_t *sp, *snext; | ||||
struct ttyent *typ; | struct ttyent *typ; | ||||
/* | /* | ||||
* Destroy any previous session state. | * Destroy any previous session state. | ||||
* There shouldn't be any, but just in case... | * There shouldn't be any, but just in case... | ||||
*/ | */ | ||||
for (sp = sessions; sp; sp = snext) { | for (sp = sessions; sp != NULL; sp = snext) { | ||||
snext = sp->se_next; | snext = sp->se_next; | ||||
free_session(sp); | free_session(sp); | ||||
} | } | ||||
sessions = 0; | sessions = 0; | ||||
if (start_session_db()) | if (start_session_db()) | ||||
return (state_func_t) single_user; | return (state_func_t) single_user; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | clean_ttys(void) | ||||
* as we find or create new ones they'll be marked as keepers, | * 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 | * we'll later nuke all the ones not found in /etc/ttys | ||||
*/ | */ | ||||
for (sp = sessions; sp != NULL; sp = sp->se_next) | for (sp = sessions; sp != NULL; sp = sp->se_next) | ||||
sp->se_flags &= ~SE_PRESENT; | sp->se_flags &= ~SE_PRESENT; | ||||
devlen = sizeof(_PATH_DEV) - 1; | devlen = sizeof(_PATH_DEV) - 1; | ||||
while ((typ = getttyent()) != NULL) { | while ((typ = getttyent()) != NULL) { | ||||
for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next) | for (sprev = NULL, sp = sessions; sp != NULL; | ||||
sprev = sp, sp = sp->se_next) | |||||
if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) | if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) | ||||
break; | break; | ||||
if (sp) { | if (sp) { | ||||
/* we want this one to live */ | /* we want this one to live */ | ||||
sp->se_flags |= SE_PRESENT; | sp->se_flags |= SE_PRESENT; | ||||
if ((typ->ty_status & TTY_ON) == 0 || | if ((typ->ty_status & TTY_ON) == 0 || | ||||
typ->ty_getty == 0) { | typ->ty_getty == 0) { | ||||
sp->se_flags |= SE_SHUTDOWN; | sp->se_flags |= SE_SHUTDOWN; | ||||
kill(sp->se_process, SIGHUP); | kill(sp->se_process, SIGHUP); | ||||
continue; | continue; | ||||
} | } | ||||
sp->se_flags &= ~SE_SHUTDOWN; | sp->se_flags &= ~SE_SHUTDOWN; | ||||
old_getty = sp->se_getty ? strdup(sp->se_getty) : 0; | old_getty = sp->se_getty ? strdup(sp->se_getty) : NULL; | ||||
kibUnsubmitted Not Done Inline Actionssp->se_getty != NULL ? strdup() : ... Are you leaving strdup() result unchecked ? kib: ```sp->se_getty != NULL ? strdup() : ...```
Are you leaving strdup() result unchecked ? | |||||
old_window = sp->se_window ? strdup(sp->se_window) : 0; | old_window = sp->se_window ? strdup(sp->se_window) : NULL; | ||||
old_type = sp->se_type ? strdup(sp->se_type) : 0; | old_type = sp->se_type ? strdup(sp->se_type) : NULL; | ||||
if (setupargv(sp, typ) == 0) { | if (setupargv(sp, typ) == 0) { | ||||
warning("can't parse getty for port %s", | warning("can't parse getty for port %s", | ||||
sp->se_device); | sp->se_device); | ||||
sp->se_flags |= SE_SHUTDOWN; | sp->se_flags |= SE_SHUTDOWN; | ||||
kill(sp->se_process, SIGHUP); | kill(sp->se_process, SIGHUP); | ||||
} | free_session(sp); | ||||
else if ( !old_getty | } else if ( !old_getty | ||||
kibUnsubmitted Not Done Inline ActionsWrite this as == NULL for all tests ? kib: Write this as ` == NULL` for all tests ? | |||||
|| (!old_type && sp->se_type) | || (!old_type && sp->se_type) | ||||
|| (old_type && !sp->se_type) | || (old_type && !sp->se_type) | ||||
|| (!old_window && sp->se_window) | || (!old_window && sp->se_window) | ||||
|| (old_window && !sp->se_window) | || (old_window && !sp->se_window) | ||||
|| (strcmp(old_getty, sp->se_getty) != 0) | || (strcmp(old_getty, sp->se_getty) != 0) | ||||
|| (old_window && strcmp(old_window, sp->se_window) != 0) | || (old_window && strcmp(old_window, sp->se_window) != 0) | ||||
|| (old_type && strcmp(old_type, sp->se_type) != 0) | || (old_type && strcmp(old_type, sp->se_type) != 0) | ||||
) { | ) { | ||||
▲ Show 20 Lines • Show All 322 Lines • Show Last 20 Lines |
It would be useful to print path in the error message.