util-linux/util-linux-2.23-agetty-clocal.patch
Karel Zak bf69284dde 2.23.1-3: fix #972457 (agetty)
Signed-off-by: Karel Zak <kzak@redhat.com>
2013-06-13 11:40:47 +02:00

154 lines
5.6 KiB
Diff

diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index a23cf6d..054a1dd 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -132,13 +132,20 @@ struct options {
int delay; /* Sleep seconds before prompt */
int nice; /* Run login with this priority */
int numspeed; /* number of baud rates to try */
+ int clocal; /* CLOCAL_MODE_* */
speed_t speeds[MAX_SPEED]; /* baud rates to be tried */
};
+enum {
+ CLOCAL_MODE_AUTO = 0,
+ CLOCAL_MODE_ALWAYS,
+ CLOCAL_MODE_NEVER
+};
+
#define F_PARSE (1<<0) /* process modem status messages */
#define F_ISSUE (1<<1) /* display /etc/issue */
#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */
-#define F_LOCAL (1<<3) /* force local */
+
#define F_INITSTRING (1<<4) /* initstring is set */
#define F_WAITCRLF (1<<5) /* wait for CR or LF */
#define F_CUSTISSUE (1<<6) /* give alternative issue file */
@@ -235,6 +242,9 @@ static void login_options_to_argv(char *argv[], int *argc, char *str, char *user
static char *fakehost;
#ifdef DEBUGGING
+#ifndef
+# define DEBUG_OUTPUT "/dev/ttyp0"
+#endif
#define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0)
FILE *dbf;
#else
@@ -270,7 +280,7 @@ int main(int argc, char **argv)
sigaction(SIGINT, &sa, &sa_int);
#ifdef DEBUGGING
- dbf = fopen("/dev/ttyp0", "w");
+ dbf = fopen(DEBUG_OUTPUT, "w");
for (int i = 1; i < argc; i++)
debug(argv[i]);
#endif /* DEBUGGING */
@@ -311,8 +321,10 @@ int main(int argc, char **argv)
strlen(options.initstring));
}
- if (!serial_tty_option(&options, F_LOCAL))
- /* Go to blocking write mode unless -L is specified. */
+ if (options.flags & F_VCONSOLE || options.clocal != CLOCAL_MODE_ALWAYS)
+ /* Go to blocking mode unless -L is specified, this change
+ * affects stdout, stdin and stderr as all the file descriptors
+ * are created by dup(). */
fcntl(STDOUT_FILENO, F_SETFL,
fcntl(STDOUT_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
@@ -420,6 +432,12 @@ int main(int argc, char **argv)
options.tty);
}
+#ifdef DEBUGGING
+ fprintf(dbf, "read %c\n", ch);
+ if (close_stream(dbf) != 0)
+ log_err("write failed: %s", DEBUG_OUTPUT);
+#endif
+
/* Let the login program take care of password validation. */
execv(options.login, login_argv);
log_err(_("%s: can't exec %s: %m"), options.tty, login_argv[0]);
@@ -532,7 +550,7 @@ static void parse_args(int argc, char **argv, struct options *op)
{ "init-string", required_argument, 0, 'I' },
{ "noclear", no_argument, 0, 'J' },
{ "login-program", required_argument, 0, 'l' },
- { "local-line", no_argument, 0, 'L' },
+ { "local-line", optional_argument, 0, 'L' },
{ "extract-baud", no_argument, 0, 'm' },
{ "skip-login", no_argument, 0, 'n' },
{ "nonewline", no_argument, 0, 'N' },
@@ -601,7 +619,18 @@ static void parse_args(int argc, char **argv, struct options *op)
op->login = optarg;
break;
case 'L':
- op->flags |= F_LOCAL;
+ /* -L and -L=always have the same meaning */
+ op->clocal = CLOCAL_MODE_ALWAYS;
+ if (optarg) {
+ if (strcmp(optarg, "=always") == 0)
+ op->clocal = CLOCAL_MODE_ALWAYS;
+ else if (strcmp(optarg, "=never") == 0)
+ op->clocal = CLOCAL_MODE_NEVER;
+ else if (strcmp(optarg, "=auto") == 0)
+ op->clocal = CLOCAL_MODE_AUTO;
+ else
+ log_err(_("unssuported --local-line mode argument"));
+ }
break;
case 'm':
op->flags |= F_PARSE;
@@ -1088,8 +1117,19 @@ static void termio_init(struct options *op, struct termios *tp)
cfsetispeed(tp, ispeed);
cfsetospeed(tp, ospeed);
- if (op->flags & F_LOCAL)
- tp->c_cflag |= CLOCAL;
+ /* The default is to follow setting from kernel, but it's possible
+ * to explicitly remove/add CLOCAL flag by -L[=<mode>]*/
+ switch (op->clocal) {
+ case CLOCAL_MODE_ALWAYS:
+ tp->c_cflag |= CLOCAL; /* -L or -L=always */
+ break;
+ case CLOCAL_MODE_NEVER:
+ tp->c_cflag &= ~CLOCAL; /* -L=never */
+ break;
+ case CLOCAL_MODE_AUTO: /* -L=auto */
+ break;
+ }
+
#ifdef HAVE_STRUCT_TERMIOS_C_LINE
tp->c_line = 0;
#endif
@@ -1410,9 +1450,10 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
if (read(STDIN_FILENO, &c, 1) < 1) {
- /* Do not report trivial like EINTR/EIO errors. */
+ /* The terminal could be open with O_NONBLOCK when
+ * -L (force CLOCAL) is specified... */
if (errno == EINTR || errno == EAGAIN) {
- usleep(1000);
+ usleep(250000);
continue;
}
switch (errno) {
@@ -1633,7 +1674,7 @@ static speed_t bcode(char *s)
static void __attribute__ ((__noreturn__)) usage(FILE *out)
{
fputs(USAGE_HEADER, out);
- fprintf(out, _(" %1$s [options] line baud_rate,... [termtype]\n"
+ fprintf(out, _(" %1$s [options] line [baud_rate,...] [termtype]\n"
" %1$s [options] baud_rate,... line [termtype]\n"), program_invocation_short_name);
fputs(USAGE_OPTIONS, out);
fputs(_(" -8, --8bits assume 8-bit tty\n"), out);
@@ -1646,7 +1687,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
fputs(_(" -i, --noissue do not display issue file\n"), out);
fputs(_(" -I, --init-string <string> set init string\n"), out);
fputs(_(" -l, --login-program <file> specify login program\n"), out);
- fputs(_(" -L, --local-line force local line\n"), out);
+ fputs(_(" -L, --local-line[=<mode>] cotrol local line flag\n"), out);
fputs(_(" -m, --extract-baud extract baud rate during connect\n"), out);
fputs(_(" -n, --skip-login do not prompt for login\n"), out);
fputs(_(" -o, --login-options <opts> options that are passed to login\n"), out);