--- mingetty-0.9.4b/mingetty.8	Mon Oct 23 07:57:59 2000
+++ mingetty-0.9.4b/mingetty.8.autologin	Fri May 24 12:51:52 2002
@@ -1,9 +1,9 @@
-.TH MINGETTY 8 "12 June 1999" "SuSE" "Linux Programmer's Manual"
+.TH MINGETTY 8 "24 May 2002" "SuSE" "Linux Programmer's Manual"
 .SH NAME
 mingetty \- minimal getty for consoles
 .SH SYNOPSIS
 .B mingetty
-[\-\-noclear] [\-\-long\-hostname] [\-\-noreset]
+[\-\-noclear] [\-\-long\-hostname] [\-\-autologin username ] [\-\-noreset]
 .I tty
 .PP
 .SH DESCRIPTION
@@ -27,6 +27,41 @@
 By default the hostname is only printed until the first dot.
 With this option enabled, the full text from gethostname() is shown.
 .TP
+.B \-\-autologin username
+Log the specified user onto the console (normally
+.IR  /dev/console )
+when the system is first booted without prompting for a username or
+password.
+.IP
+When the autologin option is supplied,
+.B mingetty 
+will check that the controlling terminal is the console (normally
+.IR /dev/console ), 
+that a reasonable username has been supplied, and that this is the
+first autologin request since the system has booted.  If all of these
+conditions have been met, a request for an unauthenticated login is
+passed to the
+.B login 
+program.  Otherwise, a normal interactive login is performed.
+.IP
+The
+.B login 
+program may deny the request for an unauthenticated login.  Typically
+this will happen when the user is root, has a UID of 0, or whenever a
+normal interactive login would be denied due to the access
+restrictions specified in the
+.IR nologin , 
+.IR usertty , 
+or
+.I securetty 
+files.
+.IP
+Only a single autologin request will be issued after a system boot.
+If the automated login request is denied, or if the user logs out, 
+.B mingetty
+will revert to performing normal interactive logins for all subsequent
+login requests.
+.TP
 .B \-\-noreset
 By default the terminal settings will be initialized to some
 sane default values.  With this option the terminal settings
@@ -103,7 +138,8 @@
 .PP
 .SH FILES
 .IR /etc/issue ,
-.IR /var/run/utmp .
+.IR /var/run/utmp ,
+.IR /var/log/autologin .
 .PP
 .SH "SEE ALSO"
 .BR mgetty (8),
--- mingetty-0.9.4b/mingetty.c	Fri May 24 11:11:55 2002
+++ mingetty-0.9.4b/mingetty.c.autologin	Fri May 24 11:51:48 2002
@@ -17,8 +17,8 @@
  *  should be very reliable. For a modem getty, I'd also use nothing else
  *  but mgetty.
  *
- *  Usage: mingetty [--noclear] [--noreset] [--login loginprog] 
- *   [--logopts "options for login prog"] tty
+ *  Usage: mingetty [--noclear] [--autologin username] [--noreset] 
+ *   [--login loginprog] [--logopts "options for login prog"] tty
  *  Example entry in /etc/inittab: 1:123:respawn:/sbin/mingetty tty1
  *
  *  This program is free software; you can redistribute it and/or
@@ -100,6 +100,20 @@
 #endif
 
 #ifdef linux
+/* Autologin stuff.  Currently Linux-specific, since there's no
+   standard way of getting the system boot time.  The kernel.h and the
+   sysinfo prototype are used to get the system uptime under Linux. */
+#include <linux/kernel.h>
+int sysinfo(struct sysinfo *info);
+
+/* AUTO_LAST points to a timestamp file used to limit autologins to
+   one per system boot. */
+#define AUTO_LAST "/var/log/autologin"
+
+/* AUTO_TTY is the tty on which autologins will be accepted.  If set
+   to an empty string, autologins will be accepted on any tty. */
+#define AUTO_TTY "console"
+
 #include <sys/param.h>
 #define USE_SYSLOG
 #endif
@@ -137,6 +151,8 @@
 static int noclear = 0;
 /* Print the whole string of gethostname() instead of just until the next "." */
 static int longhostname = 0;
+/* If supplied, attempt an automatic login with this username. */
+static char *autologin_name = NULL;
 /* do not reset the terminal ? */
 static int noreset = 0;
 /* login program */
@@ -654,6 +670,61 @@
 	return logname;
 }
 
+/*
+ * autologin_ok -- returns 1 if it's okay to auto-login when:
+ *   this login is from /dev/tty1; and
+ *   there was a login name passed with the --autologin option; and
+ *   the autologin_name contains only "nice" characters; and
+ *   this is the first autologin attempt since the last boot; 
+ * return 0 otherwise.
+ */
+static int autologin_ok(void)
+{
+	char c, *cp;
+	int stat_err, fd;
+	struct sysinfo info;
+	struct stat sbuf;
+
+	/* Autologins are restricted to AUTO_TTY if non-empty. */
+	if (AUTO_TTY[0] && strcmp(tty, AUTO_TTY))
+		return 0;
+
+	/* An all-alphanumeric autologin name must be supplied. */
+	if (autologin_name == NULL || autologin_name[0] == '\0')
+		return 0;
+	for (cp = autologin_name; (c = *cp); cp++)
+		if (!isalnum(c) && c != '_')
+			return 0;
+
+	/* Get the uptime in info.uptime, and the last autologin time
+           in sbuf.st_mtime. */
+	sysinfo(&info);
+	stat_err = stat(AUTO_LAST, &sbuf);
+
+	/* If a stat error other than "no such file" occurs, I don't
+           know what went wrong, so I'll proceed with caution by
+           denying the autologin request. */
+	if (stat_err && errno != ENOENT)
+		return 0;
+
+	/* If there's been an autologin granted since the last boot,
+           deny this and any subsequent attempts.  Note that this test
+           is skipped if the AUTO_LAST file doesn't exist. */
+	if (!stat_err && time(NULL) - info.uptime < sbuf.st_mtime)
+		return 0;
+
+	/* Create the AUTO_LAST file.  The mtime of this file provides
+           a persistent record of the last time that an autologin
+           request was granted.  Deny the autologin request if either
+           the file open or file close fails. */
+	if ((fd=open(AUTO_LAST, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
+		return 0;
+	if (close(fd) != 0)
+		return 0;
+
+	/* All tests are okay, so grant the autologin request. */
+	return 1;
+}
 static void usage (void)
 {
 	error ("%s: usage: '%s [--noclear] [--noreset] [--long-hostname] [--login program] [--logopts \"loginprg opts\"] tty' with e.g. tty=tty1", VERSION, progname);
@@ -665,6 +736,7 @@
 	{ "noreset", no_argument, &noreset, 1},
 	{ "login", required_argument, 0, 2},
 	{ "logopts", required_argument, 0, 3},
+	{ "autologin", required_argument, NULL, 'a'},
 	{ 0, 0, 0, 0 }
 };
 
@@ -753,6 +825,9 @@
 		                loginprog = optarg; break;
 		        case 3:
 		                logoptstr = optarg; break;
+			case 'a':
+				autologin_name = optarg;
+				break;
 			default:
 				usage ();
 		}
@@ -777,19 +852,22 @@
 #else
 	ioctl (0, TCFLSH, 2);
 #endif
-
-	while ((logname = get_logname ()) == 0);
-	strcpy (logcmd, loginprog); strcat (logcmd, " ");
-	strcat (logcmd, logoptstr);
-	mkarray (logarr, logcmd);
-	checkname (logname); replacename (logarr, logname);
+	if (autologin_ok()) {
+		execl (_PATH_LOGIN, _PATH_LOGIN, "-f", autologin_name, NULL);
+	} else {
+		while ((logname = get_logname ()) == 0);
+		strcpy (logcmd, loginprog); strcat (logcmd, " ");
+		strcat (logcmd, logoptstr);
+		mkarray (logarr, logcmd);
+		checkname (logname); replacename (logarr, logname);
 
 #if DEBUG_THIS
-	printf ("About to execute %s", logcmd);
-	c = 1; while (logarr[c]) printf (" `%s'", logarr[c++]);
-	printf ("\n"); sleep (1);
+		printf ("About to execute %s", logcmd);
+		c = 1; while (logarr[c]) printf (" `%s'", logarr[c++]);
+		printf ("\n"); sleep (1);
 #endif
-	execv (loginprog, logarr);
+		execv (loginprog, logarr);
+	}
 	error ("%s: can't exec %s: %s", tty, loginprog, strerror(errno));
 	sleep (1); exit (0);
 }
