diff -up util-linux-2.23.2/term-utils/agetty.c.kzak util-linux-2.23.2/term-utils/agetty.c --- util-linux-2.23.2/term-utils/agetty.c.kzak 2013-07-30 11:14:18.124912322 +0200 +++ util-linux-2.23.2/term-utils/agetty.c 2013-09-09 09:07:46.406689270 +0200 @@ -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,10 +242,13 @@ static void login_options_to_argv(char * static char *fakehost; #ifdef DEBUGGING -#define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) +# ifndef DEBUG_OUTPUT +# define DEBUG_OUTPUT "/dev/ttyp0" +# endif +# define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) FILE *dbf; #else -#define debug(s) do { ; } while (0) +# define debug(s) do { ; } while (0) #endif int main(int argc, char **argv) @@ -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]); @@ -534,7 +552,7 @@ static void parse_args(int argc, char ** { "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' }, @@ -603,7 +621,18 @@ static void parse_args(int argc, char ** 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; @@ -1090,8 +1119,19 @@ static void termio_init(struct options * 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[=]*/ + 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 @@ -1412,9 +1452,10 @@ static char *get_logname(struct options 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) { @@ -1648,7 +1689,7 @@ static void __attribute__ ((__noreturn__ fputs(_(" -i, --noissue do not display issue file\n"), out); fputs(_(" -I, --init-string set init string\n"), out); fputs(_(" -l, --login-program specify login program\n"), out); - fputs(_(" -L, --local-line force local line\n"), out); + fputs(_(" -L, --local-line[=] 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 options that are passed to login\n"), out);