[PATCH 2/8] Next cleanup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Next cleanup, that is split off special character parsing in do_prompt()
and parse_args(), handle name of line of virtual console and use it in
utmp update as well as the session id.  Also move the initial TERM
variable to open_tty() as we use this later in open_tty().

Signed-off-by: Werner Fink <werner@xxxxxxx>
---
 term-utils/agetty.c |  458 ++++++++++++++++++++++++++++-----------------------
 1 files changed, 255 insertions(+), 203 deletions(-)

diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 15998df..35ef1c2 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -27,6 +27,7 @@
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <langinfo.h>
 
 #include "strutils.h"
 #include "nls.h"
@@ -37,6 +38,19 @@
 #ifdef __linux__
 #  include <sys/param.h>
 #  define USE_SYSLOG
+#  ifndef DEFAULT_VCTERM
+#    define DEFAULT_VCTERM "linux"
+#  endif
+#  ifndef DEFAULT_STERM
+#    define DEFAULT_STERM  "vt102"
+#  endif
+#else
+#  ifndef DEFAULT_VCTERM
+#    define DEFAULT_VCTERM "vt100"
+#  endif
+#  ifndef DEFAULT_STERM
+#    define DEFAULT_STERM  "vt100"
+#  endif
 #endif
 
 /* If USE_SYSLOG is undefined all diagnostics go to /dev/console. */
@@ -112,6 +126,8 @@ struct options {
 	int timeout;			/* time-out period */
 	char *login;			/* login program */
 	char *tty;			/* name of tty */
+	char *vcline;			/* line of virtual console */
+	char *term;			/* terminal type */
 	char *initstring;		/* modem init string */
 	char *issue;			/* alternative issue file */
 	int numspeed;			/* number of baud rates to try */
@@ -194,12 +210,14 @@ static struct Speedtab speedtab[] = {
 
 #undef warn
 #undef error
+static void init_special_char(char* arg, struct options *op);
 static void parse_args(int argc, char **argv, struct options *op);
 static void parse_speeds(struct options *op, char *arg);
-static void update_utmp(char *line);
-static void open_tty(char *tty, struct termios *tp, int local);
+static void update_utmp(struct options *op);
+static void open_tty(char *tty, struct termios *tp, struct options *op);
 static void termio_init(struct options *op, struct termios *tp);
 static void auto_baud(struct termios *tp);
+static void output_special_char (unsigned char c, struct options *op, struct termios *tp);
 static void do_prompt(struct options *op, struct termios *tp);
 static void next_speed(struct options *op, struct termios *tp);
 static char *get_logname(struct options *op,
@@ -211,6 +229,7 @@ static speed_t bcode(char *s);
 static void usage(FILE * out) __attribute__((__noreturn__));
 static void error(const char *, ...) __attribute__((__noreturn__)) __attribute__((__format__(printf, 1, 2)));
 static void warn (const char *, ...) __attribute__((__format__(printf, 1, 2)));
+static ssize_t safe_write (int fd, const char *buffer, size_t count);
 
 /* Fake hostname for ut_host specified on command line. */
 static char *fakehost;
@@ -232,6 +251,8 @@ int main(int argc, char **argv)
 		0,		/* no timeout */
 		_PATH_LOGIN,	/* default login program */
 		"tty1",		/* default tty line */
+		0,		/* line of virtual console */
+		DEFAULT_VCTERM,	/* terminal type */
 		"",		/* modem init string */
 		ISSUE,		/* default issue file */
 		0, 		/* no baud rates known yet */
@@ -257,13 +278,13 @@ int main(int argc, char **argv)
 
 	/* Update the utmp file. */
 #ifdef	SYSV_STYLE
-	update_utmp(options.tty);
+	update_utmp(&options);
 #endif
 
 	debug("calling open_tty\n");
 
 	/* Open the tty as standard { input, output, error }. */
-	open_tty(options.tty, &termios, options.flags & F_LOCAL);
+	open_tty(options.tty, &termios, &options);
 
 	tcsetpgrp(STDIN_FILENO, getpid());
 	/* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
@@ -273,9 +294,8 @@ int main(int argc, char **argv)
 	/* Write the modem init string and DO NOT flush the buffers. */
 	if (options.flags & F_INITSTRING) {
 		debug("writing init string\n");
-		ignore_result(write
-			      (STDIN_FILENO, options.initstring,
-			       strlen(options.initstring)));
+		safe_write(STDIN_FILENO, options.initstring,
+			       strlen(options.initstring));
 	}
 
 	if (!(options.flags & F_LOCAL))
@@ -325,7 +345,7 @@ int main(int argc, char **argv)
 	termio_final(&options, &termios, &chardata);
 
 	/* Now the newline character should be properly written. */
-	ignore_result(write(STDOUT_FILENO, "\n", 1));
+	safe_write(STDOUT_FILENO, "\n", 1);
 
 	/* Let the login program take care of password validation. */
 	execl(options.login, options.login, "--", logname, NULL);
@@ -392,50 +412,9 @@ static void parse_args(int argc, char **argv, struct options *op)
 			op->flags &= ~F_ISSUE;
 			break;
 		case 'I':
-			/*
-			 * FIXME: It would be better to use a separate
-			 * function for this task.
-			 */
-			{
-				char ch, *p, *q;
-				int i;
-
-				op->initstring = xmalloc(strlen(optarg) + 1);
-
-				/*
-				 * Copy optarg into op->initstring decoding \ddd octal
-				 * codes into chars.
-				 */
-				q = op->initstring;
-				p = optarg;
-				while (*p) {
-					/* The \\ is converted to \ */
-					if (*p == '\\') {
-						p++;
-						if (*p == '\\') {
-							ch = '\\';
-							p++;
-						} else {
-							/* Handle \000 - \177. */
-							ch = 0;
-							for (i = 1; i <= 3; i++) {
-								if (*p >= '0' && *p <= '7') {
-									ch <<= 3;
-									ch += *p - '0';
-									p++;
-								} else {
-									break;
-								}
-							}
-						}
-						*q++ = ch;
-					} else
-						*q++ = *p++;
-				}
-				*q = '\0';
-				op->flags |= F_INITSTRING;
-				break;
-			}
+			init_special_char(optarg, op);
+			op->flags |= F_INITSTRING;
+			break;
 		case 'l':
 			op->login = optarg;
 			break;
@@ -483,15 +462,29 @@ static void parse_args(int argc, char **argv, struct options *op)
 	if ('0' <= argv[optind][0] && argv[optind][0] <= '9') {
 		/* Assume BSD style speed. */
 		parse_speeds(op, argv[optind++]);
-		op->tty = argv[optind];
+		if (argc < optind + 1) {
+			warn(_("not enough arguments"));
+			usage(stderr);
+		}
+		op->tty = argv[optind++];
 	} else {
 		op->tty = argv[optind++];
-		parse_speeds(op, argv[optind]);
+		if (argc > optind) {
+			char *v = argv[optind++];
+			if ('0' <= *v && *v <= '9')
+				parse_speeds(op, v);
+			else
+				op->speeds[op->numspeed++] = bcode("9600");
+		}
 	}
 
-	optind++;
+	/* On virtual console remember the line which is used for */
+	if (strncmp(op->tty, "tty", 3) == 0 &&
+	    strspn(op->tty + 3, "0123456789") == strlen(op->tty+3))
+		op->vcline = op->tty+3;
+
 	if (argc > optind && argv[optind])
-		setenv("TERM", argv[optind], 1);
+		op->term = argv[optind];
 
 #ifdef DO_DEVFS_FIDDLING
 	/*
@@ -547,11 +540,14 @@ static void parse_speeds(struct options *op, char *arg)
 #ifdef	SYSV_STYLE
 
 /* Update our utmp entry. */
-static void update_utmp(char *line)
+static void update_utmp(struct options *op)
 {
 	struct utmp ut;
 	time_t t;
-	int mypid = getpid();
+	pid_t pid = getpid();
+	pid_t sid = getsid(0);
+	char *vcline = op->vcline;
+	char *line   = op->tty;
 	struct utmp *utp;
 
 	/*
@@ -566,7 +562,7 @@ static void update_utmp(char *line)
 	setutent();
 
 	/*
-	 * Find mypid in utmp.
+	 * Find my pid in utmp.
 	 *
 	 * FIXME: Earlier (when was that?) code here tested only utp->ut_type !=
 	 * INIT_PROCESS, so maybe the >= here should be >.
@@ -575,7 +571,7 @@ static void update_utmp(char *line)
 	 * maybe login has to be changed as well (is this true?).
 	 */
 	while ((utp = getutent()))
-		if (utp->ut_pid == mypid
+		if (utp->ut_pid == pid
 				&& utp->ut_type >= INIT_PROCESS
 				&& utp->ut_type <= DEAD_PROCESS)
 			break;
@@ -585,7 +581,18 @@ static void update_utmp(char *line)
 	} else {
 		/* Some inits do not initialize utmp. */
 		memset(&ut, 0, sizeof(ut));
-		strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+		if (vcline && *vcline)
+			/* Standard virtual console devices */
+			strncpy (ut.ut_id, vcline, sizeof (ut.ut_id));
+		else {
+			size_t len = strlen(line);
+			char * ptr;
+			if (len >= sizeof (ut.ut_id))
+				ptr = line + len - sizeof (ut.ut_id);
+			else
+				ptr = line;
+			strncpy (ut.ut_id, ptr, sizeof(ut.ut_id));
+		}
 	}
 
 	strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
@@ -595,7 +602,8 @@ static void update_utmp(char *line)
 	time(&t);
 	ut.ut_time = t;
 	ut.ut_type = LOGIN_PROCESS;
-	ut.ut_pid = mypid;
+	ut.ut_pid = pid;
+	ut.ut_session = sid;
 
 	pututline(&ut);
 	endutent();
@@ -611,7 +619,7 @@ static void update_utmp(char *line)
 			flock(lf, LOCK_EX);
 			if ((ut_fd =
 			     open(_PATH_WTMP, O_APPEND | O_WRONLY)) >= 0) {
-				ignore_result(write(ut_fd, &ut, sizeof(ut)));
+				safe_write(ut_fd, &ut, sizeof(ut));
 				close(ut_fd);
 			}
 			flock(lf, LOCK_UN);
@@ -624,7 +632,7 @@ static void update_utmp(char *line)
 #endif				/* SYSV_STYLE */
 
 /* Set up tty as stdin, stdout & stderr. */
-static void open_tty(char *tty, struct termios *tp, int __attribute__((__unused__)) local)
+static void open_tty(char *tty, struct termios *tp, struct options *op)
 {
 	/* Get rid of the present outputs. */
 	close(STDOUT_FILENO);
@@ -690,6 +698,8 @@ static void open_tty(char *tty, struct termios *tp, int __attribute__((__unused_
 	ignore_result(chown(tty, 0, 0));
 	ignore_result(chmod(tty, 0600));
 	errno = 0;
+
+	setenv("TERM", op->term, 1);
 }
 
 /* Initialize termios settings. */
@@ -816,14 +826,14 @@ static void do_prompt(struct options *op, struct termios *tp)
 #ifdef	ISSUE
 	FILE *fd;
 	int oflag;
-	int c, i;
+	int c;
 	struct utsname uts;
 
 	uname(&uts);
 #endif				/* ISSUE */
 
 	/* Issue not in use, start with a new line. */
-	ignore_result(write(STDOUT_FILENO, "\r\n", 2));
+	safe_write(STDOUT_FILENO, "\r\n", 2);
 #ifdef	ISSUE
 	if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
 		/* Save current setting. */
@@ -833,132 +843,10 @@ static void do_prompt(struct options *op, struct termios *tp)
 		tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
 
 		while ((c = getc(fd)) != EOF) {
-			if (c == '\\') {
-				c = getc(fd);
-
-				switch (c) {
-				case 's':
-					printf("%s", uts.sysname);
-					break;
-				case 'n':
-					printf("%s", uts.nodename);
-					break;
-				case 'r':
-					printf("%s", uts.release);
-					break;
-				case 'v':
-					printf("%s", uts.version);
-					break;
-				case 'm':
-					printf("%s", uts.machine);
-					break;
-				case 'o':
-					/*
-					 * FIXME: It would be better to use a
-					 * separate function for this task.
-					 */
-					{
-						char domainname[MAXHOSTNAMELEN + 1];
-#ifdef HAVE_GETDOMAINNAME
-						if (getdomainname(domainname, sizeof(domainname)))
-#endif				/* HAVE_GETDOMAINNAME */
-							strcpy(domainname, "unknown_domain");
-						domainname[sizeof(domainname) - 1] = '\0';
-						printf("%s", domainname);
-						break;
-					}
-				case 'O':
-					/*
-					 * FIXME: It would be better to use a
-					 * separate function for this task.
-					 */
-					{
-						char *dom = "unknown_domain";
-						char host[MAXHOSTNAMELEN + 1];
-						struct addrinfo hints, *info = NULL;
-
-						memset(&hints, 0, sizeof(hints));
-						hints.ai_flags = AI_CANONNAME;
-
-						if (gethostname(host, sizeof(host))
-						    || getaddrinfo(host, NULL, &hints, &info)
-						    || info == NULL) {
-							fputs(dom, stdout);
-						} else {
-							char *canon;
-
-							if (info->ai_canonname
-							    && (canon =
-								strchr(info->ai_canonname, '.'))) {
-								dom = canon + 1;
-							}
-							fputs(dom, stdout);
-							freeaddrinfo(info);
-						}
-						break;
-					}
-				case 'd':
-				case 't':
-					/*
-					 * FIXME: It would be better to use a
-					 * separate function for this task.
-					 */
-					{
-						time_t now;
-						struct tm *tm;
-
-						time(&now);
-						tm = localtime(&now);
-
-						if (c == 'd')
-							printf
-							    ("%s %s %d  %d",
-							     nl_langinfo(ABDAY_1 + tm->tm_wday),
-							     nl_langinfo(ABMON_1 + tm->tm_mon),
-							     tm->tm_mday,
-							     /* FIXME: y2070 bug */
-							     tm->tm_year < 70 ?
-								 tm->tm_year + 2000 :
-								 tm->tm_year + 1900);
-						else
-							printf("%02d:%02d:%02d",
-							       tm->tm_hour, tm->tm_min, tm->tm_sec);
-						break;
-					}
-				case 'l':
-					printf("%s", op->tty);
-					break;
-				case 'b':
-					for (i = 0; speedtab[i].speed; i++)
-						if (speedtab[i].code == cfgetispeed(tp))
-							printf("%ld", speedtab[i].speed);
-					break;
-					break;
-				case 'u':
-				case 'U':
-					/*
-					 * FIXME: It would be better to use a
-					 * separate function for this task.
-					 */
-					{
-						int users = 0;
-						struct utmp *ut;
-						setutent();
-						while ((ut = getutent()))
-							if (ut->ut_type == USER_PROCESS)
-								users++;
-						endutent();
-						printf("%d ", users);
-						if (c == 'U')
-							printf((users == 1) ?
-								_("user") : _("users"));
-						break;
-					}
-				default:
-					putchar(c);
-				}
-			} else
-				putchar(c);
+			if (c == '\\')
+				output_special_char(getc(fd), op, tp);
+			else
+				(void) putchar(c);
 		}
 		fflush(stdout);
 
@@ -972,10 +860,10 @@ static void do_prompt(struct options *op, struct termios *tp)
 	{
 		char hn[MAXHOSTNAMELEN + 1];
 		if (gethostname(hn, sizeof(hn)) == 0)
-			ignore_result(write(STDIN_FILENO, hn, strlen(hn)));
+			safe_write(STDIN_FILENO, hn, strlen(hn));
 	}
 	/* Always show login prompt. */
-	ignore_result(write(STDOUT_FILENO, LOGIN, sizeof(LOGIN) - 1));
+	safe_write(STDOUT_FILENO, LOGIN, sizeof(LOGIN) - 1);
 }
 
 /* Select next baud rate. */
@@ -1070,9 +958,8 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
 				/* Set erase character. */
 				cp->erase = ascval;
 				if (bp > logname) {
-					ignore_result(write
-						      (STDIN_FILENO,
-						       erase[cp->parity], 3));
+					safe_write(STDIN_FILENO,
+						   erase[cp->parity], 3);
 					bp--;
 				}
 				break;
@@ -1081,9 +968,8 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
 				/* Set kill character. */
 				cp->kill = ascval;
 				while (bp > logname) {
-					ignore_result(write
-						      (STDIN_FILENO,
-						       erase[cp->parity], 3));
+					safe_write(STDIN_FILENO,
+						   erase[cp->parity], 3);
 					bp--;
 				}
 				break;
@@ -1096,8 +982,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
 					error(_("%s: input overrun"), op->tty);
 				} else {
 					/* Echo the character... */
-					ignore_result(write
-						      (STDIN_FILENO, &c, 1));
+					safe_write(STDIN_FILENO, &c, 1);
 					/* ...and store it. */
 					*bp++ = ascval;
 				}
@@ -1307,7 +1192,7 @@ static void dolog(int priority, const char *fmt, va_list ap)
 	/* Terminate with CR-LF since the console mode is unknown. */
 	strcat(bp, "\r\n");
 	if ((fd = open("/dev/console", 1)) >= 0) {
-		ignore_result(write(fd, buf, strlen(buf)));
+		safe_write(fd, buf, strlen(buf));
 		close(fd);
 	}
 #endif				/* USE_SYSLOG */
@@ -1335,3 +1220,170 @@ static void warn(const char *fmt, ...)
 	va_end(ap);
 }
 
+static ssize_t safe_write(int fd, const char *buffer, size_t count)
+{
+	ssize_t offset = 0;
+
+	while (count > 0) {
+	ssize_t block = write(fd, &buffer[offset], count);
+	    if (block < 0 && errno == EINTR)
+	    continue;
+	    if (block <= 0)
+		return offset ? offset : block;
+	    offset += block;
+	    count -= block;
+	}
+	return offset;
+}
+static void output_special_char(unsigned char c, struct options *op,
+				struct termios *tp)
+{
+	struct utsname uts;
+	(void) uname(&uts);
+	switch (c) {
+	case 's':
+		(void) printf ("%s", uts.sysname);
+		break;
+	case 'n':
+		(void) printf ("%s", uts.nodename);
+		break;
+	case 'r':
+		(void) printf ("%s", uts.release);
+		break;
+	case 'v':
+		(void) printf ("%s", uts.version);
+		break;
+	case 'm':
+		(void) printf ("%s", uts.machine);
+		break;
+	case 'o':
+	{
+		char domainname[MAXHOSTNAMELEN+1];
+#ifdef HAVE_GETDOMAINNAME
+		if (getdomainname(domainname, sizeof(domainname)))
+#endif
+		strcpy(domainname, "unknown_domain");
+		domainname[sizeof(domainname)-1] = '\0';
+		printf ("%s", domainname);
+		break;
+	}
+	case 'O':
+	{
+		char *dom = "unknown_domain";
+		char host[MAXHOSTNAMELEN+1];
+		struct addrinfo hints, *info = NULL;
+
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_flags = AI_CANONNAME;
+
+		if (gethostname(host, sizeof(host)) ||
+		    getaddrinfo(host, NULL, &hints, &info) ||
+		    info == NULL)
+			fputs(dom, stdout);
+		else {
+			char *canon;
+			if (info->ai_canonname &&
+			    (canon = strchr(info->ai_canonname, '.')))
+				dom = canon + 1;
+			fputs(dom, stdout);
+			freeaddrinfo(info);
+		}
+		break;
+	}
+	case 'd':
+	case 't':
+	{
+		time_t now;
+		struct tm *tm;
+
+		(void) time (&now);
+		tm = localtime(&now);
+
+		if (c == 'd') /* ISO 8601 */
+			(void) printf("%s %s %d  %d",
+				      nl_langinfo(ABDAY_1 + tm->tm_wday),
+				      nl_langinfo(ABMON_1 + tm->tm_mon),
+				      tm->tm_mday,
+				      tm->tm_year < 70 ? tm->tm_year + 2000 :
+				      tm->tm_year + 1900);
+		else
+			(void) printf("%02d:%02d:%02d",
+				      tm->tm_hour, tm->tm_min, tm->tm_sec);
+		break;
+	}
+	case 'l':
+		(void) printf ("%s", op->tty);
+		break;
+	case 'b':
+	{
+		const speed_t speed = cfgetispeed(tp);
+		int i;
+
+		for (i = 0; speedtab[i].speed; i++) {
+			if (speedtab[i].code == speed) {
+				printf("%ld", speedtab[i].speed);
+				break;
+			}
+		}
+		break;
+	}
+	case 'u':
+	case 'U':
+	{
+		int users = 0;
+		struct utmp *ut;
+		setutent();
+		while ((ut = getutent()))
+			if (ut->ut_type == USER_PROCESS)
+				users++;
+		endutent();
+		printf ("%d ", users);
+		if (c == 'U')
+			printf ((users == 1) ? _("user") : _("users"));
+		break;
+	}
+	default:
+		(void) putchar(c);
+		break;
+	}
+}
+
+static void init_special_char(char* arg, struct options *op)
+{
+	char ch, *p, *q;
+	int i;
+
+	op->initstring = xmalloc(strlen(arg) + 1);
+
+	/*
+	 * Copy optarg into op->initstring decoding \ddd octal
+	 * codes into chars.
+	 */
+	q = op->initstring;
+	p = arg;
+	while (*p) {
+		/* The \\ is converted to \ */
+		if (*p == '\\') {
+			p++;
+			if (*p == '\\') {
+				ch = '\\';
+				p++;
+			} else {
+				/* Handle \000 - \177. */
+				ch = 0;
+				for (i = 1; i <= 3; i++) {
+					if (*p >= '0' && *p <= '7') {
+						ch <<= 3;
+						ch += *p - '0';
+						p++;
+					} else {
+						break;
+					}
+				}
+			}
+			*q++ = ch;
+		} else
+			*q++ = *p++;
+	}
+	*q = '\0';
+}
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux