lineedit: print prompt and editing operations to stderr
[busybox-git.git] / loginutils / sulogin.c
blob9c927ed79b8872368ebbf7e8712840b579bfdbc6
1 /* vi: set sw=4 ts=4: */
2 /*
3 * Mini sulogin implementation for busybox
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */
7 //config:config SULOGIN
8 //config: bool "sulogin (18 kb)"
9 //config: default y
10 //config: select FEATURE_SYSLOG
11 //config: help
12 //config: sulogin is invoked when the system goes into single user
13 //config: mode (this is done through an entry in inittab).
15 //applet:IF_SULOGIN(APPLET_NOEXEC(sulogin, sulogin, BB_DIR_SBIN, BB_SUID_DROP, sulogin))
17 //kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
19 //usage:#define sulogin_trivial_usage
20 //usage: "[-t N] [TTY]"
21 //usage:#define sulogin_full_usage "\n\n"
22 //usage: "Single user login\n"
23 //usage: "\n -p Start a login shell"
24 //usage: "\n -t SEC Timeout"
26 #include "libbb.h"
27 #include <syslog.h>
29 int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
30 int sulogin_main(int argc UNUSED_PARAM, char **argv)
32 int tsid;
33 int timeout = 0;
34 unsigned opts;
35 struct passwd *pwd;
36 const char *shell;
38 /* Note: sulogin is not a suid app. It is meant to be run by init
39 * for single user / emergency mode. init starts it as root.
40 * Normal users (potentially malicious ones) can only run it under
41 * their UID, therefore no paranoia here is warranted:
42 * $LD_LIBRARY_PATH in env, TTY = /dev/sda
43 * are no more dangerous here than in e.g. cp applet.
46 logmode = LOGMODE_BOTH;
47 openlog(applet_name, 0, LOG_AUTH);
49 opts = getopt32(argv, "pt:+", &timeout);
50 argv += optind;
52 if (argv[0]) {
53 close(0);
54 close(1);
55 dup(xopen(argv[0], O_RDWR));
56 close(2);
57 dup(0);
60 pwd = getpwuid(0);
61 if (!pwd) {
62 bb_simple_error_msg_and_die("no password entry for root");
65 while (1) {
66 int r;
68 r = ask_and_check_password_extended(pwd, timeout,
69 "Give root password for maintenance\n"
70 "(or type Ctrl-D to continue): "
72 if (r < 0) {
73 /* ^D, ^C, timeout, or read error */
74 /* util-linux 2.36.1 compat: no message */
75 /*bb_simple_info_msg("normal startup");*/
76 return 0;
78 if (r > 0) {
79 break;
81 pause_after_failed_login();
82 bb_simple_info_msg("Login incorrect");
85 /* util-linux 2.36.1 compat: no message */
86 /*bb_simple_info_msg("starting shell for system maintenance");*/
88 IF_SELINUX(renew_current_security_context());
90 shell = getenv("SUSHELL");
91 if (!shell)
92 shell = getenv("sushell");
93 if (!shell)
94 shell = pwd->pw_shell;
96 /* util-linux 2.36.1 compat: cd to root's HOME, set a few envvars */
97 setup_environment(shell, 0
98 + SETUP_ENV_CHANGEENV_LOGNAME
99 + SETUP_ENV_CHDIR
100 , pwd);
101 // no SETUP_ENV_CLEARENV
102 // SETUP_ENV_CHANGEENV_LOGNAME - set HOME, SHELL, USER,and LOGNAME
103 // SETUP_ENV_CHDIR - cd to $HOME
105 /* util-linux 2.36.1 compat: steal ctty if we don't have it yet
106 * (yes, util-linux uses force=1) */
107 tsid = tcgetsid(STDIN_FILENO);
108 if (tsid < 0 || getpid() != tsid) {
109 if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) {
110 // bb_perror_msg("TIOCSCTTY1 tsid:%d", tsid);
111 if (setsid() > 0) {
112 // bb_error_msg("done setsid()");
113 /* If it still does not work, ignore */
114 if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) {
115 // bb_perror_msg("TIOCSCTTY2 tsid:%d", tsid);
122 * Note: login does this (should we do it too?):
124 /*signal(SIGINT, SIG_DFL);*/
126 /* Exec shell with no additional parameters. Never returns. */
127 exec_shell(shell, /* -p? then shell is login:*/(opts & 1), NULL);