*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//config:config GETTY
+//config: bool "getty (10 kb)"
+//config: default y
+//config: select FEATURE_SYSLOG
+//config: help
+//config: getty lets you log in on a tty. It is normally invoked by init.
+//config:
+//config: Note that you can save a few bytes by disabling it and
+//config: using login applet directly.
+//config: If you need to reset tty attributes before calling login,
+//config: this script approximates getty:
+//config:
+//config: exec </dev/$1 >/dev/$1 2>&1 || exit 1
+//config: reset
+//config: stty sane; stty ispeed 38400; stty ospeed 38400
+//config: printf "%s login: " "`hostname`"
+//config: read -r login
+//config: exec /bin/login "$login"
+
+//applet:IF_GETTY(APPLET(getty, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_GETTY) += getty.o
#include "libbb.h"
#include <syslog.h>
//usage: "\n"
//usage: "\nBAUD_RATE of 0 leaves it unchanged"
-static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn";
+#define OPT_STR "I:LH:f:hil:mt:+wn"
#define F_INITSTRING (1 << 0) /* -I */
#define F_LOCAL (1 << 1) /* -L */
#define F_FAKEHOST (1 << 2) /* -H */
/* note: arg "0" turns into speed B0 */
G.numspeed++;
if (G.numspeed > MAX_SPEED)
- bb_error_msg_and_die("too many alternate speeds");
+ bb_simple_error_msg_and_die("too many alternate speeds");
}
debug("exiting parse_speeds\n");
}
char *ts;
int flags;
- opt_complementary = "-2:t+"; /* at least 2 args; -t N */
- flags = getopt32(argv, opt_string,
+ flags = getopt32(argv, "^" OPT_STR "\0" "-2"/* at least 2 args*/,
&G.initstring, &G.fakehost, &G.issue,
&G.login, &G.timeout
);
* Make sure it is open for read/write.
*/
if ((fcntl(0, F_GETFL) & (O_RDWR|O_RDONLY|O_WRONLY)) != O_RDWR)
- bb_error_msg_and_die("stdin is not open for read/write");
+ bb_simple_error_msg_and_die("stdin is not open for read/write");
/* Try to get real tty name instead of "-" */
n = xmalloc_ttyname(0);
static void set_tty_attrs(void)
{
if (tcsetattr_stdin_TCSANOW(&G.tty_attrs) < 0)
- bb_perror_msg_and_die("tcsetattr");
+ bb_simple_perror_msg_and_die("tcsetattr");
}
/* We manipulate tty_attrs this way:
/* non-raw output; add CR to each NL */
G.tty_attrs.c_oflag = OPOST | ONLCR;
- /* reads would block only if < 1 char is available */
+ /* reads will block only if < 1 char is available */
G.tty_attrs.c_cc[VMIN] = 1;
/* no timeout (reads block forever) */
G.tty_attrs.c_cc[VTIME] = 0;
* observed to improve backspacing through Unicode chars
*/
- /* line buffered input (NL or EOL or EOF chars end a line);
- * recognize INT/QUIT/SUSP chars;
- * echo input chars;
- * echo BS-SP-BS on erase character;
- * echo kill char specially, not as ^c (ECHOKE controls how exactly);
- * erase all input via BS-SP-BS on kill char (else go to next line)
+ /* ICANON line buffered input (NL or EOL or EOF chars end a line);
+ * ISIG recognize INT/QUIT/SUSP chars;
+ * ECHO echo input chars;
+ * ECHOE echo BS-SP-BS on erase character;
+ * ECHOK echo kill char specially, not as ^c (ECHOKE controls how exactly);
+ * ECHOKE erase all input via BS-SP-BS on kill char (else go to next line)
+ * ECHOCTL Echo ctrl chars as ^c (else echo verbatim:
+ * e.g. up arrow emits "ESC-something" and thus moves cursor up!)
*/
- G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
+ G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL;
/* Other bits in c_lflag:
* XCASE Map uppercase to \lowercase [tried, doesn't work]
* ECHONL Echo NL even if ECHO is not set
- * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this?
* ECHOPRT On erase, echo erased chars
* [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen]
* NOFLSH Don't flush input buffer after interrupt or quit chars
finalize_tty_attrs();
if (errno == EINTR || errno == EIO)
exit(EXIT_SUCCESS);
- bb_perror_msg_and_die(bb_msg_read_error);
+ bb_simple_perror_msg_and_die(bb_msg_read_error);
}
switch (c) {
_exit(EXIT_SUCCESS);
}
+static void sleep10(void)
+{
+ sleep(10);
+}
+
int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int getty_main(int argc UNUSED_PARAM, char **argv)
{
// " sid %d pgid %d",
// pid, getppid(),
// getsid(0), getpgid(0));
- bb_perror_msg_and_die("setsid");
+ bb_simple_perror_msg_and_die("setsid");
/*
* When we can end up here?
* Example: setsid() fails when run alone in interactive shell:
close(n--);
/* Logging. We want special flavor of error_msg_and_die */
- die_sleep = 10;
+ die_func = sleep10;
msg_eol = "\r\n";
/* most likely will internally use fd #3 in CLOEXEC mode: */
openlog(applet_name, LOG_PID, LOG_AUTH);
tsid = tcgetsid(STDIN_FILENO);
if (tsid < 0 || pid != tsid) {
if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) < 0)
- bb_perror_msg_and_die("TIOCSCTTY");
+ bb_simple_perror_msg_and_die("TIOCSCTTY");
}
#ifdef __linux__
/* Make ourself a foreground process group within our session */
if (tcsetpgrp(STDIN_FILENO, pid) < 0)
- bb_perror_msg_and_die("tcsetpgrp");
+ bb_simple_perror_msg_and_die("tcsetpgrp");
#endif
/*
* 5 seconds seems to be a good value.
*/
if (tcgetattr(STDIN_FILENO, &G.tty_attrs) < 0)
- bb_perror_msg_and_die("tcgetattr");
+ bb_simple_perror_msg_and_die("tcgetattr");
/* Update the utmp file. This tty is ours now! */
update_utmp(pid, LOGIN_PROCESS, G.tty_name, "LOGIN", G.fakehost);