diff -urN shadow-960810-orig/README shadow-960810-final/README
--- shadow-960810-orig/README	Sat Aug 10 10:59:49 1996
+++ shadow-960810-final/README	Wed Aug 14 18:56:06 1996
@@ -5,3 +5,20 @@
 working version is shadow-960325.
 
 --marekm
+
+
+Features for RedHat Users Only:
+
+I have added basic support for long usernames.  It just falls back on
+getpwuid(getuid()) if getlogin fails.  I needed it. I thought someone
+else might too.
+--Tim Hockin <thockin@ais.net>
+
+I have added a limits patch for setting user resources on login. Check
+the login manpage for details.
+--Cristian Gafton <gafton@sorosis.ro>
+
+Ask for support at shadow@broadwaynet.com if you have any problems with
+this package.
+--RedHat shadow developers (shadow@broadwaynet.com)
+
diff -urN shadow-960810-orig/acconfig.h shadow-960810-final/acconfig.h
--- shadow-960810-orig/acconfig.h	Sat Aug 10 10:59:49 1996
+++ shadow-960810-final/acconfig.h	Wed Aug 14 19:07:11 1996
@@ -131,3 +131,8 @@
 /* see lmain.c and login.defs.linux */
 #define CONSOLE_GROUPS
 
+/* the user-limits file */
+#define LIMITS_FILE "/etc/limits"
+
+/* Define to allow the use of long user names */
+#define LONG_USER_NAMES 1
diff -urN shadow-960810-orig/configure.in shadow-960810-final/configure.in
--- shadow-960810-orig/configure.in	Sat Aug 10 10:59:49 1996
+++ shadow-960810-final/configure.in	Thu Aug 15 02:28:16 1996
@@ -54,7 +54,12 @@
 AC_TYPE_SIGNAL
 AC_FUNC_UTIME_NULL
 AC_CHECK_FUNCS(gethostname gettimeofday getusershell strcspn strftime strspn strtol)
-AC_CHECK_FUNCS(initgroups getgroups setgroups sigaction getutent getspnam)
+dnl ### RedHat libc shadow is compiled with compatibility ON, thus
+dnl ### libc getspnam sucks - always returns success. Use the libshadow.a one
+dnl ### instead (at least for core, otherwise pwconv will fail...)
+dnl AC_CHECK_FUNCS(initgroups getgroups setgroups sigaction getutent getspnam)
+dnl ### --cristiang
+AC_CHECK_FUNCS(initgroups getgroups setgroups sigaction getutent)
 
 AC_REPLACE_FUNCS(mkdir rename rmdir strdup strstr)
 AC_REPLACE_FUNCS(putgrent putpwent putspent sgetgrent sgetpwent sgetspent)
@@ -170,6 +175,8 @@
 AC_DEFINE(SU_ACCESS)
 AC_DEFINE(FAILLOG_LOCKTIME)
 AC_DEFINE(CONSOLE_GROUPS)
+AC_DEFINE(LIMITS_FILE,"/etc/limits")
+AC_DEFINE(LONG_USER_NAMES)
 
 AC_ARG_ENABLE(shadowgrp, [  --enable-shadowgrp      enable shadow group support], AC_DEFINE(SHADOWGRP))
 
diff -urN shadow-960810-orig/etc/limits shadow-960810-final/etc/limits
--- shadow-960810-orig/etc/limits	Thu Jan  1 02:00:00 1970
+++ shadow-960810-final/etc/limits	Wed Aug 14 18:46:16 1996
@@ -0,0 +1,25 @@
+# this file set the user limits
+# Format:
+# <username> <limits-string>
+#
+# default entry is '*' for username
+#
+# Valid flags are:
+# C: max core file size (KB)
+# D: max data size (KB)
+# F: maximum filesize (KB)
+# M: max locked-in-memory address space (KB)
+# N: max number of open files
+# R: max resident set size (KB)
+# S: max stack size (KB)
+# T: max CPU time (MIN)
+# U: max number of processes
+# L: max number of logins for this user
+
+# the default entry
+* L2 D6144 R2048 S2048 U32 N32 F16384 T5 C0
+# another way of suspending a user login
+guest   L0
+# this account has no limits
+sysadm  -
+
diff -urN shadow-960810-orig/etc/login.defs.linux shadow-960810-final/etc/login.defs.linux
--- shadow-960810-orig/etc/login.defs.linux	Sat Aug 10 10:59:52 1996
+++ shadow-960810-final/etc/login.defs.linux	Wed Aug 14 19:17:23 1996
@@ -80,7 +80,7 @@
 #
 # If defined, all su activity is logged to this file.
 #
-#SULOG_FILE	/var/log/sulog
+SULOG_FILE	/var/log/sulog
 
 #
 # If defined, ":" delimited list of "message of the day" files to
@@ -97,7 +97,7 @@
 # If defined, file which maps tty line to TERM environment parameter.
 # Each line of the file is in a format something like "vt100  tty01".
 #
-#TTYTYPE_FILE	/etc/ttytype
+TTYTYPE_FILE	/etc/ttytype
 
 #
 # If defined, login failures will be logged here in a utmp format.
@@ -179,7 +179,7 @@
 # TTYPERM to either 622 or 600.
 #
 TTYGROUP	tty
-TTYPERM		0600
+TTYPERM		0620
 
 #
 # Login configuration initializations:
@@ -219,7 +219,7 @@
 # to uid 0 accounts.  If the group doesn't exist or is empty, no one
 # will be able to "su" to uid 0.
 #
-SU_WHEEL_ONLY	no
+SU_WHEEL_ONLY	yes
 
 #
 # If compiled with cracklib support, where are the dictionaries
@@ -241,12 +241,12 @@
 #
 # Max number of login retries if password is bad
 #
-LOGIN_RETRIES		5
+LOGIN_RETRIES		3
 
 #
 # Max time in seconds for login
 #
-LOGIN_TIMEOUT		60
+LOGIN_TIMEOUT		45
 
 #
 # Maximum number of attempts to change password if rejected (too easy)
@@ -298,4 +298,4 @@
 # Should login be allowed if we can't cd to the home directory?
 # Default in no.
 #
-#DEFAULT_HOME	yes
+DEFAULT_HOME	no
diff -urN shadow-960810-orig/lib/getdef.c shadow-960810-final/lib/getdef.c
--- shadow-960810-orig/lib/getdef.c	Sat Aug 10 10:59:50 1996
+++ shadow-960810-final/lib/getdef.c	Wed Aug 14 19:19:29 1996
@@ -83,6 +83,7 @@
 	{ "LOGIN_RETRIES",		NULL },
 	{ "LOGIN_STRING",		NULL },
 	{ "LOGIN_TIMEOUT",		NULL },
+	{ "LOG_FAIL_WARN",              NULL },
 	{ "LOG_OK_LOGINS",		NULL },
 	{ "LOG_UNKFAIL_ENAB",		NULL },
 	{ "MAIL_CHECK_ENAB",		NULL },
diff -urN shadow-960810-orig/man/login.1 shadow-960810-final/man/login.1
--- shadow-960810-orig/man/login.1	Sat Aug 10 10:59:50 1996
+++ shadow-960810-final/man/login.1	Wed Aug 14 18:51:31 1996
@@ -103,6 +103,47 @@
 may be in use at any particular site.
 .PP
 The location of files is subject to differences in system configuration.
+.SH
+Setting user limits for shadow login program
+.PP
+First, make a root-only-readable file (\fB/etc/limits\fR by default or LIMITS_FILE
+defined config.h) that describes the resource limits you wish to impose. By
+default no quotas are imposed on 'root'. In fact, there is no way to impose
+limits via this procedure to root-equiv accounts (accounts with UID 0).
+.PP
+Each line describes a limit for a user in the form:
+.br
+\fBuser LIMITS_STRING\fR
+.PP
+The \fBLIMITS_STRING\fR is a string of a concatenated list of resource limits.
+Each limit consists of a letter identifier followed by a numerical limit.
+The valid identifiers are:
+.br
+\fBC\fR: max core file size (KB)
+.br
+\fBD\fR: max data size (KB)
+.br
+\fBF\fR: maximum filesize (KB)
+.br
+\fBM\fR: max locked-in-memory address space (KB)
+.br
+\fBN\fR: max number of open files
+.br
+\fBR\fR: max resident set size (KB)
+.br
+\fBS\fR: max stack size (KB)
+.br
+\fBT\fR: max CPU time (MIN)
+.br
+\fBU\fR: max number of processes
+.br
+\fBL\fR: max number of logins for this user
+.PP
+For example, \fBL2D2048N5\fR is a valid \fBLIMITS_STRING\fR.
+.PP
+The default entry is denoted by username '\fB*\fR'. If you have multiple 'default'
+entries in your LIMITS_FILE, the last one will be used as the default
+entry.
 .SH Files
 /etc/utmp \- list of current login sessions
 .br
@@ -115,6 +156,8 @@
 /etc/motd \- system message file
 .br
 /etc/ttytype \- list of terminal types
+.br
+/etc/limits \- the user limits on system resources file
 .br
 $HOME/.profile \- initialization script for default shell
 .br
diff -urN shadow-960810-orig/src/chfn.c shadow-960810-final/src/chfn.c
--- shadow-960810-orig/src/chfn.c	Sat Aug 10 10:59:52 1996
+++ shadow-960810-final/src/chfn.c	Wed Aug 14 20:02:46 1996
@@ -219,7 +219,7 @@
 	char **argv;
 {
 	char	*cp;			/* temporary character pointer       */
-	const struct passwd *pw;	/* password file entry               */
+	const struct passwd *pw = NULL;	/* password file entry               */
 	struct	passwd	pwent;		/* modified password file entry      */
 	char	old_gecos[BUFSIZ];	/* buffer for old GECOS fields       */
 	char	new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
@@ -307,14 +307,22 @@
 	if (optind < argc)
 		strncpy (user, argv[optind], sizeof user - 1);
 	else if ((cp = getlogin ()))
-		strncpy (user, cp, sizeof user - 1);
+#ifdef LONG_USER_NAMES
+		if (! (pw = getpwnam(cp)) || pw->pw_uid != getuid()) {
+			pw = getpwuid(getuid());
+			strncpy (user, pw->pw_name, sizeof(user) - 1);
+		} else
+#endif
+		strncpy (user, cp, sizeof(user) - 1);
 	else {
 		fprintf (stderr, WHOAREYOU, Prog);
 		closelog ();
 		exit (1);
 	}
 	user[sizeof user - 1] = '\0';
+#ifndef LONG_USER_NAMES
 	pw = getpwnam(user);
+#endif
 
 	/*
 	 * Make certain there was a password entry for the
@@ -322,9 +330,17 @@
 	 */
 
 	if (! pw) {
+#ifdef LONG_USER_NAMES
+		if (!(pw = getpwnam(user))) {
+#endif
 		fprintf (stderr, UNKUSER, Prog, user);
+#ifdef  USE_SYSLOG
 		closelog ();
+#endif
 		exit (1);
+#ifdef LONG_USER_NAMES
+		}
+#endif
 	}
 
 #ifdef	USE_NIS
diff -urN shadow-960810-orig/src/chsh.c shadow-960810-final/src/chsh.c
--- shadow-960810-orig/src/chsh.c	Sat Aug 10 10:59:52 1996
+++ shadow-960810-final/src/chsh.c	Wed Aug 14 20:02:21 1996
@@ -215,7 +215,7 @@
 	int	sflg = 0;		/* -s - set shell from command line  */
 	int	i;			/* Loop control variable             */
 	char	*cp;			/* Miscellaneous character pointer   */
-	const struct passwd *pw;	/* Password entry from /etc/passwd   */
+	const struct passwd *pw = NULL;	/* Password entry from /etc/passwd   */
 	struct	passwd	pwent;		/* New password entry                */
 
 	/*
@@ -273,7 +273,13 @@
 	if (optind < argc)
 		strncpy (user, argv[optind], sizeof user - 1);
 	else if ((cp = getlogin ()))
-		strncpy (user, cp, sizeof user - 1);
+#ifdef LONG_USER_NAMES
+		if (! (pw = getpwnam(cp)) || pw->pw_uid != getuid()) {
+			pw = getpwuid(getuid());
+			strncpy (user, pw->pw_name, sizeof(user) - 1);
+		} else
+#endif
+		strncpy (user, cp, sizeof(user) - 1);
 	else {
 		fprintf (stderr, WHOAREYOU, Prog);
 #ifdef	USE_SYSLOG
@@ -281,8 +287,10 @@
 #endif
 		exit (1);
 	}
-	user[sizeof user - 1] = '\0';
+	user[sizeof(user) - 1] = '\0';
+#ifndef LONG_USER_NAMES
 	pw = getpwnam(user);
+#endif
 
 	/*
 	 * Make certain there was a password entry for the
@@ -290,11 +298,17 @@
 	 */
 
 	if (! pw) {
+#ifdef LONG_USER_NAMES
+		if (!(pw = getpwnam(user))) {
+#endif
 		fprintf (stderr, UNKUSER, Prog, user);
 #ifdef	USE_SYSLOG
 		closelog ();
 #endif
 		exit (1);
+#ifdef LONG_USER_NAMES
+		}
+#endif
 	}
 
 #ifdef	USE_NIS
diff -urN shadow-960810-orig/src/login.c shadow-960810-final/src/login.c
--- shadow-960810-orig/src/login.c	Sat Aug 10 10:59:52 1996
+++ shadow-960810-final/src/login.c	Wed Aug 14 19:26:19 1996
@@ -156,6 +156,7 @@
 	"Warning: login re-enabled after temporary lockout.\n"
 #define REENABLED2 \
 	"login `%s' re-enabled after temporary lockout (%d failures).\n"
+#define	MANY_FAILS	"REPEATED login failures (%d)%s'\n"
 
 /*
  * usage - print login command usage and exit
@@ -267,6 +268,7 @@
 	int	retries;
 	int	arg;
 	int	failed;
+	int	fails;
 	int	flag;
 	int	subroot = 0;
 	int	is_console;
@@ -543,6 +545,7 @@
 
 	environ = newenvp;		/* make new environment active */
 	retries = getdef_num("LOGIN_RETRIES", RETRIES);
+	fails = 0;
 	while (1) {	/* repeatedly get login/password pairs */
 		failed = 0;		/* haven't failed authentication yet */
 #ifdef RADIUS
@@ -733,6 +736,11 @@
 			sleep (getdef_num ("FAIL_DELAY", 0));
 
 		puts ("Login incorrect");
+		fails++;
+#ifdef USE_SYSLOG
+		if (fails >= getdef_num("LOG_FAIL_WARN",3))
+			syslog(LOG_CRIT, MANY_FAILS, fails, fromhost);
+#endif
 
 		/* allow only one attempt with -r or -f */
 		if (rflg || fflg || retries <= 0)
diff -urN shadow-960810-orig/src/passwd.c shadow-960810-final/src/passwd.c
--- shadow-960810-orig/src/passwd.c	Sat Aug 10 10:59:52 1996
+++ shadow-960810-final/src/passwd.c	Wed Aug 14 20:07:58 1996
@@ -900,7 +900,7 @@
 {
 	char	*cp;			/* Miscellaneous character pointing  */
 	int	flag;			/* Current option to process         */
-	const struct passwd *pw;	/* Password file entry for user      */
+	const struct passwd *pw = NULL;	/* Password file entry for user      */
 #ifdef SHADOWPWD
 	const struct spwd *sp;		/* Shadow file entry for user        */
 #endif
@@ -1071,6 +1071,8 @@
 	 * Now I have to get the user name.  The name will be gotten 
 	 * from the command line if possible.  Otherwise it is figured
 	 * out from the environment.
+	 *
+	 * If they do not match, fall back on getpwuid(getuid()).
 	 */
 
 	if (optind < argc) {
@@ -1080,6 +1082,12 @@
 		strcpy (name, "root");
 #endif
 	} else if ((cp = getlogin ())) {
+#ifdef LONG_USER_NAMES
+		if(! (pw = getpwnam(cp)) || pw->pw_uid != getuid()){
+			pw = getpwuid(getuid());
+			STRFCPY(name, pw->pw_name);
+		} else
+#endif
 		STRFCPY(name, cp);
 	} else {
 		fprintf (stderr, WHOAREYOU, Prog);
@@ -1094,6 +1102,9 @@
 	 * matches the current real UID.
 	 */
 
+#ifdef LONG_USER_NAMES
+	if (! pw )
+#endif
 	if (! (pw = getpwnam (name))) {
 		fprintf (stderr, UNKUSER, Prog, name);
 #ifdef	USE_SYSLOG
