Ondrej Vasik edc268
diff -urNp coreutils-8.4-orig/configure.ac coreutils-8.4/configure.ac
Ondrej Vasik edc268
--- coreutils-8.4-orig/configure.ac	2010-01-11 18:20:42.000000000 +0100
Ondrej Vasik edc268
+++ coreutils-8.4/configure.ac	2010-02-12 10:17:46.000000000 +0100
Ondrej Vasik c77f9b
@@ -126,6 +126,13 @@ if test "$gl_gcc_warnings" = yes; then
Ondrej Vasik c77f9b
   AC_SUBST([GNULIB_WARN_CFLAGS])
Ondrej Vasik f8d3fd
 fi
Ondrej Vasik f8d3fd
 
Ondrej Vasik f8d3fd
+dnl Give the chance to enable PAM
Ondrej Vasik f8d3fd
+AC_ARG_ENABLE(pam, dnl
Ondrej Vasik f8d3fd
+[  --enable-pam              Enable use of the PAM libraries],
Ondrej Vasik f8d3fd
+[AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM])
Ondrej Vasik f8d3fd
+LIB_PAM="-ldl -lpam -lpam_misc"
Ondrej Vasik f8d3fd
+AC_SUBST(LIB_PAM)])
Ondrej Vasik f8d3fd
+
Ondrej Vasik f8d3fd
 AC_FUNC_FORK
Ondrej Vasik f8d3fd
 
Ondrej Vasik f8d3fd
 optional_bin_progs=
Ondrej Vasik edc268
diff -urNp coreutils-8.4-orig/doc/coreutils.texi coreutils-8.4/doc/coreutils.texi
Ondrej Vasik edc268
--- coreutils-8.4-orig/doc/coreutils.texi	2010-01-03 18:06:20.000000000 +0100
Ondrej Vasik edc268
+++ coreutils-8.4/doc/coreutils.texi	2010-02-12 10:17:46.000000000 +0100
Ondrej Vasik edc268
@@ -15081,8 +15081,11 @@ to certain shells, etc.).
Ondrej Vasik f8d3fd
 @findex syslog
Ondrej Vasik f8d3fd
 @command{su} can optionally be compiled to use @code{syslog} to report
Ondrej Vasik 66a4fe
 failed, and optionally successful, @command{su} attempts.  (If the system
Ondrej Vasik 66a4fe
-supports @code{syslog}.)  However, GNU @command{su} does not check if the
Ondrej Vasik 66a4fe
-user is a member of the @code{wheel} group; see below.
Ondrej Vasik 66a4fe
+supports @code{syslog}.)
Ondrej Vasik f8d3fd
+
Ondrej Vasik 66a4fe
+This version of @command{su} has support for using PAM for
Ondrej Vasik 66a4fe
+authentication.  You can edit @file{/etc/pam.d/su} to customize its
Ondrej Vasik 66a4fe
+behaviour.
Ondrej Vasik 66a4fe
 
Ondrej Vasik 66a4fe
 The program accepts the following options.  Also see @ref{Common options}.
Ondrej Vasik 66a4fe
 
Ondrej Vasik edc268
@@ -15124,6 +15127,8 @@ environment variables except @env{TERM},
Ondrej Vasik 66a4fe
 @env{PATH} to a compiled-in default value.  Change to @var{user}'s home
Ondrej Vasik 66a4fe
 directory.  Prepend @samp{-} to the shell's name, intended to make it
Ondrej Vasik 66a4fe
 read its login startup file(s).
Ondrej Vasik 66a4fe
+Additionaly @env{DISPLAY} and @env{XAUTHORITY} environment variables 
Ondrej Vasik 66a4fe
+are preserved as well for PAM functionality.
Ondrej Vasik 66a4fe
 
Ondrej Vasik 66a4fe
 @item -m
Ondrej Vasik 66a4fe
 @itemx -p
Ondrej Vasik edc268
@@ -15163,33 +15168,6 @@ Exit status:
Ondrej Vasik 66a4fe
 the exit status of the subshell otherwise
Ondrej Vasik 66a4fe
 @end display
Ondrej Vasik 66a4fe
 
Ondrej Vasik 66a4fe
-@cindex wheel group, not supported
Ondrej Vasik 66a4fe
-@cindex group wheel, not supported
Ondrej Vasik 66a4fe
-@cindex fascism
Ondrej Vasik 66a4fe
-@subsection Why GNU @command{su} does not support the @samp{wheel} group
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
-(This section is by Richard Stallman.)
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
-@cindex Twenex
Ondrej Vasik 66a4fe
-@cindex MIT AI lab
Ondrej Vasik 66a4fe
-Sometimes a few of the users try to hold total power over all the
Ondrej Vasik 66a4fe
-rest.  For example, in 1984, a few users at the MIT AI lab decided to
Ondrej Vasik 66a4fe
-seize power by changing the operator password on the Twenex system and
Ondrej Vasik 66a4fe
-keeping it secret from everyone else.  (I was able to thwart this coup
Ondrej Vasik 66a4fe
-and give power back to the users by patching the kernel, but I
Ondrej Vasik 66a4fe
-wouldn't know how to do that in Unix.)
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
-However, occasionally the rulers do tell someone.  Under the usual
Ondrej Vasik 66a4fe
-@command{su} mechanism, once someone learns the root password who
Ondrej Vasik 66a4fe
-sympathizes with the ordinary users, he or she can tell the rest.  The
Ondrej Vasik 66a4fe
-``wheel group'' feature would make this impossible, and thus cement the
Ondrej Vasik 66a4fe
-power of the rulers.
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
-I'm on the side of the masses, not that of the rulers.  If you are
Ondrej Vasik 66a4fe
-used to supporting the bosses and sysadmins in whatever they do, you
Ondrej Vasik 66a4fe
-might find this idea strange at first.
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
-
Ondrej Vasik 66a4fe
 @node timeout invocation
Ondrej Vasik 66a4fe
 @section @command{timeout}: Run a command with a time limit
Ondrej Vasik 66a4fe
 
Ondrej Vasik edc268
diff -urNp coreutils-8.4-orig/src/Makefile.am coreutils-8.4/src/Makefile.am
Ondrej Vasik edc268
--- coreutils-8.4-orig/src/Makefile.am	2010-01-03 18:06:20.000000000 +0100
Ondrej Vasik edc268
+++ coreutils-8.4/src/Makefile.am	2010-02-12 10:17:46.000000000 +0100
Ondrej Vasik edc268
@@ -361,7 +361,7 @@ factor_LDADD += $(LIB_GMP)
Ondrej Vasik c77f9b
 uptime_LDADD += $(GETLOADAVG_LIBS)
cvsdist 5adf0d
 
Ondrej Vasik c77f9b
 # for crypt
Ondrej Vasik c77f9b
-su_LDADD += $(LIB_CRYPT)
Ondrej Vasik c77f9b
+su_LDADD += $(LIB_CRYPT) @LIB_PAM@
cvsdist 5adf0d
 
Ondrej Vasik c77f9b
 # for various ACL functions
Ondrej Vasik c77f9b
 copy_LDADD += $(LIB_ACL)
Ondrej Vasik edc268
diff -urNp coreutils-8.4-orig/src/su.c coreutils-8.4/src/su.c
Ondrej Vasik edc268
--- coreutils-8.4-orig/src/su.c	2010-02-12 10:15:15.000000000 +0100
Ondrej Vasik edc268
+++ coreutils-8.4/src/su.c	2010-02-12 10:24:29.000000000 +0100
Ondrej Vasik f8d3fd
@@ -37,6 +37,16 @@
cvsdist 5adf0d
    restricts who can su to UID 0 accounts.  RMS considers that to
cvsdist 5adf0d
    be fascist.
cvsdist 5adf0d
 
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+
cvsdist 5adf0d
+   Actually, with PAM, su has nothing to do with whether or not a
cvsdist 5adf0d
+   wheel group is enforced by su.  RMS tries to restrict your access
cvsdist 5adf0d
+   to a su which implements the wheel group, but PAM considers that
cvsdist 5adf0d
+   to be fascist, and gives the user/sysadmin the opportunity to
cvsdist 5adf0d
+   enforce a wheel group by proper editing of /etc/pam.conf
cvsdist 5adf0d
+
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
+
Tim Waugh d66c4d
    Compile-time options:
Tim Waugh d66c4d
    -DSYSLOG_SUCCESS	Log successful su's (by default, to root) with syslog.
Tim Waugh d66c4d
    -DSYSLOG_FAILURE	Log failed su's (by default, to root) with syslog.
Ondrej Vasik f8d3fd
@@ -53,6 +63,15 @@
Ondrej Vasik f8d3fd
 #include <pwd.h>
Ondrej Vasik f8d3fd
 #include <grp.h>
cvsdist 5adf0d
 
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+# include <signal.h>
cvsdist 5adf0d
+# include <sys/wait.h>
cvsdist 5adf0d
+# include <sys/fsuid.h>
Tim Waugh e87740
+# include <unistd.h>
Tim Waugh 3dd4af
+# include <security/pam_appl.h>
Tim Waugh 3dd4af
+# include <security/pam_misc.h>
cvsdist 5adf0d
+#endif /* USE_PAM */
cvsdist 5adf0d
+
cvsdist 5adf0d
 #include "system.h"
Tim Waugh d66c4d
 #include "getpass.h"
cvsdist 5adf0d
 
Ondrej Vasik c77f9b
@@ -120,10 +139,17 @@
cvsdist 5adf0d
 /* The user to become if none is specified.  */
cvsdist 5adf0d
 #define DEFAULT_USER "root"
cvsdist 5adf0d
 
cvsdist 5adf0d
+#ifndef USE_PAM
Ondrej Vasik c4b1fe
 char *crypt (char const *key, char const *salt);
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
 
Tim Waugh c3e4c8
-static void run_shell (char const *, char const *, char **, size_t)
Tim Waugh c3e4c8
+static void run_shell (char const *, char const *, char **, size_t,
Tim Waugh c3e4c8
+	const struct passwd *)
cvsdist 5adf0d
+#ifdef USE_PAM
Tim Waugh c3e4c8
+	;
cvsdist 5adf0d
+#else
cvsdist 5adf0d
      ATTRIBUTE_NORETURN;
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
 
Ondrej Vasik e18e41
 /* If true, pass the `-f' option to the subshell.  */
Ondrej Vasik e18e41
 static bool fast_startup;
Ondrej Vasik c77f9b
@@ -209,7 +235,26 @@ log_su (struct passwd const *pw, bool su
cvsdist 5adf0d
 }
cvsdist 5adf0d
 #endif
cvsdist 5adf0d
 
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+static pam_handle_t *pamh = NULL;
cvsdist 5adf0d
+static int retval;
cvsdist 5adf0d
+static struct pam_conv conv = {
cvsdist 5adf0d
+  misc_conv,
cvsdist 5adf0d
+  NULL
cvsdist 5adf0d
+};
cvsdist 5adf0d
+
cvsdist 5adf0d
+#define PAM_BAIL_P if (retval) { \
cvsdist 5adf0d
+  pam_end(pamh, PAM_SUCCESS); \
cvsdist 5adf0d
+  return 0; \
cvsdist 5adf0d
+}
Tim Waugh ee719b
+#define PAM_BAIL_P_VOID if (retval) {		\
Tim Waugh ee719b
+  pam_end(pamh, PAM_SUCCESS);			\
Tim Waugh ee719b
+return;						\
Tim Waugh ee719b
+}
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
+
cvsdist 5adf0d
 /* Ask the user for a password.
cvsdist 5adf0d
+   If PAM is in use, let PAM ask for the password if necessary.
Tim Waugh c3e4c8
    Return true if the user gives the correct password for entry PW,
Tim Waugh c3e4c8
    false if not.  Return true without asking for a password if run by UID 0
cvsdist 5adf0d
    or if PW has an empty password.  */
Ondrej Vasik c77f9b
@@ -217,6 +262,44 @@ log_su (struct passwd const *pw, bool su
Tim Waugh c3e4c8
 static bool
cvsdist 5adf0d
 correct_password (const struct passwd *pw)
cvsdist 5adf0d
 {
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+  struct passwd *caller;
Tim Waugh e87740
+  char *tty_name, *ttyn;
cvsdist 5adf0d
+  retval = pam_start(PROGRAM_NAME, pw->pw_name, &conv, &pamh);
cvsdist 5adf0d
+  PAM_BAIL_P;
cvsdist 5adf0d
+
cvsdist 5adf0d
+  if (getuid() != 0 && !isatty(0)) {
cvsdist 5adf0d
+	fprintf(stderr, "standard in must be a tty\n");
cvsdist 5adf0d
+	exit(1);
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+
cvsdist 5adf0d
+  caller = getpwuid(getuid());
cvsdist 5adf0d
+  if(caller != NULL && caller->pw_name != NULL) {
cvsdist 5adf0d
+	  retval = pam_set_item(pamh, PAM_RUSER, caller->pw_name);
cvsdist 5adf0d
+	  PAM_BAIL_P;
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+
Tim Waugh e87740
+  ttyn = ttyname(0);
Tim Waugh f1ce78
+  if (ttyn) {
Tim Waugh f1ce78
+    if (strncmp(ttyn, "/dev/", 5) == 0)
Tim Waugh e87740
+       tty_name = ttyn+5;
Tim Waugh f1ce78
+    else
Tim Waugh e87740
+       tty_name = ttyn;
Tim Waugh f1ce78
+    retval = pam_set_item(pamh, PAM_TTY, tty_name);
Tim Waugh f1ce78
+    PAM_BAIL_P;
Tim Waugh f1ce78
+  }
cvsdist 5adf0d
+  retval = pam_authenticate(pamh, 0);
cvsdist 5adf0d
+  PAM_BAIL_P;
cvsdist 5adf0d
+  retval = pam_acct_mgmt(pamh, 0);
cvsdist 5adf0d
+  if (retval == PAM_NEW_AUTHTOK_REQD) {
cvsdist 5adf0d
+    /* password has expired.  Offer option to change it. */
cvsdist 5adf0d
+    retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
cvsdist 5adf0d
+    PAM_BAIL_P;
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+  PAM_BAIL_P;
cvsdist 5adf0d
+  /* must be authenticated if this point was reached */
cvsdist 5adf0d
+  return 1;
cvsdist 5adf0d
+#else /* !USE_PAM */
cvsdist 5adf0d
   char *unencrypted, *encrypted, *correct;
cvsdist 5adf0d
 #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
cvsdist 5adf0d
   /* Shadow passwd stuff for SVR3 and maybe other systems.  */
Ondrej Vasik c77f9b
@@ -241,6 +324,7 @@ correct_password (const struct passwd *p
cvsdist 5adf0d
   encrypted = crypt (unencrypted, correct);
cvsdist 5adf0d
   memset (unencrypted, 0, strlen (unencrypted));
Tim Waugh c3e4c8
   return STREQ (encrypted, correct);
cvsdist 5adf0d
+#endif /* !USE_PAM */
cvsdist 5adf0d
 }
cvsdist 5adf0d
 
cvsdist 5adf0d
 /* Update `environ' for the new shell based on PW, with SHELL being
Ondrej Vasik c77f9b
@@ -254,12 +338,18 @@ modify_environment (const struct passwd 
Tim Waugh c3e4c8
       /* Leave TERM unchanged.  Set HOME, SHELL, USER, LOGNAME, PATH.
cvsdist 5adf0d
          Unset all other environment variables.  */
Tim Waugh c3e4c8
       char const *term = getenv ("TERM");
Tim Waugh c3e4c8
+      char const *display = getenv ("DISPLAY");
Tim Waugh c3e4c8
+      char const *xauthority = getenv ("XAUTHORITY");
Tim Waugh c3e4c8
       if (term)
Ondrej Vasik 250517
         term = xstrdup (term);
Tim Waugh c3e4c8
       environ = xmalloc ((6 + !!term) * sizeof (char *));
Tim Waugh c3e4c8
       environ[0] = NULL;
cvsdist 5adf0d
       if (term)
Ondrej Vasik 250517
         xsetenv ("TERM", term);
cvsdist 5adf0d
+      if (display)
Ondrej Vasik 250517
+        xsetenv ("DISPLAY", display);
cvsdist 5adf0d
+      if (xauthority)
Ondrej Vasik 250517
+        xsetenv ("XAUTHORITY", xauthority);
Tim Waugh c3e4c8
       xsetenv ("HOME", pw->pw_dir);
Tim Waugh c3e4c8
       xsetenv ("SHELL", shell);
Tim Waugh c3e4c8
       xsetenv ("USER", pw->pw_name);
Ondrej Vasik c77f9b
@@ -292,8 +382,13 @@ change_identity (const struct passwd *pw
Tim Waugh e87740
 {
Tim Waugh e87740
 #ifdef HAVE_INITGROUPS
Tim Waugh e87740
   errno = 0;
Tim Waugh e87740
-  if (initgroups (pw->pw_name, pw->pw_gid) == -1)
Tim Waugh e87740
+  if (initgroups (pw->pw_name, pw->pw_gid) == -1) {
Tim Waugh e87740
+#ifdef USE_PAM
Tim Waugh e87740
+    pam_close_session(pamh, 0);
Tim Waugh e87740
+    pam_end(pamh, PAM_ABORT);
Tim Waugh e87740
+#endif
Ondrej Vasik c77f9b
     error (EXIT_CANCELED, errno, _("cannot set groups"));
Tim Waugh e87740
+  }
cvsdist 5adf0d
   endgrent ();
cvsdist 5adf0d
 #endif
cvsdist 5adf0d
   if (setgid (pw->pw_gid))
Ondrej Vasik c77f9b
@@ -302,6 +397,31 @@ change_identity (const struct passwd *pw
Ondrej Vasik c77f9b
     error (EXIT_CANCELED, errno, _("cannot set user id"));
cvsdist 5adf0d
 }
cvsdist 5adf0d
 
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+static int caught=0;
cvsdist 5adf0d
+/* Signal handler for parent process later */
cvsdist 5adf0d
+static void su_catch_sig(int sig)
cvsdist 5adf0d
+{
cvsdist 5adf0d
+  ++caught;
cvsdist 5adf0d
+}
cvsdist 5adf0d
+
cvsdist 5adf0d
+int
cvsdist 5adf0d
+pam_copyenv (pam_handle_t *pamh)
cvsdist 5adf0d
+{
cvsdist 5adf0d
+  char **env;
cvsdist 5adf0d
+
cvsdist 5adf0d
+  env = pam_getenvlist(pamh);
cvsdist 5adf0d
+  if(env) {
cvsdist 5adf0d
+    while(*env) {
Tim Waugh c3e4c8
+	if (putenv (*env))
Tim Waugh c3e4c8
+	  xalloc_die ();
cvsdist 5adf0d
+	env++;
cvsdist 5adf0d
+    }
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+  return(0);
cvsdist 5adf0d
+}
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
+
cvsdist 5adf0d
 /* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
cvsdist 5adf0d
    If COMMAND is nonzero, pass it to the shell with the -c option.
Tim Waugh c3e4c8
    Pass ADDITIONAL_ARGS to the shell as more arguments; there
Ondrej Vasik c77f9b
@@ -309,17 +429,49 @@ change_identity (const struct passwd *pw
cvsdist 5adf0d
 
cvsdist 5adf0d
 static void
Tim Waugh c3e4c8
 run_shell (char const *shell, char const *command, char **additional_args,
Ondrej Vasik 250517
-           size_t n_additional_args)
Ondrej Vasik 250517
+           size_t n_additional_args, const struct passwd *pw)
cvsdist 5adf0d
 {
Tim Waugh c3e4c8
   size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
Tim Waugh c3e4c8
   char const **args = xnmalloc (n_args, sizeof *args);
Tim Waugh c3e4c8
   size_t argno = 1;
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+  int child;
cvsdist 5adf0d
+  sigset_t ourset;
cvsdist 5adf0d
+  int status;
cvsdist 5adf0d
+
cvsdist 5adf0d
+  retval = pam_open_session(pamh,0);
cvsdist 5adf0d
+  if (retval != PAM_SUCCESS) {
cvsdist 5adf0d
+    fprintf (stderr, "could not open session\n");
cvsdist 5adf0d
+    exit (1);
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+
cvsdist 5adf0d
+/* do this at the last possible moment, because environment variables may
cvsdist 5adf0d
+   be passed even in the session phase
cvsdist 5adf0d
+*/
cvsdist 5adf0d
+  if(pam_copyenv(pamh) != PAM_SUCCESS)
cvsdist 5adf0d
+     fprintf (stderr, "error copying PAM environment\n");
cvsdist 5adf0d
+  
Tim Waugh e87740
+  /* Credentials should be set in the parent */ 
Tim Waugh e87740
+  if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
Tim Waugh e87740
+    pam_close_session(pamh, 0);
Tim Waugh e87740
+    fprintf(stderr, "could not set PAM credentials\n");
Tim Waugh e87740
+    exit(1);
Tim Waugh e87740
+  }
Tim Waugh e87740
+
cvsdist 5adf0d
+  child = fork();
cvsdist 5adf0d
+  if (child == 0) {  /* child shell */
cvsdist 5adf0d
+  change_identity (pw);
cvsdist 5adf0d
+  pam_end(pamh, 0);
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
 
Tim Waugh c3e4c8
   if (simulate_login)
Tim Waugh c3e4c8
     {
cvsdist 5adf0d
       char *arg0;
cvsdist 5adf0d
       char *shell_basename;
cvsdist 5adf0d
 
cvsdist 5adf0d
+      if(chdir(pw->pw_dir))
cvsdist 5adf0d
+	      error(0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
cvsdist 5adf0d
+
Tim Waugh d66c4d
       shell_basename = last_component (shell);
cvsdist 5adf0d
       arg0 = xmalloc (strlen (shell_basename) + 2);
cvsdist 5adf0d
       arg0[0] = '-';
Ondrej Vasik edc268
@@ -344,6 +496,67 @@ run_shell (char const *shell, char const
cvsdist 5adf0d
     error (0, errno, "%s", shell);
cvsdist 5adf0d
     exit (exit_status);
cvsdist 5adf0d
   }
cvsdist 5adf0d
+#ifdef USE_PAM
cvsdist 5adf0d
+  } else if (child == -1) {
cvsdist 5adf0d
+      fprintf(stderr, "can not fork user shell: %s", strerror(errno));
Tim Waugh e87740
+      pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
Tim Waugh e87740
+      pam_close_session(pamh, 0);
Tim Waugh e87740
+      pam_end(pamh, PAM_ABORT);
cvsdist 5adf0d
+      exit(1);
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+  /* parent only */
cvsdist 5adf0d
+  sigfillset(&ourset);
cvsdist 5adf0d
+  if (sigprocmask(SIG_BLOCK, &ourset, NULL)) {
cvsdist 5adf0d
+    fprintf(stderr, "%s: signal malfunction\n", PROGRAM_NAME);
cvsdist 5adf0d
+    caught = 1;
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+  if (!caught) {
cvsdist 5adf0d
+    struct sigaction action;
cvsdist 5adf0d
+    action.sa_handler = su_catch_sig;
cvsdist 5adf0d
+    sigemptyset(&action.sa_mask);
cvsdist 5adf0d
+    action.sa_flags = 0;
cvsdist 5adf0d
+    sigemptyset(&ourset);
cvsdist 5adf0d
+    if (sigaddset(&ourset, SIGTERM)
cvsdist 5adf0d
+        || sigaddset(&ourset, SIGALRM)
cvsdist 5adf0d
+        || sigaction(SIGTERM, &action, NULL)
cvsdist 5adf0d
+        || sigprocmask(SIG_UNBLOCK, &ourset, NULL)) {
cvsdist 5adf0d
+      fprintf(stderr, "%s: signal masking malfunction\n", PROGRAM_NAME);
cvsdist 5adf0d
+      caught = 1;
cvsdist 5adf0d
+    }
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+  if (!caught) {
cvsdist 5adf0d
+    do {
cvsdist 5adf0d
+      int pid;
cvsdist 5adf0d
+
cvsdist 5adf0d
+      pid = waitpid(-1, &status, WUNTRACED);
cvsdist 5adf0d
+
Ondrej Vasik edc268
+      if (((pid_t)-1 != pid) && (0 != WIFSTOPPED (status))) {
Ondrej Vasik edc268
+          kill(getpid(), WSTOPSIG(status));
cvsdist 5adf0d
+          /* once we get here, we must have resumed */
cvsdist 5adf0d
+          kill(pid, SIGCONT);
cvsdist 5adf0d
+      }
Ondrej Vasik edc268
+    } while (0 != WIFSTOPPED(status));
cvsdist 5adf0d
+  }
cvsdist 5adf0d
+
cvsdist 5adf0d
+  if (caught) {
cvsdist 5adf0d
+    fprintf(stderr, "\nSession terminated, killing shell...");
cvsdist 5adf0d
+    kill (child, SIGTERM);
cvsdist 5adf0d
+  }
Tim Waugh e87740
+  /* Not checking retval on this because we need to call close session */
Tim Waugh e87740
+  pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
cvsdist 5adf0d
+  retval = pam_close_session(pamh, 0);
Tim Waugh ee719b
+  PAM_BAIL_P_VOID;
cvsdist 5adf0d
+  retval = pam_end(pamh, PAM_SUCCESS);
Tim Waugh ee719b
+  PAM_BAIL_P_VOID;
cvsdist 5adf0d
+  if (caught) {
cvsdist 5adf0d
+    sleep(2);
cvsdist 5adf0d
+    kill(child, SIGKILL);
cvsdist 5adf0d
+    fprintf(stderr, " ...killed.\n");
cvsdist 5adf0d
+    exit(-1);
cvsdist 5adf0d
+  }
Ondrej Vasik edc268
+  exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status)
Ondrej Vasik edc268
+                                  : WTERMSIG (status) + 128);
cvsdist 5adf0d
+#endif /* USE_PAM */
cvsdist 5adf0d
 }
cvsdist 5adf0d
 
Tim Waugh c3e4c8
 /* Return true if SHELL is a restricted shell (one not returned by
Ondrej Vasik edc268
@@ -511,9 +724,9 @@ main (int argc, char **argv)
Tim Waugh d66c4d
   shell = xstrdup (shell ? shell : pw->pw_shell);
Tim Waugh d66c4d
   modify_environment (pw, shell);
cvsdist 5adf0d
 
Tim Waugh a2135b
+#ifndef USE_PAM
cvsdist 5adf0d
   change_identity (pw);
Tim Waugh e6a660
-  if (simulate_login && chdir (pw->pw_dir) != 0)
Tim Waugh e6a660
-    error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
cvsdist 5adf0d
+#endif
cvsdist 5adf0d
 
Ondrej Vasik c77f9b
   /* error() flushes stderr, but does not check for write failure.
Ondrej Vasik c77f9b
      Normally, we would catch this via our atexit() hook of
Ondrej Vasik edc268
@@ -523,5 +736,5 @@ main (int argc, char **argv)
Ondrej Vasik c77f9b
   if (ferror (stderr))
Ondrej Vasik c77f9b
     exit (EXIT_CANCELED);
Ondrej Vasik c77f9b
 
Tim Waugh c3e4c8
-  run_shell (shell, command, argv + optind, MAX (0, argc - optind));
Tim Waugh c3e4c8
+  run_shell (shell, command, argv + optind, MAX (0, argc - optind), pw);
cvsdist 5adf0d
 }