File notify-pam-dead.patch of Package sysvinit

--- src/Makefile
+++ src/Makefile	2010-04-13 00:00:00.000000000 +0000
@@ -8,7 +8,7 @@
 # Version:	@(#)Makefile  2.85-13  23-Mar-2004  miquels@cistron.nl
 #
 
-CPPFLAGS =
+CPPFLAGS = -DUSE_PAM
 CFLAGS	?= -ansi -O2 -fomit-frame-pointer
 override CFLAGS += -W -Wall -D_GNU_SOURCE
 STATIC	=
@@ -78,6 +78,13 @@ else
 endif
 
 # Additional libs for GNU libc.
+ifneq ($(findstring -DUSE_PAM,$(CPPFLAGS)),)
+  INITLIBS	+= -lpam
+  PAMDOTD	= /etc/pam.d
+  PAMINIT	= $(PAMDOTD)/init
+endif
+
+# Additional libs for GNU libc.
 ifneq ($(wildcard /usr/lib*/libcrypt.a),)
   SULOGINLIBS	+= -lcrypt
 endif
@@ -149,6 +156,11 @@ install:
 		for i in $(USRBIN); do \
 			$(INSTALL_EXEC) $$i $(ROOT)/usr/bin/ ; \
 		done
+ifneq ($(findstring -DUSE_PAM,$(CPPFLAGS)),)
+		$(INSTALL_DIR) $(ROOT)$(PAMDOTD)
+		test -s $(ROOT)$(PAMINIT) || \
+		$(INSTALL_DATA) init.sample $(ROOT)$(PAMINIT)
+endif
 		# $(INSTALL_DIR) $(ROOT)/etc/
 		# $(INSTALL_EXEC) initscript.sample $(ROOT)/etc/
 		ln -sf halt $(ROOT)/sbin/reboot
--- src/init.c
+++ src/init.c	2010-04-13 00:00:00.000000000 +0000
@@ -79,6 +79,10 @@
 #include "reboot.h"
 #include "set.h"
 
+#ifdef USE_PAM
+extern void notify_pam_dead_session(const char *id);
+#endif
+
 #ifndef SIGPWR
 #  define SIGPWR SIGUSR2
 #endif
@@ -1132,6 +1136,9 @@ pid_t spawn(CHILD *ch, int *res)
 			}
 			dup(f);
 			dup(f);
+#ifdef USE_PAM
+			notify_pam_dead_session(ch->id);
+#endif
 		}
 
 		/*
@@ -1551,6 +1558,9 @@ void read_inittab(void)
 		    INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
 				ch->pid, ch->id);
 		    ch->flags &= ~RUNNING;
+#ifdef USE_PAM
+		    notify_pam_dead_session(ch->id);
+#endif
 		    if (ch->process[0] != '+')
 		    	write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 		}
@@ -2012,6 +2022,9 @@ void re_exec(void)
 	    if (ch->flags & ZOMBIE) {
 		INITDBG(L_VB, "Child died, PID= %d", ch->pid);
 		ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
+#ifdef USE_PAM
+		notify_pam_dead_session(ch->id);
+#endif
 		if (ch->process[0] != '+')
 			write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 	    }
@@ -2465,6 +2478,9 @@ void process_signals()
 	    if (ch->flags & ZOMBIE) {
 		INITDBG(L_VB, "Child died, PID= %d", ch->pid);
 		ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
+#ifdef USE_PAM
+		notify_pam_dead_session(ch->id);
+#endif
 		if (ch->process[0] != '+')
 			write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 	    }
--- src/init.sample
+++ src/init.sample	2010-04-13 00:00:00.000000000 +0000
@@ -0,0 +1,8 @@
+#%PAM-1.0
+#
+# The PAM configuration file for /sbin/init
+# Used for updating the lastlog logging file
+#
+auth	    sufficient	pam_rootok.so
+account	    include	common-account
+session	    requisite	pam_lastlog.so silent
--- src/utmp.c
+++ src/utmp.c	2010-04-13 00:00:00.000000000 +0000
@@ -34,10 +34,18 @@
 #include <string.h>
 #include <utmp.h>
 
+#if defined(USE_PAM) && defined(INIT_MAIN)
+#  include <security/pam_appl.h>
+#  include <security/pam_misc.h>
+#endif
+
 #include "init.h"
 #include "initreq.h"
 #include "paths.h"
 
+#ifndef _PATH_DEV
+# define _PATH_DEV	"/dev/"
+#endif
 
 #if defined(__GLIBC__)
 #  if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) && defined(__powerpc__)
@@ -127,9 +135,9 @@ char *line)			/* Which line is this */
 	strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
 	strncpy(utmp.ut_id  , id  , sizeof(utmp.ut_id  ));
 	strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
-        
-        /* Put the OS version in place of the hostname */
-        if (uname(&uname_buf) == 0)
+	
+	/* Put the OS version in place of the hostname */
+	if (uname(&uname_buf) == 0)
 		strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
 
 #if HAVE_UPDWTMP
@@ -262,3 +270,75 @@ char *line)			/* LINE if used. */
 	write_wtmp(user, id, pid, type, line && line[0] ? line : oldline);
 }
 
+#if defined(USE_PAM) && defined(INIT_MAIN)
+static pam_handle_t *pamh = NULL;
+# ifdef __GNUC__
+static int
+null_conv(int num_msg, const struct pam_message **msgm,
+	  struct pam_response **response __attribute__((unused)),
+	  void *appdata_ptr __attribute__((unused)))
+# else
+static int
+null_conv(int num_msg, const struct pam_message **msgm,
+	  struct pam_response **response, void *appdata_ptr)
+# endif
+{
+	int i;
+	for (i = 0; i < num_msg; i++) {
+		const struct pam_message *msg = msgm[i];
+		if (msg == (const struct pam_message*)0)
+			continue;
+		if (msg->msg == (char*)0)
+			continue;
+		switch (msg->msg_style) {
+		case PAM_ERROR_MSG:
+		case PAM_TEXT_INFO:
+			initlog(L_VB, "pam_message %s", msg->msg);
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+static const struct pam_conv conv = { null_conv, NULL };
+# define PAM_FAIL_CHECK(func, args...)  \
+	{ \
+		if ((pam_ret = (func)(args)) != PAM_SUCCESS) { \
+			initlog(L_VB, "%s", pam_strerror(pamh, pam_ret)); \
+			goto pam_error; \
+		} \
+	}
+
+void notify_pam_dead_session(const char *id)
+{
+	struct utmp *oldut, ut;
+
+	setutent();
+
+	memset(&ut, 0, sizeof(ut));
+	ut.ut_type = DEAD_PROCESS;
+	strncpy(ut.ut_id, id, sizeof(ut.ut_id));
+
+	if ((oldut = getutid(&ut)) && (oldut->ut_type == USER_PROCESS)) {
+		int pam_ret;
+		char tty[UT_LINESIZE+ strlen(_PATH_DEV) + 1];
+
+		if (strncmp(oldut->ut_line, _PATH_DEV, strlen(_PATH_DEV)))
+			snprintf(tty, sizeof(tty), _PATH_DEV "%.*s",
+				 UT_LINESIZE, oldut->ut_line);
+		else
+			snprintf(tty, sizeof(tty), "%.*s",
+				 UT_LINESIZE, oldut->ut_line);
+
+		PAM_FAIL_CHECK(pam_start, "init", oldut->ut_user, &conv, &pamh);
+		PAM_FAIL_CHECK(pam_set_item, pamh, PAM_TTY, tty);
+		PAM_FAIL_CHECK(pam_set_item, pamh, PAM_RHOST, oldut->ut_host);
+		PAM_FAIL_CHECK(pam_close_session, pamh, PAM_SILENT);
+	pam_error:
+		pam_end(pamh, pam_ret);
+	}
+
+	endutent();
+}
+#endif /* USE_PAM && INIT_MAIN */
+