[packages/util-linux] - up to 2.23.1; initrd build broken, rest builds fine
arekm
arekm at pld-linux.org
Tue Jun 18 20:38:29 CEST 2013
commit 232bdb1aa2ccb366530735e18678f22ef68813fa
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Tue Jun 18 20:38:26 2013 +0200
- up to 2.23.1; initrd build broken, rest builds fine
util-linux-diet.patch | 47 +-
util-linux-runuser.patch | 1957 ----------------------------------------------
util-linux.spec | 80 +-
3 files changed, 45 insertions(+), 2039 deletions(-)
---
diff --git a/util-linux.spec b/util-linux.spec
index 2951ae7..3adc416 100644
--- a/util-linux.spec
+++ b/util-linux.spec
@@ -35,12 +35,12 @@ Summary(ru.UTF-8): Набор базовых системных утилит д
Summary(tr.UTF-8): Temel sistem araçları
Summary(uk.UTF-8): Набір базових системних утиліт для Linux
Name: util-linux
-Version: 2.22.2
-Release: 6
+Version: 2.23.1
+Release: 0.1
License: GPL
Group: Applications/System
-Source0: https://www.kernel.org/pub/linux/utils/util-linux/v2.22/%{name}-%{version}.tar.xz
-# Source0-md5: eeacbfdd2556acd899a2d0ffdb446185
+Source0: https://www.kernel.org/pub/linux/utils/util-linux/v2.23/%{name}-%{version}.tar.xz
+# Source0-md5: 33ba55ce82f8e3b8d7a38fac0f62779a
Source1: http://www.mif.pg.gda.pl/homepages/ankry/man-PLD/%{name}-non-english-man-pages.tar.bz2
# Source1-md5: 3c940c7e7fe699eaa2ddb1bffb3de2fe
Source2: login.pamd
@@ -55,7 +55,7 @@ Source10: nologin.c
Source11: nologin.8
Patch0: %{name}-pl.po-update.patch
Patch1: %{name}-ng-union-mount.patch
-Patch2: %{name}-runuser.patch
+
Patch3: %{name}-fdformat-ide.patch
Patch4: %{name}-fhs.patch
Patch5: %{name}-hotkeys.patch
@@ -63,7 +63,6 @@ Patch7: %{name}-login-lastlog.patch
Patch8: %{name}-procpartitions.patch
Patch9: su-paths.patch
Patch10: %{name}-diet.patch
-Patch11: https://github.com/karelzak/util-linux/commit/38db00f17824f41679c99a6c711a11e4585a0484.patch
# Patch11-md5: 2a37a871117466841edb3e8be692825b
URL: http://userweb.kernel.org/~kzak/util-linux/
BuildRequires: audit-libs-devel >= 1.0.6
@@ -112,6 +111,7 @@ Obsoletes: rawdevices
Obsoletes: schedutils
Obsoletes: setarch
Obsoletes: sparc32
+Obsoletes: util-linux-chkdupexe
Obsoletes: util-linux-ng < 2.20-1
Obsoletes: util-linux-suids
Conflicts: SysVinit < 2.86-26
@@ -343,22 +343,6 @@ sisteminizin işlevselliği açısından kritiktir.
дерева. Swapon та swapoff, відповідно, дозволяє та заборонює свопінг у
визначені файли або пристрої.
-%package chkdupexe
-Summary: chkdupexe - find duplicate executables
-Summary(pl.UTF-8): chkdupexe odszukuje powtarzające się pliki uruchamialne
-Group: Applications/System
-Obsoletes: util-linux-ng-chkdupexe < 2.20-1
-
-%description chkdupexe
-chkdupexe will scan the union of $PATH and a hardcoded list of common
-locations for binaries. It will report dangling symlinks and
-duplicately-named binaries.
-
-%description chkdupexe -l pl.UTF-8
-chkdupexe przeszukuje katalogi z $PATH oraz inne powszechnie znane
-katalogi z plikami uruchamialnymi i informuje o powtarzających się
-plikach w różnych katalogach.
-
%package -n tunelp
Summary: Configures kernel parallel port driver
Summary(de.UTF-8): Konfiguriert den Kerneltreiber für den parallelen Port
@@ -644,19 +628,31 @@ or UUID - staticaly linked for initrd.
Pakiet ten zawiera narzędzie blkid do rozpoznawania partycji przez
etykietę lub UUID - statycznie skonsolidowane na potrzeby initrd.
+%package -n bash-completion-util-linux
+Summary: bash completion for util-linux
+Summary(pl.UTF-8): Dopełnienia basha dla util-linux
+Group: Applications/Shells
+Requires: %{name} = %{version}-%{release}
+Requires: bash-completion
+
+%description -n bash-completion-util-linux
+Bash completion for util-linux.
+
+%description -n bash-completion-util-linux -l pl.UTF-8
+Dopełnienia basha dla util-linux.
+
%prep
%setup -q -a1
#%patch0 -p1
%patch1 -p1
-%patch2 -p1
+
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
-%patch10 -p1
-%patch11 -p1
+%{?with_initrd:%patch10 -p1}
install %{SOURCE10} nologin.c
@@ -707,6 +703,7 @@ export CPPFLAGS="%{rpmcppflags} -I/usr/include/ncurses -DHAVE_LSEEK64_PROTOTYPE
--disable-silent-rules \
--disable-su \
--disable-sulogin \
+ --disable-tunelp \
--disable-use-tty-group \
--disable-utmpdump \
--disable-uuidd \
@@ -742,8 +739,6 @@ export CPPFLAGS="%{rpmcppflags} -I/usr/include/ncurses -DHAVE_LSEEK64_PROTOTYPE
--disable-use-tty-group \
--disable-wall \
--enable-chfn-chsh \
- --enable-chkdupexe \
- --enable-ddate \
--enable-kill \
--enable-libblkid \
--enable-line \
@@ -754,10 +749,12 @@ export CPPFLAGS="%{rpmcppflags} -I/usr/include/ncurses -DHAVE_LSEEK64_PROTOTYPE
--enable-runuser%{!?with_su:=no} \
--enable-su%{!?with_su:=no} \
--enable-sulogin \
+ --enable-tunelp \
--enable-utmpdump \
--enable-vipw \
--enable-write \
--with-audit \
+ --with-bashcompletiondir=/etc/bash_completion.d \
--with-selinux%{!?with_selinux:=no}
%{__make}
@@ -960,6 +957,7 @@ fi
%attr(755,root,root) /sbin/chcpu
%attr(755,root,root) /sbin/ctrlaltdel
%attr(755,root,root) /sbin/addpart
+%attr(755,root,root) /sbin/blkdiscard
%attr(755,root,root) /sbin/delpart
%attr(755,root,root) /sbin/partx
%attr(755,root,root) /bin/lsblk
@@ -980,7 +978,6 @@ fi
%attr(755,root,root) %{_bindir}/colrm
%attr(755,root,root) %{_bindir}/column
%attr(755,root,root) %{_bindir}/cytune
-%attr(755,root,root) %{_bindir}/ddate
%attr(755,root,root) %{_bindir}/eject
%attr(755,root,root) %{_bindir}/flock
%{?with_fallocate:%attr(755,root,root) %{_bindir}/fallocate}
@@ -998,6 +995,7 @@ fi
%attr(755,root,root) %{_bindir}/lslocks
%attr(755,root,root) %{_bindir}/mcookie
%attr(755,root,root) %{_bindir}/namei
+%attr(755,root,root) %{_bindir}/nsenter
%attr(755,root,root) %{_bindir}/pg
%attr(755,root,root) %{_bindir}/prlimit
%attr(755,root,root) %{_bindir}/raw
@@ -1006,6 +1004,7 @@ fi
%attr(755,root,root) %{_bindir}/rev
%attr(755,root,root) %{_bindir}/script
%attr(755,root,root) %{_bindir}/scriptreplay
+%attr(755,root,root) %{_bindir}/setpriv
%attr(755,root,root) %{_bindir}/setsid
%attr(755,root,root) %{_bindir}/setterm
%attr(755,root,root) %{_bindir}/tailf
@@ -1028,7 +1027,6 @@ fi
%{_mandir}/man1/colcrt.1*
%{_mandir}/man1/colrm.1*
%{_mandir}/man1/column.1*
-%{_mandir}/man1/ddate.1*
%{_mandir}/man1/dmesg.1*
%{_mandir}/man1/eject.1*
%{?with_fallocate:%{_mandir}/man1/fallocate.1*}
@@ -1047,11 +1045,13 @@ fi
%{_mandir}/man1/mcookie.1*
%{_mandir}/man1/more.1*
%{_mandir}/man1/namei.1*
+%{_mandir}/man1/nsenter.1*
%{_mandir}/man1/prlimit.1*
%{_mandir}/man1/pg.1*
%{_mandir}/man1/renice.1*
%{_mandir}/man1/rev.1*
%{_mandir}/man1/rename.1*
+%{_mandir}/man1/setpriv.1*
%{_mandir}/man1/setsid.1*
%{_mandir}/man1/script.1*
%{_mandir}/man1/scriptreplay.1*
@@ -1064,6 +1064,7 @@ fi
%{_mandir}/man1/whereis.1*
%{_mandir}/man1/write.1*
%{_mandir}/man8/addpart.8*
+%{_mandir}/man8/blkdiscard.8*
%{_mandir}/man8/delpart.8*
%{_mandir}/man8/partx.8*
%{_mandir}/man8/lsblk.8*
@@ -1096,7 +1097,6 @@ fi
%lang(es) %{_mandir}/es/man1/colrm.1*
%lang(es) %{_mandir}/es/man1/column.1*
-%lang(es) %{_mandir}/es/man1/ddate.1*
%lang(es) %{_mandir}/es/man1/getopt.1*
%lang(es) %{_mandir}/es/man1/look.1*
%lang(es) %{_mandir}/es/man1/more.1*
@@ -1166,7 +1166,6 @@ fi
%lang(ja) %{_mandir}/ja/man1/colcrt.1*
%lang(ja) %{_mandir}/ja/man1/colrm.1*
%lang(ja) %{_mandir}/ja/man1/column.1*
-%lang(ja) %{_mandir}/ja/man1/ddate.1*
%lang(ja) %{_mandir}/ja/man1/getopt.1*
%lang(ja) %{_mandir}/ja/man1/hexdump.1*
%lang(ja) %{_mandir}/ja/man1/kill.1*
@@ -1200,7 +1199,6 @@ fi
%lang(ko) %{_mandir}/ko/man1/colcrt.1*
%lang(ko) %{_mandir}/ko/man1/colrm.1*
%lang(ko) %{_mandir}/ko/man1/column.1*
-%lang(ko) %{_mandir}/ko/man1/ddate.1*
%lang(ko) %{_mandir}/ko/man1/getopt.1*
%lang(ko) %{_mandir}/ko/man1/hexdump.1*
%lang(ko) %{_mandir}/ko/man1/kill.1*
@@ -1251,8 +1249,6 @@ fi
%lang(pl) %{_mandir}/pl/man8/mkswap.8*
%lang(pl) %{_mandir}/pl/man8/renice.8*
-%lang(ru) %{_mandir}/ru/man1/ddate.1*
-
%attr(755,root,root) /sbin/fdisk
%attr(755,root,root) /sbin/fsck.minix
%attr(755,root,root) /sbin/mkfs.minix
@@ -1314,9 +1310,11 @@ fi
%attr(755,root,root) /sbin/fsck.cramfs
%attr(755,root,root) /sbin/mkfs.cramfs
%attr(755,root,root) /sbin/mkfs.bfs
+%{_mandir}/man8/fsck.cramfs.8*
+%{_mandir}/man8/mkfs.cramfs.8*
%if %{with su}
-%attr(755,root,root) /bin/runuser
+%attr(755,root,root) /sbin/runuser
%attr(4755,root,root) /bin/su
%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/pam.d/runuser
%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/pam.d/runuser-l
@@ -1407,14 +1405,6 @@ fi
%lang(ko) %{_mandir}/ko/man8/losetup.8*
%lang(pl) %{_mandir}/pl/man8/losetup.8*
-%files chkdupexe
-%defattr(644,root,root,755)
-%attr(755,root,root) %{_bindir}/chkdupexe
-%{_mandir}/man1/chkdupexe.1*
-%lang(ja) %{_mandir}/ja/man1/chkdupexe.1*
-%lang(ko) %{_mandir}/ko/man1/chkdupexe.1*
-%lang(pl) %{_mandir}/pl/man1/chkdupexe.1*
-
%files -n tunelp
%defattr(644,root,root,755)
%attr(755,root,root) %{_sbindir}/tunelp
@@ -1486,6 +1476,10 @@ fi
%defattr(644,root,root,755)
%{_libdir}/libuuid.a
+%files -n bash-completion-util-linux
+%defattr(644,root,root,755)
+/etc/bash_completion.d/*
+
%if %{with initrd} && %{with dietlibc}
%files -n libuuid-dietlibc
%defattr(644,root,root,755)
diff --git a/util-linux-diet.patch b/util-linux-diet.patch
index b0085b0..24404a5 100644
--- a/util-linux-diet.patch
+++ b/util-linux-diet.patch
@@ -72,16 +72,16 @@
--- util-linux-2.19/misc-utils/findmnt.c~ 2011-01-31 16:43:47.000000000 +0100
+++ util-linux-2.19/misc-utils/findmnt.c 2011-02-10 20:54:23.100130391 +0100
-@@ -30,6 +30,9 @@
- #include <poll.h>
- #include <sys/statvfs.h>
- #include <sys/types.h>
+@@ -36,6 +36,9 @@
+ # include <libudev.h>
+ #endif
+ #include <libmount.h>
+#ifdef __dietlibc__
+#include <sys/stat.h> /* for major and minor macros */
+#endif
- #include <libmount.h>
-
+ #include "pathnames.h"
+ #include "nls.h"
--- util-linux-2.19/disk-utils/fsck.c~ 2011-02-07 16:19:29.000000000 +0100
+++ util-linux-2.19/disk-utils/fsck.c 2011-02-10 21:09:27.024658725 +0100
@@ -270,7 +270,13 @@
@@ -101,10 +101,10 @@
--- util-linux-2.21/configure.ac~ 2012-02-24 12:53:35.000000000 +0200
+++ util-linux-2.21/configure.ac 2012-03-05 21:03:25.833675080 +0200
-@@ -311,6 +311,7 @@
- lchown \
+@@ -323,6 +323,7 @@ AC_CHECK_FUNCS([ \
llseek \
lseek64 \
+ mempcpy \
+ mkostemp \
nanosleep \
personality \
@@ -144,37 +144,6 @@
if (n <= 0)
return 0;
---- util-linux-2.22.1/lib/Makemodule.am.orig 2012-09-20 15:16:51.344635140 +0200
-+++ util-linux-2.22.1/lib/Makemodule.am 2012-10-13 16:15:53.662070426 +0200
-@@ -5,7 +5,6 @@
- lib/at.c \
- lib/blkdev.c \
- lib/canonicalize.c \
-- lib/cpuset.c \
- lib/crc32.c \
- lib/env.c \
- lib/fileutils.c \
-@@ -15,7 +14,6 @@
- lib/mbsalign.c \
- lib/md5.c \
- lib/pager.c \
-- lib/path.c \
- lib/procutils.c \
- lib/randutils.c \
- lib/setproctitle.c \
-@@ -25,6 +23,12 @@
- lib/wholedisk.c \
- lib/xgetpass.c
-
-+if HAVE_CPU_SET_T
-+libcommon_la_SOURCES += \
-+ lib/cpuset.c \
-+ lib/path.c
-+endif
-+
- if LINUX
- libcommon_la_SOURCES += \
- lib/linux_version.c \
--- util-linux-2.22.1/lib/tt.c.orig 2012-09-20 15:16:51.349635172 +0200
+++ util-linux-2.22.1/lib/tt.c 2012-10-13 16:58:37.331962836 +0200
@@ -59,11 +59,13 @@
diff --git a/util-linux-runuser.patch b/util-linux-runuser.patch
deleted file mode 100644
index 7b885d0..0000000
--- a/util-linux-runuser.patch
+++ /dev/null
@@ -1,1957 +0,0 @@
-diff --git a/configure.ac b/configure.ac
-index 87e85fa..ead559c 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1149,6 +1154,15 @@ UL_REQUIRES_HAVE([su], [security_pam_misc_h], [PAM header file])
- AM_CONDITIONAL(BUILD_SU, test "x$build_su" = xyes)
-
-
-+AC_ARG_ENABLE([runuser],
-+ AS_HELP_STRING([--disable-runuser], [do not build runuser]),
-+ [], enable_runuser=yes
-+)
-+UL_BUILD_INIT([runuser])
-+UL_REQUIRES_HAVE([runuser], [security_pam_misc_h], [PAM header file])
-+AM_CONDITIONAL(BUILD_RUNUSER, test "x$build_runuser" = xyes)
-+
-+
- AC_ARG_ENABLE([schedutils],
- AS_HELP_STRING([--disable-schedutils], [do not build chrt, ionice, teskset]),
- [], enable_schedutils=yes
-diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
-index e10da46..755a361 100644
---- a/login-utils/Makemodule.am
-+++ b/login-utils/Makemodule.am
-@@ -83,6 +83,8 @@
- dist_man_MANS += login-utils/su.1
- su_SOURCES = \
- login-utils/su.c \
-+ login-utils/su-common.c \
-+ login-utils/su-common.h \
- login-utils/logindefs.c \
- login-utils/logindefs.h
- su_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS)
-@@ -91,6 +93,19 @@
- endif
-
-
-+if BUILD_RUNUSER
-+bin_PROGRAMS += runuser
-+dist_man_MANS += login-utils/runuser.1
-+runuser_SOURCES = \
-+ login-utils/runuser.c \
-+ login-utils/su-common.c \
-+ login-utils/su-common.h \
-+ login-utils/logindefs.c \
-+ login-utils/logindefs.h
-+runuser_LDADD = $(LDADD) -lpam -lpam_misc
-+endif
-+
-+
- if BUILD_NEWGRP
- usrbin_exec_PROGRAMS += newgrp
- dist_man_MANS += login-utils/newgrp.1
-diff --git a/login-utils/runuser.1 b/login-utils/runuser.1
-new file mode 100644
-index 0000000..66ad1c4
---- /dev/null
-+++ b/login-utils/runuser.1
-@@ -0,0 +1,230 @@
-+.TH RUNUSER "1" "August 2012" "util-linux" "User Commands"
-+.SH NAME
-+runuser \- run a command with substitute user and group ID
-+.SH SYNOPSIS
-+.B runuser
-+[options...] [\-] [user [args...]]
-+.SH DESCRIPTION
-+.B runuser
-+allows to run commands with substitute user and group ID.
-+The difference between the commands
-+.B runuser
-+and
-+.B su
-+is that
-+.B runuser
-+does not ask for password, because it may be executed by root user only.
-+The command
-+.B runuser
-+does not have to be installed with suid permissions.
-+.PP
-+When called without arguments
-+.B runuser
-+defaults to running an interactive shell as
-+.IR root .
-+.PP
-+For backward compatibility
-+.B runuser
-+defaults to not change the current directory and to only set the
-+environment variables
-+.B HOME
-+and
-+.B SHELL
-+(plus
-+.B USER
-+and
-+.B LOGNAME
-+if the target
-+.I user
-+is not root). It is recommended to always use the
-+.B \-\-login
-+option (instead it's shortcut
-+.BR \- )
-+to avoid side effects caused by mixing environments.
-+.PP
-+This version of
-+.B runuser
-+uses PAM for session management.
-+.SH OPTIONS
-+.TP
-+\fB\-c\fR \fIcommand\fR, \fB\-\-command\fR=\fIcommand\fR
-+Pass
-+.I command
-+to the shell with the
-+.B \-c
-+option.
-+.TP
-+\fB\-\-session\-command\fR=\fIcommand\fR
-+Same as
-+.B \-c
-+but do not create a new session (discouraged).
-+.TP
-+\fB\-f\fR, \fB\-\-fast\fR
-+Pass
-+.B \-f
-+to the shell which may or may not be useful depending on the
-+shell.
-+.TP
-+\fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR
-+specify the primary group, this option is allowed for root user only
-+.TP
-+\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR
-+specify a supplemental group, this option is allowed for root user only
-+.TP
-+\fB\-\fR, \fB\-l\fR, \fB\-\-login\fR
-+Starts the shell as login shell with an environment similar to a real
-+login:
-+.RS 10
-+.TP
-+o
-+clears all environment variables except for
-+.B TERM
-+.TP
-+o
-+initializes the environment variables
-+.BR HOME ,
-+.BR SHELL ,
-+.BR USER ,
-+.BR LOGNAME ,
-+.B PATH
-+.TP
-+o
-+changes to the target user's home directory
-+.TP
-+o
-+sets argv[0] of the shell to
-+.RB ' \- '
-+in order to make the shell a login shell
-+.RE
-+.TP
-+\fB\-m\fR, \fB\-p\fR, \fB\-\-preserve-environment\fR
-+Preserves the whole environment, ie does not set
-+.BR HOME ,
-+.BR SHELL ,
-+.B USER
-+nor
-+.BR LOGNAME .
-+.TP
-+\fB\-s\fR \fISHELL\fR, \fB\-\-shell\fR=\fISHELL\fR
-+Runs the specified shell instead of the default. The shell to run is
-+selected according to the following rules in order:
-+.RS 10
-+.TP
-+o
-+the shell specified with
-+.B \-\-shell
-+.TP
-+o
-+The shell specified in the environment variable
-+.B SHELL
-+if the
-+.B \-\-preserve-environment
-+option is used.
-+.TP
-+o
-+the shell listed in the passwd entry of the target user
-+.TP
-+o
-+/bin/sh
-+.RE
-+.IP
-+If the target user has a restricted shell (i.e. not listed in
-+/etc/shells) the
-+.B \-\-shell
-+option and the
-+.B SHELL
-+environment variables are ignored unless the calling user is root.
-+.TP
-+\fB\-\-help\fR
-+Display help text and exit.
-+.TP
-+\fB\-\-version\fR
-+Display version information and exit.
-+.SH CONFIG FILES
-+.B runuser
-+reads the
-+.I /etc/default/runuser
-+and
-+.I /etc/login.defs
-+configuration files. The following configuration items are relevant
-+for
-+.BR runuser :
-+.PP
-+.B ENV_PATH
-+(string)
-+.RS 4
-+Defines the PATH environment variable for a regular user. The
-+default value is
-+.IR /usr/local/bin:\:/bin:\:/usr/bin .
-+.RE
-+.PP
-+.B ENV_ROOTPATH
-+(string)
-+.br
-+.B ENV_SUPATH
-+(string)
-+.RS 4
-+Defines the PATH environment variable for root. The default value is
-+.IR /usr/local/sbin:\:/usr/local/bin:\:/sbin:\:/bin:\:/usr/sbin:\:/usr/bin .
-+.RE
-+.PP
-+.B ALWAYS_SET_PATH
-+(boolean)
-+.RS 4
-+If set to
-+.I yes
-+and \-\-login and \-\-preserve\-environment were not specified
-+.B runuser
-+initializes
-+.BR PATH .
-+.RE
-+.SH EXIT STATUS
-+.B runuser
-+normally returns the exit status of the command it executed. If the
-+command was killed by a signal,
-+.B runuser
-+returns the number of the signal plus 128.
-+.PP
-+Exit status generated by
-+.B runuser
-+itself:
-+.RS 10
-+.TP
-+1
-+Generic error before executing the requested command
-+.TP
-+126
-+The requested command could not be executed
-+.TP
-+127
-+The requested command could was not found
-+.RE
-+.SH FILES
-+.PD 0
-+.TP 17
-+/etc/pam.d/runuser
-+default PAM configuration file
-+.TP
-+/etc/pam.d/runuser-l
-+PAM configuration file if \-\-login is specified
-+.TP
-+/etc/default/runuser
-+runuser specific logindef config file
-+.TP
-+/etc/login.defs
-+global logindef config file
-+.PD 1
-+.SH "SEE ALSO"
-+.BR pam (8),
-+.BR shells (5),
-+.BR login.defs (5),
-+.BR su (1)
-+.SH AUTHOR
-+Derived from coreutils' su which was based on an implemenation from
-+David MacKenzie and Fedora runuser command from Dan Walsh.
-+.SH AVAILABILITY
-+The runuser command is part of the util-linux package and is
-+available from
-+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
-+Linux Kernel Archive
-+.UE .
-diff --git a/login-utils/runuser.c b/login-utils/runuser.c
-new file mode 100644
-index 0000000..d761a14
---- /dev/null
-+++ b/login-utils/runuser.c
-@@ -0,0 +1,7 @@
-+
-+#include "su-common.h"
-+
-+int main(int argv, char **argc)
-+{
-+ return su_main(argv, argc, RUNUSER_MODE);
-+}
-diff --git a/login-utils/su-common.c b/login-utils/su-common.c
-new file mode 100644
-index 0000000..d1fecd7
---- /dev/null
-+++ b/login-utils/su-common.c
-@@ -0,0 +1,918 @@
-+/* su for Linux. Run a shell with substitute user and group IDs.
-+ Copyright (C) 1992-2006 Free Software Foundation, Inc.
-+ Copyright (C) 2012 SUSE Linux Products GmbH, Nuernberg
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2, or (at your option)
-+ any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software Foundation,
-+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-+
-+/* Run a shell with the real and effective UID and GID and groups
-+ of USER, default `root'.
-+
-+ The shell run is taken from USER's password entry, /bin/sh if
-+ none is specified there. If the account has a password, su
-+ prompts for a password unless run by a user with real UID 0.
-+
-+ Does not change the current directory.
-+ Sets `HOME' and `SHELL' from the password entry for USER, and if
-+ USER is not root, sets `USER' and `LOGNAME' to USER.
-+ The subshell is not a login shell.
-+
-+ If one or more ARGs are given, they are passed as additional
-+ arguments to the subshell.
-+
-+ Does not handle /bin/sh or other shells specially
-+ (setting argv[0] to "-su", passing -c only to certain shells, etc.).
-+ I don't see the point in doing that, and it's ugly.
-+
-+ Based on an implemenation by David MacKenzie <djm at gnu.ai.mit.edu>. */
-+
-+enum
-+{
-+ EXIT_CANNOT_INVOKE = 126,
-+ EXIT_ENOENT = 127
-+};
-+
-+#include <config.h>
-+#include <stdio.h>
-+#include <getopt.h>
-+#include <sys/types.h>
-+#include <pwd.h>
-+#include <grp.h>
-+#include <security/pam_appl.h>
-+#include <security/pam_misc.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <syslog.h>
-+
-+#include "err.h"
-+
-+#include <stdbool.h>
-+#include "c.h"
-+#include "xalloc.h"
-+#include "nls.h"
-+#include "pathnames.h"
-+#include "env.h"
-+
-+/* name of the pam configuration files. separate configs for su and su - */
-+#define PAM_SRVNAME_SU "su"
-+#define PAM_SRVNAME_SU_L "su-l"
-+
-+#define PAM_SRVNAME_RUNUSER "runuser"
-+#define PAM_SRVNAME_RUNUSER_L "runuser-l"
-+
-+#define _PATH_LOGINDEFS_SU "/etc/defaults/su"
-+#define _PATH_LOGINDEFS_RUNUSER "/etc/defaults/runuser"
-+
-+#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
-+
-+#include "logindefs.h"
-+#include "su-common.h"
-+
-+/* The shell to run if none is given in the user's passwd entry. */
-+#define DEFAULT_SHELL "/bin/sh"
-+
-+/* The user to become if none is specified. */
-+#define DEFAULT_USER "root"
-+
-+#ifndef HAVE_ENVIRON_DECL
-+extern char **environ;
-+#endif
-+
-+static void run_shell (char const *, char const *, char **, size_t)
-+ __attribute__ ((__noreturn__));
-+
-+/* If true, pass the `-f' option to the subshell. */
-+static bool fast_startup;
-+
-+/* If true, simulate a login instead of just starting a shell. */
-+static bool simulate_login;
-+
-+/* If true, change some environment vars to indicate the user su'd to. */
-+static bool change_environment;
-+
-+/* If true, then don't call setsid() with a command. */
-+static int same_session = 0;
-+
-+/* SU_MODE_{RUNUSER,SU} */
-+static int su_mode;
-+
-+static bool _pam_session_opened;
-+static bool _pam_cred_established;
-+static sig_atomic_t volatile caught_signal = false;
-+static pam_handle_t *pamh = NULL;
-+
-+static int restricted = 1; /* zero for root user */
-+
-+static struct option const longopts[] =
-+{
-+ {"command", required_argument, NULL, 'c'},
-+ {"session-command", required_argument, NULL, 'C'},
-+ {"fast", no_argument, NULL, 'f'},
-+ {"login", no_argument, NULL, 'l'},
-+ {"preserve-environment", no_argument, NULL, 'p'},
-+ {"shell", required_argument, NULL, 's'},
-+ {"group", required_argument, NULL, 'g'},
-+ {"supp-group", required_argument, NULL, 'G'},
-+ {"help", no_argument, 0, 'h'},
-+ {"version", no_argument, 0, 'V'},
-+ {NULL, 0, NULL, 0}
-+};
-+
-+/* Log the fact that someone has run su to the user given by PW;
-+ if SUCCESSFUL is true, they gave the correct password, etc. */
-+
-+static void
-+log_su (struct passwd const *pw, bool successful)
-+{
-+ const char *new_user, *old_user, *tty;
-+
-+ new_user = pw->pw_name;
-+ /* The utmp entry (via getlogin) is probably the best way to identify
-+ the user, especially if someone su's from a su-shell. */
-+ old_user = getlogin ();
-+ if (!old_user)
-+ {
-+ /* getlogin can fail -- usually due to lack of utmp entry.
-+ Resort to getpwuid. */
-+ struct passwd *pwd = getpwuid (getuid ());
-+ old_user = (pwd ? pwd->pw_name : "");
-+ }
-+ tty = ttyname (STDERR_FILENO);
-+ if (!tty)
-+ tty = "none";
-+
-+ openlog (program_invocation_short_name, 0 , LOG_AUTH);
-+ syslog (LOG_NOTICE, "%s(to %s) %s on %s",
-+ successful ? "" :
-+ su_mode == RUNUSER_MODE ? "FAILED RUNUSER " : "FAILED SU ",
-+ new_user, old_user, tty);
-+ closelog ();
-+}
-+
-+static struct pam_conv conv =
-+{
-+ misc_conv,
-+ NULL
-+};
-+
-+static void
-+cleanup_pam (int retcode)
-+{
-+ int saved_errno = errno;
-+
-+ if (_pam_session_opened)
-+ pam_close_session (pamh, 0);
-+
-+ if (_pam_cred_established)
-+ pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT);
-+
-+ pam_end(pamh, retcode);
-+
-+ errno = saved_errno;
-+}
-+
-+/* Signal handler for parent process. */
-+static void
-+su_catch_sig (int sig __attribute__((__unused__)))
-+{
-+ caught_signal = true;
-+}
-+
-+/* Export env variables declared by PAM modules. */
-+static void
-+export_pamenv (void)
-+{
-+ char **env;
-+
-+ /* This is a copy but don't care to free as we exec later anyways. */
-+ env = pam_getenvlist (pamh);
-+ while (env && *env)
-+ {
-+ if (putenv (*env) != 0)
-+ err (EXIT_FAILURE, NULL);
-+ env++;
-+ }
-+}
-+
-+static void
-+create_watching_parent (void)
-+{
-+ pid_t child;
-+ sigset_t ourset;
-+ int status = 0;
-+ int retval;
-+
-+ retval = pam_open_session (pamh, 0);
-+ if (is_pam_failure(retval))
-+ {
-+ cleanup_pam (retval);
-+ errx (EXIT_FAILURE, _("cannot not open session: %s"),
-+ pam_strerror (pamh, retval));
-+ }
-+ else
-+ _pam_session_opened = 1;
-+
-+ child = fork ();
-+ if (child == (pid_t) -1)
-+ {
-+ cleanup_pam (PAM_ABORT);
-+ err (EXIT_FAILURE, _("cannot create child process"));
-+ }
-+
-+ /* the child proceeds to run the shell */
-+ if (child == 0)
-+ return;
-+
-+ /* In the parent watch the child. */
-+
-+ /* su without pam support does not have a helper that keeps
-+ sitting on any directory so let's go to /. */
-+ if (chdir ("/") != 0)
-+ warn (_("cannot change directory to %s"), "/");
-+
-+ sigfillset (&ourset);
-+ if (sigprocmask (SIG_BLOCK, &ourset, NULL))
-+ {
-+ warn (_("cannot block signals"));
-+ caught_signal = true;
-+ }
-+ if (!caught_signal)
-+ {
-+ struct sigaction action;
-+ action.sa_handler = su_catch_sig;
-+ sigemptyset (&action.sa_mask);
-+ action.sa_flags = 0;
-+ sigemptyset (&ourset);
-+ if (!same_session)
-+ {
-+ if (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT))
-+ {
-+ warn (_("cannot set signal handler"));
-+ caught_signal = true;
-+ }
-+ }
-+ if (!caught_signal && (sigaddset(&ourset, SIGTERM)
-+ || sigaddset(&ourset, SIGALRM)
-+ || sigaction(SIGTERM, &action, NULL)
-+ || sigprocmask(SIG_UNBLOCK, &ourset, NULL))) {
-+ warn (_("cannot set signal handler"));
-+ caught_signal = true;
-+ }
-+ if (!caught_signal && !same_session && (sigaction(SIGINT, &action, NULL)
-+ || sigaction(SIGQUIT, &action, NULL)))
-+ {
-+ warn (_("cannot set signal handler"));
-+ caught_signal = true;
-+ }
-+ }
-+ if (!caught_signal)
-+ {
-+ pid_t pid;
-+ for (;;)
-+ {
-+ pid = waitpid (child, &status, WUNTRACED);
-+
-+ if (pid != (pid_t)-1 && WIFSTOPPED (status))
-+ {
-+ kill (getpid (), SIGSTOP);
-+ /* once we get here, we must have resumed */
-+ kill (pid, SIGCONT);
-+ }
-+ else
-+ break;
-+ }
-+ if (pid != (pid_t)-1)
-+ if (WIFSIGNALED (status))
-+ status = WTERMSIG (status) + 128;
-+ else
-+ status = WEXITSTATUS (status);
-+ else
-+ status = 1;
-+ }
-+ else
-+ status = 1;
-+
-+ if (caught_signal)
-+ {
-+ fprintf (stderr, _("\nSession terminated, killing shell..."));
-+ kill (child, SIGTERM);
-+ }
-+
-+ cleanup_pam (PAM_SUCCESS);
-+
-+ if (caught_signal)
-+ {
-+ sleep (2);
-+ kill (child, SIGKILL);
-+ fprintf (stderr, _(" ...killed.\n"));
-+ }
-+ exit (status);
-+}
-+
-+static void
-+authenticate (const struct passwd *pw)
-+{
-+ const struct passwd *lpw;
-+ const char *cp, *srvname = NULL;
-+ int retval;
-+
-+ switch (su_mode) {
-+ case SU_MODE:
-+ srvname = simulate_login ? PAM_SRVNAME_SU_L : PAM_SRVNAME_SU;
-+ break;
-+ case RUNUSER_MODE:
-+ srvname = simulate_login ? PAM_SRVNAME_RUNUSER_L : PAM_SRVNAME_RUNUSER;
-+ break;
-+ }
-+
-+ retval = pam_start (srvname, pw->pw_name, &conv, &pamh);
-+ if (is_pam_failure(retval))
-+ goto done;
-+
-+ if (isatty (0) && (cp = ttyname (0)) != NULL)
-+ {
-+ const char *tty;
-+
-+ if (strncmp (cp, "/dev/", 5) == 0)
-+ tty = cp + 5;
-+ else
-+ tty = cp;
-+ retval = pam_set_item (pamh, PAM_TTY, tty);
-+ if (is_pam_failure(retval))
-+ goto done;
-+ }
-+
-+ lpw = getpwuid (getuid ());
-+ if (lpw && lpw->pw_name)
-+ {
-+ retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name);
-+ if (is_pam_failure(retval))
-+ goto done;
-+ }
-+
-+ if (su_mode == RUNUSER_MODE)
-+ {
-+ /*
-+ * This is the only difference between runuser(1) and su(1). The command
-+ * runuser(1) does not required authentication, because user is root.
-+ */
-+ if (restricted)
-+ errx(EXIT_FAILURE, _("may not be used by non-root users"));
-+ return;
-+ }
-+
-+ retval = pam_authenticate (pamh, 0);
-+ if (is_pam_failure(retval))
-+ goto done;
-+
-+ retval = pam_acct_mgmt (pamh, 0);
-+ if (retval == PAM_NEW_AUTHTOK_REQD)
-+ {
-+ /* Password has expired. Offer option to change it. */
-+ retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
-+ }
-+
-+done:
-+
-+ log_su (pw, !is_pam_failure(retval));
-+
-+ if (is_pam_failure(retval))
-+ {
-+ const char *msg = pam_strerror(pamh, retval);
-+ pam_end(pamh, retval);
-+ sleep (getlogindefs_num ("FAIL_DELAY", 1));
-+ errx (EXIT_FAILURE, "%s", msg?msg:_("incorrect password"));
-+ }
-+}
-+
-+/* Add or clear /sbin and /usr/sbin for the su command
-+ used without `-'. */
-+
-+/* Set if /sbin is found in path. */
-+#define SBIN_MASK 0x01
-+/* Set if /usr/sbin is found in path. */
-+#define USBIN_MASK 0x02
-+
-+static char *
-+addsbin (const char *const path)
-+{
-+ unsigned char smask = 0;
-+ char *ptr, *tmp, *cur, *ret = NULL;
-+ size_t len;
-+
-+ if (!path || *path == 0)
-+ return NULL;
-+
-+ tmp = xstrdup (path);
-+ cur = tmp;
-+ for (ptr = strsep (&cur, ":"); ptr != NULL; ptr = strsep (&cur, ":"))
-+ {
-+ if (!strcmp (ptr, "/sbin"))
-+ smask |= SBIN_MASK;
-+ if (!strcmp (ptr, "/usr/sbin"))
-+ smask |= USBIN_MASK;
-+ }
-+
-+ if ((smask & (USBIN_MASK|SBIN_MASK)) == (USBIN_MASK|SBIN_MASK))
-+ {
-+ free (tmp);
-+ return NULL;
-+ }
-+
-+ len = strlen (path);
-+ if (!(smask & USBIN_MASK))
-+ len += strlen ("/usr/sbin:");
-+
-+ if (!(smask & SBIN_MASK))
-+ len += strlen (":/sbin");
-+
-+ ret = xmalloc (len + 1);
-+ strcpy (tmp, path);
-+
-+ *ret = 0;
-+ cur = tmp;
-+ for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":"))
-+ {
-+ if (!strcmp (ptr, "."))
-+ continue;
-+ if (*ret)
-+ strcat (ret, ":");
-+ if (!(smask & USBIN_MASK) && !strcmp (ptr, "/bin"))
-+ {
-+ strcat (ret, "/usr/sbin:");
-+ strcat (ret, ptr);
-+ smask |= USBIN_MASK;
-+ continue;
-+ }
-+ if (!(smask & SBIN_MASK) && !strcmp (ptr, "/usr/bin"))
-+ {
-+ strcat (ret, ptr);
-+ strcat (ret, ":/sbin");
-+ smask |= SBIN_MASK;
-+ continue;
-+ }
-+ strcat (ret, ptr);
-+ }
-+ free (tmp);
-+
-+ if (!(smask & USBIN_MASK))
-+ strcat (ret, ":/usr/sbin");
-+
-+ if (!(smask & SBIN_MASK))
-+ strcat (ret, ":/sbin");
-+
-+ return ret;
-+}
-+
-+static char *
-+clearsbin (const char *const path)
-+{
-+ char *ptr, *tmp, *cur, *ret = NULL;
-+
-+ if (!path || *path == 0)
-+ return NULL;
-+
-+ tmp = xstrdup (path);
-+
-+ ret = xmalloc (strlen (path) + 1);
-+ *ret = 0;
-+ cur = tmp;
-+ for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":"))
-+ {
-+ if (!strcmp (ptr, "/sbin"))
-+ continue;
-+ if (!strcmp (ptr, "/usr/sbin"))
-+ continue;
-+ if (!strcmp (ptr, "/usr/local/sbin"))
-+ continue;
-+ if (*ret)
-+ strcat (ret, ":");
-+ strcat (ret, ptr);
-+ }
-+ free (tmp);
-+
-+ return ret;
-+}
-+
-+static void
-+set_path(const struct passwd* pw)
-+{
-+ int r;
-+ if (pw->pw_uid)
-+ r = logindefs_setenv("PATH", "ENV_PATH", _PATH_DEFPATH);
-+
-+ else if ((r = logindefs_setenv("PATH", "ENV_ROOTPATH", NULL)) != 0)
-+ r = logindefs_setenv("PATH", "ENV_SUPATH", _PATH_DEFPATH_ROOT);
-+
-+ if (r != 0)
-+ err (EXIT_FAILURE, _("failed to set PATH"));
-+}
-+
-+/* Update `environ' for the new shell based on PW, with SHELL being
-+ the value for the SHELL environment variable. */
-+
-+static void
-+modify_environment (const struct passwd *pw, const char *shell)
-+{
-+ if (simulate_login)
-+ {
-+ /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
-+ Unset all other environment variables. */
-+ char const *term = getenv ("TERM");
-+ if (term)
-+ term = xstrdup (term);
-+ environ = xmalloc ((6 + !!term) * sizeof (char *));
-+ environ[0] = NULL;
-+ if (term)
-+ xsetenv ("TERM", term, 1);
-+ xsetenv ("HOME", pw->pw_dir, 1);
-+ xsetenv ("SHELL", shell, 1);
-+ xsetenv ("USER", pw->pw_name, 1);
-+ xsetenv ("LOGNAME", pw->pw_name, 1);
-+ set_path(pw);
-+ }
-+ else
-+ {
-+ /* Set HOME, SHELL, and if not becoming a super-user,
-+ USER and LOGNAME. */
-+ if (change_environment)
-+ {
-+ xsetenv ("HOME", pw->pw_dir, 1);
-+ xsetenv ("SHELL", shell, 1);
-+ if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
-+ set_path(pw);
-+ else
-+ {
-+ char const *path = getenv ("PATH");
-+ char *new = NULL;
-+
-+ if (pw->pw_uid)
-+ new = clearsbin (path);
-+ else
-+ new = addsbin (path);
-+
-+ if (new)
-+ {
-+ xsetenv ("PATH", new, 1);
-+ free (new);
-+ }
-+ }
-+ if (pw->pw_uid)
-+ {
-+ xsetenv ("USER", pw->pw_name, 1);
-+ xsetenv ("LOGNAME", pw->pw_name, 1);
-+ }
-+ }
-+ }
-+
-+ export_pamenv ();
-+}
-+
-+/* Become the user and group(s) specified by PW. */
-+
-+static void
-+init_groups (const struct passwd *pw, gid_t *groups, int num_groups)
-+{
-+ int retval;
-+
-+ errno = 0;
-+
-+ if (num_groups)
-+ retval = setgroups (num_groups, groups);
-+ else
-+ retval = initgroups (pw->pw_name, pw->pw_gid);
-+
-+ if (retval == -1)
-+ {
-+ cleanup_pam (PAM_ABORT);
-+ err (EXIT_FAILURE, _("cannot set groups"));
-+ }
-+ endgrent ();
-+
-+ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
-+ if (is_pam_failure(retval))
-+ errx (EXIT_FAILURE, "%s", pam_strerror (pamh, retval));
-+ else
-+ _pam_cred_established = 1;
-+}
-+
-+static void
-+change_identity (const struct passwd *pw)
-+{
-+ if (setgid (pw->pw_gid))
-+ err (EXIT_FAILURE, _("cannot set group id"));
-+ if (setuid (pw->pw_uid))
-+ err (EXIT_FAILURE, _("cannot set user id"));
-+}
-+
-+/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
-+ If COMMAND is nonzero, pass it to the shell with the -c option.
-+ Pass ADDITIONAL_ARGS to the shell as more arguments; there
-+ are N_ADDITIONAL_ARGS extra arguments. */
-+
-+static void
-+run_shell (char const *shell, char const *command, char **additional_args,
-+ size_t n_additional_args)
-+{
-+ size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
-+ char const **args = xcalloc (n_args, sizeof *args);
-+ size_t argno = 1;
-+
-+ if (simulate_login)
-+ {
-+ char *arg0;
-+ char *shell_basename;
-+
-+ shell_basename = basename (shell);
-+ arg0 = xmalloc (strlen (shell_basename) + 2);
-+ arg0[0] = '-';
-+ strcpy (arg0 + 1, shell_basename);
-+ args[0] = arg0;
-+ }
-+ else
-+ args[0] = basename (shell);
-+ if (fast_startup)
-+ args[argno++] = "-f";
-+ if (command)
-+ {
-+ args[argno++] = "-c";
-+ args[argno++] = command;
-+ }
-+ memcpy (args + argno, additional_args, n_additional_args * sizeof *args);
-+ args[argno + n_additional_args] = NULL;
-+ execv (shell, (char **) args);
-+
-+ {
-+ int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
-+ warn ("%s", shell);
-+ exit (exit_status);
-+ }
-+}
-+
-+/* Return true if SHELL is a restricted shell (one not returned by
-+ getusershell), else false, meaning it is a standard shell. */
-+
-+static bool
-+restricted_shell (const char *shell)
-+{
-+ char *line;
-+
-+ setusershell ();
-+ while ((line = getusershell ()) != NULL)
-+ {
-+ if (*line != '#' && !strcmp (line, shell))
-+ {
-+ endusershell ();
-+ return false;
-+ }
-+ }
-+ endusershell ();
-+ return true;
-+}
-+
-+static void __attribute__((__noreturn__))
-+usage (int status)
-+{
-+ if (status != EXIT_SUCCESS)
-+ fprintf (stderr, _("Try `%s --help' for more information.\n"),
-+ program_invocation_short_name);
-+ else
-+ {
-+ fputs(USAGE_HEADER, stdout);
-+ printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
-+ fputs (_("\n\
-+ Change the effective user id and group id to that of USER.\n\
-+ A mere - implies -l. If USER not given, assume root.\n"), stdout);
-+ fputs(USAGE_OPTIONS, stdout);
-+ fputs (_("\
-+ -, -l, --login make the shell a login shell\n\
-+ -c, --command <command> pass a single command to the shell with -c\n\
-+ --session-command <command> pass a single command to the shell with -c\n\
-+ and do not create a new session\n\
-+ -g --group=group specify the primary group\n\
-+ -G --supp-group=group specify a supplemental group\n\
-+ -f, --fast pass -f to the shell (for csh or tcsh)\n\
-+ -m, --preserve-environment do not reset environment variables\n\
-+ -p same as -m\n\
-+ -s, --shell <shell> run shell if /etc/shells allows it\n\
-+"), stdout);
-+
-+ fputs(USAGE_SEPARATOR, stdout);
-+ fputs(USAGE_HELP, stdout);
-+ fputs(USAGE_VERSION, stdout);
-+ printf(USAGE_MAN_TAIL("su(1)"));
-+ }
-+ exit (status);
-+}
-+
-+static
-+void load_config(void)
-+{
-+ switch (su_mode) {
-+ case SU_MODE:
-+ logindefs_load_file(_PATH_LOGINDEFS_SU);
-+ break;
-+ case RUNUSER_MODE:
-+ logindefs_load_file(_PATH_LOGINDEFS_RUNUSER);
-+ break;
-+ }
-+
-+ logindefs_load_file(_PATH_LOGINDEFS);
-+}
-+
-+/*
-+ * Returns 1 if the current user is not root
-+ */
-+static int
-+evaluate_uid(void)
-+{
-+ uid_t ruid = getuid();
-+ uid_t euid = geteuid();
-+
-+ /* if we're really root and aren't running setuid */
-+ return (uid_t) 0 == ruid && ruid == euid ? 0 : 1;
-+}
-+
-+int
-+su_main (int argc, char **argv, int mode)
-+{
-+ int optc;
-+ const char *new_user = DEFAULT_USER;
-+ char *command = NULL;
-+ int request_same_session = 0;
-+ char *shell = NULL;
-+ struct passwd *pw;
-+ struct passwd pw_copy;
-+ struct group *gr;
-+ gid_t groups[NGROUPS_MAX];
-+ int num_supp_groups = 0;
-+ int use_gid = 0;
-+
-+ setlocale (LC_ALL, "");
-+ bindtextdomain (PACKAGE, LOCALEDIR);
-+ textdomain (PACKAGE);
-+
-+ su_mode = mode;
-+ fast_startup = false;
-+ simulate_login = false;
-+ change_environment = true;
-+
-+ while ((optc = getopt_long (argc, argv, "c:fg:G:lmps:hV", longopts, NULL)) != -1)
-+ {
-+ switch (optc)
-+ {
-+ case 'c':
-+ command = optarg;
-+ break;
-+
-+ case 'C':
-+ command = optarg;
-+ request_same_session = 1;
-+ break;
-+
-+ case 'f':
-+ fast_startup = true;
-+ break;
-+
-+ case 'g':
-+ gr = getgrnam(optarg);
-+ if (!gr)
-+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
-+ use_gid = 1;
-+ groups[0] = gr->gr_gid;
-+ break;
-+
-+ case 'G':
-+ num_supp_groups++;
-+ if (num_supp_groups >= NGROUPS_MAX)
-+ errx(EXIT_FAILURE,
-+ _("can't specify more than %d supplemental groups"),
-+ NGROUPS_MAX - 1);
-+ gr = getgrnam(optarg);
-+ if (!gr)
-+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
-+ groups[num_supp_groups] = gr->gr_gid;
-+ break;
-+
-+ case 'l':
-+ simulate_login = true;
-+ break;
-+
-+ case 'm':
-+ case 'p':
-+ change_environment = false;
-+ break;
-+
-+ case 's':
-+ shell = optarg;
-+ break;
-+
-+ case 'h':
-+ usage(0);
-+
-+ case 'V':
-+ printf(UTIL_LINUX_VERSION);
-+ exit(EXIT_SUCCESS);
-+
-+ default:
-+ usage (EXIT_FAILURE);
-+ }
-+ }
-+
-+ restricted = evaluate_uid ();
-+
-+ if (optind < argc && !strcmp (argv[optind], "-"))
-+ {
-+ simulate_login = true;
-+ ++optind;
-+ }
-+ if (optind < argc)
-+ new_user = argv[optind++];
-+
-+ if ((num_supp_groups || use_gid) && restricted)
-+ errx(EXIT_FAILURE, _("only root can specify alternative groups"));
-+
-+ logindefs_load_defaults = load_config;
-+
-+ pw = getpwnam (new_user);
-+ if (! (pw && pw->pw_name && pw->pw_name[0] && pw->pw_dir && pw->pw_dir[0]
-+ && pw->pw_passwd))
-+ errx (EXIT_FAILURE, _("user %s does not exist"), new_user);
-+
-+ /* Make a copy of the password information and point pw at the local
-+ copy instead. Otherwise, some systems (e.g. Linux) would clobber
-+ the static data through the getlogin call from log_su.
-+ Also, make sure pw->pw_shell is a nonempty string.
-+ It may be NULL when NEW_USER is a username that is retrieved via NIS (YP),
-+ but that doesn't have a default shell listed. */
-+ pw_copy = *pw;
-+ pw = &pw_copy;
-+ pw->pw_name = xstrdup (pw->pw_name);
-+ pw->pw_passwd = xstrdup (pw->pw_passwd);
-+ pw->pw_dir = xstrdup (pw->pw_dir);
-+ pw->pw_shell = xstrdup (pw->pw_shell && pw->pw_shell[0]
-+ ? pw->pw_shell
-+ : DEFAULT_SHELL);
-+ endpwent ();
-+
-+ if (num_supp_groups && !use_gid)
-+ {
-+ pw->pw_gid = groups[1];
-+ memmove (groups, groups + 1, sizeof(gid_t) * num_supp_groups);
-+ }
-+ else if (use_gid)
-+ {
-+ pw->pw_gid = groups[0];
-+ num_supp_groups++;
-+ }
-+
-+ authenticate (pw);
-+
-+ if (request_same_session || !command || !pw->pw_uid)
-+ same_session = 1;
-+
-+ if (!shell && !change_environment)
-+ shell = getenv ("SHELL");
-+ if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
-+ {
-+ /* The user being su'd to has a nonstandard shell, and so is
-+ probably a uucp account or has restricted access. Don't
-+ compromise the account by allowing access with a standard
-+ shell. */
-+ warnx (_("using restricted shell %s"), pw->pw_shell);
-+ shell = NULL;
-+ }
-+ shell = xstrdup (shell ? shell : pw->pw_shell);
-+
-+ init_groups (pw, groups, num_supp_groups);
-+
-+ create_watching_parent ();
-+ /* Now we're in the child. */
-+
-+ change_identity (pw);
-+ if (!same_session)
-+ setsid ();
-+
-+ /* Set environment after pam_open_session, which may put KRB5CCNAME
-+ into the pam_env, etc. */
-+
-+ modify_environment (pw, shell);
-+
-+ if (simulate_login && chdir (pw->pw_dir) != 0)
-+ warn (_("warning: cannot change directory to %s"), pw->pw_dir);
-+
-+ run_shell (shell, command, argv + optind, max (0, argc - optind));
-+}
-+
-+// vim: sw=2 cinoptions=>4,n-2,{2,^-2,\:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
-diff --git a/login-utils/su-common.h b/login-utils/su-common.h
-new file mode 100644
-index 0000000..7cf3769
---- /dev/null
-+++ b/login-utils/su-common.h
-@@ -0,0 +1,11 @@
-+#ifndef UTIL_LINUX_SU_COMMON_H
-+#define UTIL_LINUX_SU_COMMON_H
-+
-+enum {
-+ SU_MODE,
-+ RUNUSER_MODE
-+};
-+
-+extern int su_main(int argc, char **argv, int mode);
-+
-+#endif /* UTIL_LINUX_SU_COMMON */
-diff --git a/login-utils/su.1 b/login-utils/su.1
-index 598cebd..59e1731 100644
---- a/login-utils/su.1
-+++ b/login-utils/su.1
-@@ -59,6 +59,12 @@ Pass
- to the shell which may or may not be useful depending on the
- shell.
- .TP
-+\fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR
-+specify the primary group, this option is allowed for root user only
-+.TP
-+\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR
-+specify a supplemental group, this option is allowed for root user only
-+.TP
- \fB\-\fR, \fB\-l\fR, \fB\-\-login\fR
- Starts the shell as login shell with an environment similar to a real
- login:
-diff --git a/login-utils/su.c b/login-utils/su.c
-index c6b8bce..29c10f0 100644
---- a/login-utils/su.c
-+++ b/login-utils/su.c
-@@ -1,689 +1,8 @@
--/* su for Linux. Run a shell with substitute user and group IDs.
-- Copyright (C) 1992-2006 Free Software Foundation, Inc.
-- Copyright (C) 2012 SUSE Linux Products GmbH, Nuernberg
-
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
-+#include "su-common.h"
-
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software Foundation,
-- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
--
--/* Run a shell with the real and effective UID and GID and groups
-- of USER, default `root'.
--
-- The shell run is taken from USER's password entry, /bin/sh if
-- none is specified there. If the account has a password, su
-- prompts for a password unless run by a user with real UID 0.
--
-- Does not change the current directory.
-- Sets `HOME' and `SHELL' from the password entry for USER, and if
-- USER is not root, sets `USER' and `LOGNAME' to USER.
-- The subshell is not a login shell.
--
-- If one or more ARGs are given, they are passed as additional
-- arguments to the subshell.
--
-- Does not handle /bin/sh or other shells specially
-- (setting argv[0] to "-su", passing -c only to certain shells, etc.).
-- I don't see the point in doing that, and it's ugly.
--
-- Based on an implemenation by David MacKenzie <djm at gnu.ai.mit.edu>. */
--
--enum
--{
-- EXIT_CANNOT_INVOKE = 126,
-- EXIT_ENOENT = 127
--};
--
--#include <config.h>
--#include <stdio.h>
--#include <getopt.h>
--#include <sys/types.h>
--#include <pwd.h>
--#include <grp.h>
--#include <security/pam_appl.h>
--#include <security/pam_misc.h>
--#include <signal.h>
--#include <sys/wait.h>
--#include <syslog.h>
--
--#include "err.h"
--
--#include <stdbool.h>
--#include "c.h"
--#include "xalloc.h"
--#include "nls.h"
--#include "pathnames.h"
--#include "env.h"
--
--/* name of the pam configuration files. separate configs for su and su - */
--#define PAM_SERVICE_NAME "su"
--#define PAM_SERVICE_NAME_L "su-l"
--
--#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
--
--#include "logindefs.h"
--
--/* The shell to run if none is given in the user's passwd entry. */
--#define DEFAULT_SHELL "/bin/sh"
--
--/* The user to become if none is specified. */
--#define DEFAULT_USER "root"
--
--#ifndef HAVE_ENVIRON_DECL
--extern char **environ;
--#endif
--
--static void run_shell (char const *, char const *, char **, size_t)
-- __attribute__ ((__noreturn__));
--
--/* If true, pass the `-f' option to the subshell. */
--static bool fast_startup;
--
--/* If true, simulate a login instead of just starting a shell. */
--static bool simulate_login;
--
--/* If true, change some environment vars to indicate the user su'd to. */
--static bool change_environment;
--
--/* If true, then don't call setsid() with a command. */
--int same_session = 0;
--
--static bool _pam_session_opened;
--static bool _pam_cred_established;
--static sig_atomic_t volatile caught_signal = false;
--static pam_handle_t *pamh = NULL;
--
--static struct option const longopts[] =
--{
-- {"command", required_argument, NULL, 'c'},
-- {"session-command", required_argument, NULL, 'C'},
-- {"fast", no_argument, NULL, 'f'},
-- {"login", no_argument, NULL, 'l'},
-- {"preserve-environment", no_argument, NULL, 'p'},
-- {"shell", required_argument, NULL, 's'},
-- {"help", no_argument, 0, 'h'},
-- {"version", no_argument, 0, 'V'},
-- {NULL, 0, NULL, 0}
--};
--
--/* Log the fact that someone has run su to the user given by PW;
-- if SUCCESSFUL is true, they gave the correct password, etc. */
--
--static void
--log_su (struct passwd const *pw, bool successful)
--{
-- const char *new_user, *old_user, *tty;
--
-- new_user = pw->pw_name;
-- /* The utmp entry (via getlogin) is probably the best way to identify
-- the user, especially if someone su's from a su-shell. */
-- old_user = getlogin ();
-- if (!old_user)
-- {
-- /* getlogin can fail -- usually due to lack of utmp entry.
-- Resort to getpwuid. */
-- struct passwd *pwd = getpwuid (getuid ());
-- old_user = (pwd ? pwd->pw_name : "");
-- }
-- tty = ttyname (STDERR_FILENO);
-- if (!tty)
-- tty = "none";
--
-- openlog (program_invocation_short_name, 0 , LOG_AUTH);
-- syslog (LOG_NOTICE, "%s(to %s) %s on %s",
-- successful ? "" : "FAILED SU ",
-- new_user, old_user, tty);
-- closelog ();
--}
--
--static struct pam_conv conv =
--{
-- misc_conv,
-- NULL
--};
--
--static void
--cleanup_pam (int retcode)
-+int main(int argv, char **argc)
- {
-- int saved_errno = errno;
--
-- if (_pam_session_opened)
-- pam_close_session (pamh, 0);
--
-- if (_pam_cred_established)
-- pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT);
--
-- pam_end(pamh, retcode);
--
-- errno = saved_errno;
--}
--
--/* Signal handler for parent process. */
--static void
--su_catch_sig (int sig __attribute__((__unused__)))
--{
-- caught_signal = true;
--}
--
--/* Export env variables declared by PAM modules. */
--static void
--export_pamenv (void)
--{
-- char **env;
--
-- /* This is a copy but don't care to free as we exec later anyways. */
-- env = pam_getenvlist (pamh);
-- while (env && *env)
-- {
-- if (putenv (*env) != 0)
-- err (EXIT_FAILURE, NULL);
-- env++;
-- }
--}
--
--static void
--create_watching_parent (void)
--{
-- pid_t child;
-- sigset_t ourset;
-- int status = 0;
-- int retval;
--
-- retval = pam_open_session (pamh, 0);
-- if (is_pam_failure(retval))
-- {
-- cleanup_pam (retval);
-- errx (EXIT_FAILURE, _("cannot not open session: %s"),
-- pam_strerror (pamh, retval));
-- }
-- else
-- _pam_session_opened = 1;
--
-- child = fork ();
-- if (child == (pid_t) -1)
-- {
-- cleanup_pam (PAM_ABORT);
-- err (EXIT_FAILURE, _("cannot create child process"));
-- }
--
-- /* the child proceeds to run the shell */
-- if (child == 0)
-- return;
--
-- /* In the parent watch the child. */
--
-- /* su without pam support does not have a helper that keeps
-- sitting on any directory so let's go to /. */
-- if (chdir ("/") != 0)
-- warn (_("cannot change directory to %s"), "/");
--
-- sigfillset (&ourset);
-- if (sigprocmask (SIG_BLOCK, &ourset, NULL))
-- {
-- warn (_("cannot block signals"));
-- caught_signal = true;
-- }
-- if (!caught_signal)
-- {
-- struct sigaction action;
-- action.sa_handler = su_catch_sig;
-- sigemptyset (&action.sa_mask);
-- action.sa_flags = 0;
-- sigemptyset (&ourset);
-- if (!same_session)
-- {
-- if (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT))
-- {
-- warn (_("cannot set signal handler"));
-- caught_signal = true;
-- }
-- }
-- if (!caught_signal && (sigaddset(&ourset, SIGTERM)
-- || sigaddset(&ourset, SIGALRM)
-- || sigaction(SIGTERM, &action, NULL)
-- || sigprocmask(SIG_UNBLOCK, &ourset, NULL))) {
-- warn (_("cannot set signal handler"));
-- caught_signal = true;
-- }
-- if (!caught_signal && !same_session && (sigaction(SIGINT, &action, NULL)
-- || sigaction(SIGQUIT, &action, NULL)))
-- {
-- warn (_("cannot set signal handler"));
-- caught_signal = true;
-- }
-- }
-- if (!caught_signal)
-- {
-- pid_t pid;
-- for (;;)
-- {
-- pid = waitpid (child, &status, WUNTRACED);
--
-- if (pid != (pid_t)-1 && WIFSTOPPED (status))
-- {
-- kill (getpid (), SIGSTOP);
-- /* once we get here, we must have resumed */
-- kill (pid, SIGCONT);
-- }
-- else
-- break;
-- }
-- if (pid != (pid_t)-1)
-- if (WIFSIGNALED (status))
-- status = WTERMSIG (status) + 128;
-- else
-- status = WEXITSTATUS (status);
-- else
-- status = 1;
-- }
-- else
-- status = 1;
--
-- if (caught_signal)
-- {
-- fprintf (stderr, _("\nSession terminated, killing shell..."));
-- kill (child, SIGTERM);
-- }
--
-- cleanup_pam (PAM_SUCCESS);
--
-- if (caught_signal)
-- {
-- sleep (2);
-- kill (child, SIGKILL);
-- fprintf (stderr, _(" ...killed.\n"));
-- }
-- exit (status);
--}
--
--static void
--authenticate (const struct passwd *pw)
--{
-- const struct passwd *lpw;
-- const char *cp;
-- int retval;
--
-- retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
-- pw->pw_name, &conv, &pamh);
-- if (is_pam_failure(retval))
-- goto done;
--
-- if (isatty (0) && (cp = ttyname (0)) != NULL)
-- {
-- const char *tty;
--
-- if (strncmp (cp, "/dev/", 5) == 0)
-- tty = cp + 5;
-- else
-- tty = cp;
-- retval = pam_set_item (pamh, PAM_TTY, tty);
-- if (is_pam_failure(retval))
-- goto done;
-- }
--
-- lpw = getpwuid (getuid ());
-- if (lpw && lpw->pw_name)
-- {
-- retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name);
-- if (is_pam_failure(retval))
-- goto done;
-- }
--
-- retval = pam_authenticate (pamh, 0);
-- if (is_pam_failure(retval))
-- goto done;
--
-- retval = pam_acct_mgmt (pamh, 0);
-- if (retval == PAM_NEW_AUTHTOK_REQD)
-- {
-- /* Password has expired. Offer option to change it. */
-- retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
-- }
--
--done:
--
-- log_su (pw, !is_pam_failure(retval));
--
-- if (is_pam_failure(retval))
-- {
-- const char *msg = pam_strerror(pamh, retval);
-- pam_end(pamh, retval);
-- sleep (getlogindefs_num ("FAIL_DELAY", 1));
-- errx (EXIT_FAILURE, "%s", msg?msg:_("incorrect password"));
-- }
--}
--
--static void
--set_path(const struct passwd* pw)
--{
-- int r;
-- if (pw->pw_uid)
-- r = logindefs_setenv("PATH", "ENV_PATH", _PATH_DEFPATH);
--
-- else if ((r = logindefs_setenv("PATH", "ENV_ROOTPATH", NULL)) != 0)
-- r = logindefs_setenv("PATH", "ENV_SUPATH", _PATH_DEFPATH_ROOT);
--
-- if (r != 0)
-- err (EXIT_FAILURE, _("failed to set PATH"));
--}
--
--/* Update `environ' for the new shell based on PW, with SHELL being
-- the value for the SHELL environment variable. */
--
--static void
--modify_environment (const struct passwd *pw, const char *shell)
--{
-- if (simulate_login)
-- {
-- /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
-- Unset all other environment variables. */
-- char const *term = getenv ("TERM");
-- if (term)
-- term = xstrdup (term);
-- environ = xmalloc ((6 + !!term) * sizeof (char *));
-- environ[0] = NULL;
-- if (term)
-- xsetenv ("TERM", term, 1);
-- xsetenv ("HOME", pw->pw_dir, 1);
-- xsetenv ("SHELL", shell, 1);
-- xsetenv ("USER", pw->pw_name, 1);
-- xsetenv ("LOGNAME", pw->pw_name, 1);
-- set_path(pw);
-- }
-- else
-- {
-- /* Set HOME, SHELL, and if not becoming a super-user,
-- USER and LOGNAME. */
-- if (change_environment)
-- {
-- xsetenv ("HOME", pw->pw_dir, 1);
-- xsetenv ("SHELL", shell, 1);
-- if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
-- set_path(pw);
--
-- if (pw->pw_uid)
-- {
-- xsetenv ("USER", pw->pw_name, 1);
-- xsetenv ("LOGNAME", pw->pw_name, 1);
-- }
-- }
-- }
--
-- export_pamenv ();
--}
--
--/* Become the user and group(s) specified by PW. */
--
--static void
--init_groups (const struct passwd *pw)
--{
-- int retval;
-- errno = 0;
-- if (initgroups (pw->pw_name, pw->pw_gid) == -1)
-- {
-- cleanup_pam (PAM_ABORT);
-- err (EXIT_FAILURE, _("cannot set groups"));
-- }
-- endgrent ();
--
-- retval = pam_setcred (pamh, PAM_ESTABLISH_CRED);
-- if (is_pam_failure(retval))
-- errx (EXIT_FAILURE, "%s", pam_strerror (pamh, retval));
-- else
-- _pam_cred_established = 1;
--}
--
--static void
--change_identity (const struct passwd *pw)
--{
-- if (setgid (pw->pw_gid))
-- err (EXIT_FAILURE, _("cannot set group id"));
-- if (setuid (pw->pw_uid))
-- err (EXIT_FAILURE, _("cannot set user id"));
--}
--
--/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
-- If COMMAND is nonzero, pass it to the shell with the -c option.
-- Pass ADDITIONAL_ARGS to the shell as more arguments; there
-- are N_ADDITIONAL_ARGS extra arguments. */
--
--static void
--run_shell (char const *shell, char const *command, char **additional_args,
-- size_t n_additional_args)
--{
-- size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
-- char const **args = xcalloc (n_args, sizeof *args);
-- size_t argno = 1;
--
-- if (simulate_login)
-- {
-- char *arg0;
-- char *shell_basename;
--
-- shell_basename = basename (shell);
-- arg0 = xmalloc (strlen (shell_basename) + 2);
-- arg0[0] = '-';
-- strcpy (arg0 + 1, shell_basename);
-- args[0] = arg0;
-- }
-- else
-- args[0] = basename (shell);
-- if (fast_startup)
-- args[argno++] = "-f";
-- if (command)
-- {
-- args[argno++] = "-c";
-- args[argno++] = command;
-- }
-- memcpy (args + argno, additional_args, n_additional_args * sizeof *args);
-- args[argno + n_additional_args] = NULL;
-- execv (shell, (char **) args);
--
-- {
-- int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
-- warn ("%s", shell);
-- exit (exit_status);
-- }
--}
--
--/* Return true if SHELL is a restricted shell (one not returned by
-- getusershell), else false, meaning it is a standard shell. */
--
--static bool
--restricted_shell (const char *shell)
--{
-- char *line;
--
-- setusershell ();
-- while ((line = getusershell ()) != NULL)
-- {
-- if (*line != '#' && !strcmp (line, shell))
-- {
-- endusershell ();
-- return false;
-- }
-- }
-- endusershell ();
-- return true;
--}
--
--static void __attribute__((__noreturn__))
--usage (int status)
--{
-- if (status != EXIT_SUCCESS)
-- fprintf (stderr, _("Try `%s --help' for more information.\n"),
-- program_invocation_short_name);
-- else
-- {
-- fputs(USAGE_HEADER, stdout);
-- printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
-- fputs (_("\n\
-- Change the effective user id and group id to that of USER.\n\
-- A mere - implies -l. If USER not given, assume root.\n"), stdout);
-- fputs(USAGE_OPTIONS, stdout);
-- fputs (_("\
-- -, -l, --login make the shell a login shell\n\
-- -c, --command <command> pass a single command to the shell with -c\n\
-- --session-command <command> pass a single command to the shell with -c\n\
-- and do not create a new session\n\
-- -f, --fast pass -f to the shell (for csh or tcsh)\n\
-- -m, --preserve-environment do not reset environment variables\n\
-- -p same as -m\n\
-- -s, --shell <shell> run shell if /etc/shells allows it\n\
--"), stdout);
--
-- fputs(USAGE_SEPARATOR, stdout);
-- fputs(USAGE_HELP, stdout);
-- fputs(USAGE_VERSION, stdout);
-- printf(USAGE_MAN_TAIL("su(1)"));
-- }
-- exit (status);
--}
--
--static
--void load_config(void)
--{
-- logindefs_load_file("/etc/default/su");
-- logindefs_load_file(_PATH_LOGINDEFS);
--}
--
--int
--main (int argc, char **argv)
--{
-- int optc;
-- const char *new_user = DEFAULT_USER;
-- char *command = NULL;
-- int request_same_session = 0;
-- char *shell = NULL;
-- struct passwd *pw;
-- struct passwd pw_copy;
--
-- setlocale (LC_ALL, "");
-- bindtextdomain (PACKAGE, LOCALEDIR);
-- textdomain (PACKAGE);
--
-- fast_startup = false;
-- simulate_login = false;
-- change_environment = true;
--
-- while ((optc = getopt_long (argc, argv, "c:flmps:hV", longopts, NULL)) != -1)
-- {
-- switch (optc)
-- {
-- case 'c':
-- command = optarg;
-- break;
--
-- case 'C':
-- command = optarg;
-- request_same_session = 1;
-- break;
--
-- case 'f':
-- fast_startup = true;
-- break;
--
-- case 'l':
-- simulate_login = true;
-- break;
--
-- case 'm':
-- case 'p':
-- change_environment = false;
-- break;
--
-- case 's':
-- shell = optarg;
-- break;
--
-- case 'h':
-- usage(0);
--
-- case 'V':
-- printf(UTIL_LINUX_VERSION);
-- exit(EXIT_SUCCESS);
--
-- default:
-- usage (EXIT_FAILURE);
-- }
-- }
--
-- if (optind < argc && !strcmp (argv[optind], "-"))
-- {
-- simulate_login = true;
-- ++optind;
-- }
-- if (optind < argc)
-- new_user = argv[optind++];
--
-- logindefs_load_defaults = load_config;
--
-- pw = getpwnam (new_user);
-- if (! (pw && pw->pw_name && pw->pw_name[0] && pw->pw_dir && pw->pw_dir[0]
-- && pw->pw_passwd))
-- errx (EXIT_FAILURE, _("user %s does not exist"), new_user);
--
-- /* Make a copy of the password information and point pw at the local
-- copy instead. Otherwise, some systems (e.g. Linux) would clobber
-- the static data through the getlogin call from log_su.
-- Also, make sure pw->pw_shell is a nonempty string.
-- It may be NULL when NEW_USER is a username that is retrieved via NIS (YP),
-- but that doesn't have a default shell listed. */
-- pw_copy = *pw;
-- pw = &pw_copy;
-- pw->pw_name = xstrdup (pw->pw_name);
-- pw->pw_passwd = xstrdup (pw->pw_passwd);
-- pw->pw_dir = xstrdup (pw->pw_dir);
-- pw->pw_shell = xstrdup (pw->pw_shell && pw->pw_shell[0]
-- ? pw->pw_shell
-- : DEFAULT_SHELL);
-- endpwent ();
--
-- authenticate (pw);
--
-- if (request_same_session || !command || !pw->pw_uid)
-- same_session = 1;
--
-- if (!shell && !change_environment)
-- shell = getenv ("SHELL");
-- if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
-- {
-- /* The user being su'd to has a nonstandard shell, and so is
-- probably a uucp account or has restricted access. Don't
-- compromise the account by allowing access with a standard
-- shell. */
-- warnx (_("using restricted shell %s"), pw->pw_shell);
-- shell = NULL;
-- }
-- shell = xstrdup (shell ? shell : pw->pw_shell);
--
-- init_groups (pw);
--
-- create_watching_parent ();
-- /* Now we're in the child. */
--
-- change_identity (pw);
-- if (!same_session)
-- setsid ();
--
-- /* Set environment after pam_open_session, which may put KRB5CCNAME
-- into the pam_env, etc. */
--
-- modify_environment (pw, shell);
--
-- if (simulate_login && chdir (pw->pw_dir) != 0)
-- warn (_("warning: cannot change directory to %s"), pw->pw_dir);
--
-- run_shell (shell, command, argv + optind, max (0, argc - optind));
-+ return su_main(argv, argc, SU_MODE);
- }
-
--// vim: sw=2 cinoptions=>4,n-2,{2,^-2,\:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/util-linux.git/commitdiff/232bdb1aa2ccb366530735e18678f22ef68813fa
More information about the pld-cvs-commit
mailing list