mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-07-29 12:21:15 +03:00
su: remove program (util-linux is now the best source for it)
* README: Omit "su" from list of programs. * src/su.c: Remove file. * src/Makefile.am: Remove su-related rules and variables. * tests/misc/su-fail: Remove test. * tests/Makefile.am (TESTS): Remove misc/su-fail. * tests/misc/invalid-opt: Remove su-related code. * src/.gitignore: Remove su. * man/su.x: Remove file. * man/Makefile.am (su.1): Remove rule. * po/POTFILES.in: Remove su.c from the list. * TODO: Remove ancient entry. * NEWS (Changes in behavior): Mention it. * doc/coreutils.texi: Remove su-related description. * AUTHORS: Remove su. * m4/lib-check.m4 (cu_LIB_CHECK): Remove file/macro. * configure.ac: Remove su-related code and sole use of cu_LIB_CHECK. * scripts/git-hooks/commit-msg: Remove su from this list, too.
This commit is contained in:
1
AUTHORS
1
AUTHORS
@ -80,7 +80,6 @@ split: Torbjörn Granlund, Richard M. Stallman
|
||||
stat: Michael Meskes
|
||||
stdbuf: Pádraig Brady
|
||||
stty: David MacKenzie
|
||||
su: David MacKenzie
|
||||
sum: Kayvan Aghaiepour, David MacKenzie
|
||||
sync: Jim Meyering
|
||||
tac: Jay Lepreau, David MacKenzie
|
||||
|
8
NEWS
8
NEWS
@ -30,6 +30,14 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
stat -f recognizes the new remote file system type, panfs.
|
||||
|
||||
** Changes in behavior
|
||||
|
||||
su: this program has been removed. We stopped installing "su" by
|
||||
default with the release of coreutils-6.9.90 on 2007-12-01. Now,
|
||||
that the util-linux package has the union of the Suse and Fedora
|
||||
patches as well as enough support to build on the Hurd, we no longer
|
||||
have any reason to include it here.
|
||||
|
||||
|
||||
* Noteworthy changes in release 8.17 (2012-05-10) [stable]
|
||||
|
||||
|
2
README
2
README
@ -13,7 +13,7 @@ The programs that can be built with this package are:
|
||||
link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup
|
||||
nproc od paste pathchk pinky pr printenv printf ptx pwd readlink realpath
|
||||
rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred
|
||||
shuf sleep sort split stat stdbuf stty su sum sync tac tail tee test
|
||||
shuf sleep sort split stat stdbuf stty sum sync tac tail tee test
|
||||
timeout touch tr true truncate tsort tty uname unexpand uniq unlink
|
||||
uptime users vdir wc who whoami yes
|
||||
|
||||
|
3
TODO
3
TODO
@ -78,9 +78,6 @@ unexpand: [http://www.opengroup.org/onlinepubs/007908799/xcu/unexpand.html]
|
||||
printf 'x\t \t y\n'|unexpand -t 8,9 should print its input, unmodified.
|
||||
printf 'x\t \t y\n'|unexpand -t 5,8 should print "x\ty\n"
|
||||
|
||||
Let GNU su use the 'wheel' group if appropriate.
|
||||
(there are a couple patches, already)
|
||||
|
||||
sort: Investigate better sorting algorithms; see Knuth vol. 3.
|
||||
|
||||
We tried list merge sort, but it was about 50% slower than the
|
||||
|
13
configure.ac
13
configure.ac
@ -380,7 +380,6 @@ AC_CHECK_DECLS([strsignal, sys_siglist, _sys_siglist, __sys_siglist], , ,
|
||||
[AC_INCLUDES_DEFAULT
|
||||
#include <signal.h>])
|
||||
|
||||
cu_LIB_CHECK
|
||||
cu_GMP
|
||||
|
||||
# Build df only if there's a point to it.
|
||||
@ -421,7 +420,7 @@ t=`sed -n '/^'$v' =/,/[[^\]]$/p' $mk \
|
||||
no_install_progs_default=`echo "$t"|sed 's/ $//'`
|
||||
|
||||
# Unfortunately, due to the way autoconf's AS_HELP_STRING works, the list
|
||||
# of default-not-installed programs, "arch hostname su", must appear in two
|
||||
# of default-not-installed programs, "arch hostname", must appear in two
|
||||
# places: in this file below, and in $mk. Using "$no_install_progs_default"
|
||||
# below cannot work. And we can't substitute the names into $mk because
|
||||
# automake needs the literals, too.
|
||||
@ -448,7 +447,7 @@ esac
|
||||
# Note how the second argument below is a literal, with "," separators.
|
||||
# That is required due to the way the macro works, and since the
|
||||
# corresponding ./configure option argument is comma-separated on input.
|
||||
gl_INCLUDE_EXCLUDE_PROG([optional_bin_progs], [arch,hostname,su])
|
||||
gl_INCLUDE_EXCLUDE_PROG([optional_bin_progs], [arch,hostname])
|
||||
|
||||
# Now that we know which programs will actually be built up, figure out
|
||||
# which optional helper progs should be compiled.
|
||||
@ -457,14 +456,6 @@ case " $optional_bin_progs " in
|
||||
*' stdbuf '*) gl_ADD_PROG([optional_pkglib_progs], [libstdbuf.so]) ;;
|
||||
esac
|
||||
|
||||
# Set INSTALL_SU if su installation has been requested via
|
||||
# --enable-install-program=su.
|
||||
AC_SUBST([INSTALL_SU])
|
||||
case " $optional_bin_progs " in
|
||||
*' su '*) INSTALL_SU=yes ;;
|
||||
*) INSTALL_SU=no ;;
|
||||
esac
|
||||
|
||||
MAN=`echo "$optional_bin_progs "|sed 's/ /.1 /g;s/ $//'|tr -d '\\015\\012'`
|
||||
|
||||
# Change "ginstall.1" to "install.1" in $MAN.
|
||||
|
@ -109,7 +109,6 @@
|
||||
* stat: (coreutils)stat invocation. Report file(system) status.
|
||||
* stdbuf: (coreutils)stdbuf invocation. Modify stdio buffering.
|
||||
* stty: (coreutils)stty invocation. Print/change terminal settings.
|
||||
* su: (coreutils)su invocation. Modify user and group ID.
|
||||
* sum: (coreutils)sum invocation. Print traditional checksum.
|
||||
* sync: (coreutils)sync invocation. Synchronize memory and disk.
|
||||
* tac: (coreutils)tac invocation. Reverse files.
|
||||
@ -200,7 +199,7 @@ Free Documentation License''.
|
||||
* User information:: id logname whoami groups users who
|
||||
* System context:: date arch nproc uname hostname hostid uptime
|
||||
* SELinux context:: chcon runcon
|
||||
* Modified command invocation:: chroot env nice nohup stdbuf su timeout
|
||||
* Modified command invocation:: chroot env nice nohup stdbuf timeout
|
||||
* Process control:: kill
|
||||
* Delaying:: sleep
|
||||
* Numeric operations:: factor seq
|
||||
@ -443,7 +442,6 @@ Modified command invocation
|
||||
* nice invocation:: Run a command with modified niceness
|
||||
* nohup invocation:: Run a command immune to hangups
|
||||
* stdbuf invocation:: Run a command with modified I/O buffering
|
||||
* su invocation:: Run a command with substitute user and group ID
|
||||
* timeout invocation:: Run a command with a time limit
|
||||
|
||||
Process control
|
||||
@ -766,7 +764,7 @@ meanings with the values @samp{0} and @samp{1}.
|
||||
Here are some of the exceptions:
|
||||
@command{chroot}, @command{env}, @command{expr}, @command{nice},
|
||||
@command{nohup}, @command{printenv}, @command{sort}, @command{stdbuf},
|
||||
@command{su}, @command{test}, @command{timeout}, @command{tty}.
|
||||
@command{test}, @command{timeout}, @command{tty}.
|
||||
|
||||
|
||||
@node Backup options
|
||||
@ -15266,7 +15264,6 @@ user, etc.
|
||||
* nice invocation:: Modify niceness.
|
||||
* nohup invocation:: Immunize to hangups.
|
||||
* stdbuf invocation:: Modify buffering of standard streams.
|
||||
* su invocation:: Modify user and group ID.
|
||||
* timeout invocation:: Run with time limit.
|
||||
@end menu
|
||||
|
||||
@ -15794,163 +15791,6 @@ the exit status of @var{command} otherwise
|
||||
@end display
|
||||
|
||||
|
||||
@node su invocation
|
||||
@section @command{su}: Run a command with substitute user and group ID
|
||||
|
||||
@pindex su
|
||||
@cindex substitute user and group IDs
|
||||
@cindex user ID, switching
|
||||
@cindex super-user, becoming
|
||||
@cindex root, becoming
|
||||
|
||||
@command{su} allows one user to temporarily become another user. It runs a
|
||||
command (often an interactive shell) with the real and effective user
|
||||
ID, group ID, and supplemental groups of a given @var{user}. Synopsis:
|
||||
|
||||
@example
|
||||
su [@var{option}]@dots{} [@var{user} [@var{arg}]@dots{}]
|
||||
@end example
|
||||
|
||||
@cindex passwd entry, and @command{su} shell
|
||||
@flindex /bin/sh
|
||||
@flindex /etc/passwd
|
||||
If no @var{user} is given, the default is @code{root}, the super-user.
|
||||
The shell to use is taken from @var{user}'s @code{passwd} entry, or
|
||||
@file{/bin/sh} if none is specified there. If @var{user} has a
|
||||
password, @command{su} prompts for the password unless run by a user with
|
||||
effective user ID of zero (the super-user).
|
||||
|
||||
@vindex HOME
|
||||
@vindex SHELL
|
||||
@vindex USER
|
||||
@vindex LOGNAME
|
||||
@cindex login shell
|
||||
By default, @command{su} does not change the current directory.
|
||||
It sets the environment variables @env{HOME} and @env{SHELL}
|
||||
from the password entry for @var{user}, and if @var{user} is not
|
||||
the super-user, sets @env{USER} and @env{LOGNAME} to @var{user}.
|
||||
By default, the shell is not a login shell.
|
||||
|
||||
Any additional @var{arg}s are passed as additional arguments to the
|
||||
shell.
|
||||
|
||||
@cindex @option{-su}
|
||||
GNU @command{su} does not treat @file{/bin/sh} or any other shells specially
|
||||
(e.g., by setting @code{argv[0]} to @option{-su}, passing @option{-c} only
|
||||
to certain shells, etc.).
|
||||
|
||||
@findex syslog
|
||||
@command{su} can optionally be compiled to use @code{syslog} to report
|
||||
failed, and optionally successful, @command{su} attempts. (If the system
|
||||
supports @code{syslog}.) However, GNU @command{su} does not check if the
|
||||
user is a member of the @code{wheel} group; see below.
|
||||
|
||||
The program accepts the following options. Also see @ref{Common options}.
|
||||
|
||||
@table @samp
|
||||
@item -c @var{command}
|
||||
@itemx --command=@var{command}
|
||||
@opindex -c
|
||||
@opindex --command
|
||||
Pass @var{command}, a single command line to run, to the shell with
|
||||
a @option{-c} option instead of starting an interactive shell.
|
||||
|
||||
@item -f
|
||||
@itemx --fast
|
||||
@opindex -f
|
||||
@opindex --fast
|
||||
@flindex .cshrc
|
||||
@cindex file name pattern expansion, disabled
|
||||
@cindex globbing, disabled
|
||||
Pass the @option{-f} option to the shell. This probably only makes sense
|
||||
if the shell run is @command{csh} or @command{tcsh}, for which the @option{-f}
|
||||
option prevents reading the startup file (@file{.cshrc}). With
|
||||
Bourne-like shells, the @option{-f} option disables file name pattern
|
||||
expansion (globbing), which is not likely to be useful.
|
||||
|
||||
@item -
|
||||
@itemx -l
|
||||
@itemx --login
|
||||
@opindex -
|
||||
@opindex -l
|
||||
@opindex --login
|
||||
@c other variables already indexed above
|
||||
@vindex TERM
|
||||
@vindex PATH
|
||||
@cindex login shell, creating
|
||||
Make the shell a login shell. This means the following. Unset all
|
||||
environment variables except @env{TERM}, @env{HOME}, and @env{SHELL}
|
||||
(which are set as described above), and @env{USER} and @env{LOGNAME}
|
||||
(which are set, even for the super-user, as described above), and set
|
||||
@env{PATH} to a compiled-in default value. Change to @var{user}'s home
|
||||
directory. Prepend @samp{-} to the shell's name, intended to make it
|
||||
read its login startup file(s).
|
||||
|
||||
@item -m
|
||||
@itemx -p
|
||||
@itemx --preserve-environment
|
||||
@opindex -m
|
||||
@opindex -p
|
||||
@opindex --preserve-environment
|
||||
@cindex environment, preserving
|
||||
@flindex /etc/shells
|
||||
@cindex restricted shell
|
||||
Do not change the environment variables @env{HOME}, @env{USER},
|
||||
@env{LOGNAME}, or @env{SHELL}. Run the shell given in the environment
|
||||
variable @env{SHELL} instead of the shell from @var{user}'s passwd
|
||||
entry, unless the user running @command{su} is not the super-user and
|
||||
@var{user}'s shell is restricted. A @dfn{restricted shell} is one that
|
||||
is not listed in the file @file{/etc/shells}, or in a compiled-in list
|
||||
if that file does not exist. Parts of what this option does can be
|
||||
overridden by @option{--login} and @option{--shell}.
|
||||
|
||||
@item -s @var{shell}
|
||||
@itemx --shell=@var{shell}
|
||||
@opindex -s
|
||||
@opindex --shell
|
||||
Run @var{shell} instead of the shell from @var{user}'s passwd entry,
|
||||
unless the user running @command{su} is not the super-user and @var{user}'s
|
||||
shell is restricted (see @option{-m} just above).
|
||||
|
||||
@end table
|
||||
|
||||
@cindex exit status of @command{su}
|
||||
Exit status:
|
||||
|
||||
@display
|
||||
125 if @command{su} itself fails
|
||||
126 if subshell is found but cannot be invoked
|
||||
127 if subshell cannot be found
|
||||
the exit status of the subshell otherwise
|
||||
@end display
|
||||
|
||||
@cindex wheel group, not supported
|
||||
@cindex group wheel, not supported
|
||||
@cindex fascism
|
||||
@subsection Why GNU @command{su} does not support the @samp{wheel} group
|
||||
|
||||
(This section is by Richard Stallman.)
|
||||
|
||||
@cindex Twenex
|
||||
@cindex MIT AI lab
|
||||
Sometimes a few of the users try to hold total power over all the
|
||||
rest. For example, in 1984, a few users at the MIT AI lab decided to
|
||||
seize power by changing the operator password on the Twenex system and
|
||||
keeping it secret from everyone else. (I was able to thwart this coup
|
||||
and give power back to the users by patching the kernel, but I
|
||||
wouldn't know how to do that in Unix.)
|
||||
|
||||
However, occasionally the rulers do tell someone. Under the usual
|
||||
@command{su} mechanism, once someone learns the root password who
|
||||
sympathizes with the ordinary users, he or she can tell the rest. The
|
||||
``wheel group'' feature would make this impossible, and thus cement the
|
||||
power of the rulers.
|
||||
|
||||
I'm on the side of the masses, not that of the rulers. If you are
|
||||
used to supporting the bosses and sysadmins in whatever they do, you
|
||||
might find this idea strange at first.
|
||||
|
||||
|
||||
@node timeout invocation
|
||||
@section @command{timeout}: Run a command with a time limit
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
#serial 11
|
||||
|
||||
dnl Misc lib-related macros for coreutils.
|
||||
|
||||
# Copyright (C) 1993-2012 Free Software Foundation, Inc.
|
||||
|
||||
# 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Written by Jim Meyering.
|
||||
|
||||
AC_DEFUN([cu_LIB_CHECK],
|
||||
[
|
||||
|
||||
# Check for libypsec.a on Dolphin M88K machines.
|
||||
AC_CHECK_LIB([ypsec], [main])
|
||||
|
||||
# m88k running dgux 5.4 needs this
|
||||
AC_CHECK_LIB([ldgc], [main])
|
||||
|
||||
# The -lsun library is required for YP support on Irix-4.0.5 systems.
|
||||
# m88k/svr3 DolphinOS systems using YP need -lypsec for id.
|
||||
AC_SEARCH_LIBS([yp_match], [sun ypsec])
|
||||
|
||||
# SysV needs -lsec, older versions of Linux need -lshadow for
|
||||
# shadow passwords. UnixWare 7 needs -lgen.
|
||||
AC_SEARCH_LIBS([getspnam], [shadow sec gen])
|
||||
|
||||
AC_CHECK_HEADERS([shadow.h])
|
||||
|
||||
# Requirements for su.c.
|
||||
shadow_includes="\
|
||||
$ac_includes_default
|
||||
#if HAVE_SHADOW_H
|
||||
# include <shadow.h>
|
||||
#endif
|
||||
"
|
||||
AC_CHECK_MEMBERS([struct spwd.sp_pwdp],,,[$shadow_includes])
|
||||
AC_CHECK_FUNCS([getspnam])
|
||||
|
||||
# SCO-ODT-3.0 is reported to need -lufc for crypt.
|
||||
# NetBSD needs -lcrypt for crypt.
|
||||
LIB_CRYPT=
|
||||
cu_saved_libs="$LIBS"
|
||||
AC_SEARCH_LIBS([crypt], [ufc crypt],
|
||||
[test "$ac_cv_search_crypt" = "none required" ||
|
||||
LIB_CRYPT="$ac_cv_search_crypt"])
|
||||
LIBS="$cu_saved_libs"
|
||||
AC_SUBST([LIB_CRYPT])
|
||||
])
|
1
man/.gitignore
vendored
1
man/.gitignore
vendored
@ -76,7 +76,6 @@ split.1
|
||||
stat.1
|
||||
stdbuf.1
|
||||
stty.1
|
||||
su.1
|
||||
sum.1
|
||||
sync.1
|
||||
tac.1
|
||||
|
@ -110,7 +110,6 @@ split.1: $(common_dep) $(srcdir)/split.x ../src/split.c
|
||||
stat.1: $(common_dep) $(srcdir)/stat.x ../src/stat.c
|
||||
stdbuf.1: $(common_dep) $(srcdir)/stdbuf.x ../src/stdbuf.c
|
||||
stty.1: $(common_dep) $(srcdir)/stty.x ../src/stty.c
|
||||
su.1: $(common_dep) $(srcdir)/su.x ../src/su.c
|
||||
sum.1: $(common_dep) $(srcdir)/sum.x ../src/sum.c
|
||||
sync.1: $(common_dep) $(srcdir)/sync.x ../src/sync.c
|
||||
tac.1: $(common_dep) $(srcdir)/tac.x ../src/tac.c
|
||||
@ -192,7 +191,7 @@ ASSORT = LC_ALL=C sort
|
||||
|
||||
# Ensure that for each .x file in this directory, there is a
|
||||
# corresponding .1 file in the definition of $(dist_man1_MANS) above.
|
||||
# But since that expansion usually lacks programs like su and arch,
|
||||
# But since that expansion usually lacks programs like arch and hostname,
|
||||
# add them here manually.
|
||||
.PHONY: check-x-vs-1
|
||||
check-x-vs-1:
|
||||
|
4
man/su.x
4
man/su.x
@ -1,4 +0,0 @@
|
||||
[NAME]
|
||||
su \- run a shell with substitute user and group IDs
|
||||
[DESCRIPTION]
|
||||
.\" Add any additional description here
|
@ -118,7 +118,6 @@ src/split.c
|
||||
src/stat.c
|
||||
src/stdbuf.c
|
||||
src/stty.c
|
||||
src/su.c
|
||||
src/sum.c
|
||||
src/sync.c
|
||||
src/system.h
|
||||
|
@ -19,7 +19,7 @@ my @valid = qw(
|
||||
mv nice nl nohup nproc od paste pathchk pinky pr printenv printf
|
||||
ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum
|
||||
sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty
|
||||
su sum sync tac tail tee test timeout touch tr true truncate tsort
|
||||
sum sync tac tail tee test timeout touch tr true truncate tsort
|
||||
tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
|
||||
|
||||
copy gnulib tests maint doc build scripts
|
||||
|
1
src/.gitignore
vendored
1
src/.gitignore
vendored
@ -87,7 +87,6 @@ split
|
||||
stat
|
||||
stdbuf
|
||||
stty
|
||||
su
|
||||
sum
|
||||
sync
|
||||
tac
|
||||
|
@ -21,7 +21,7 @@
|
||||
# Hence, if you want to install programs from this list anyway, say A and B,
|
||||
# use --enable-install-program=A,B
|
||||
no_install__progs = \
|
||||
arch hostname su
|
||||
arch hostname
|
||||
|
||||
build_if_possible__progs = \
|
||||
chroot \
|
||||
@ -32,7 +32,6 @@ build_if_possible__progs = \
|
||||
pinky \
|
||||
stdbuf \
|
||||
stty \
|
||||
su \
|
||||
uptime \
|
||||
users \
|
||||
who
|
||||
@ -164,7 +163,7 @@ noinst_HEADERS = \
|
||||
EXTRA_DIST = dcgen dircolors.hin tac-pipe.c \
|
||||
wheel-gen.pl extract-magic c99-to-c89.diff
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES = $(SCRIPTS) su
|
||||
CLEANFILES = $(SCRIPTS)
|
||||
|
||||
# Also remove these sometimes-built programs.
|
||||
# For example, even when excluded, they're built via _sc_check-AUTHORS.
|
||||
@ -268,7 +267,6 @@ split_LDADD = $(LDADD)
|
||||
stat_LDADD = $(LDADD)
|
||||
stdbuf_LDADD = $(LDADD)
|
||||
stty_LDADD = $(LDADD)
|
||||
su_LDADD = $(LDADD)
|
||||
sum_LDADD = $(LDADD)
|
||||
sync_LDADD = $(LDADD)
|
||||
tac_LDADD = $(LDADD)
|
||||
@ -357,9 +355,6 @@ factor_LDADD += $(LIB_GMP)
|
||||
# for getloadavg
|
||||
uptime_LDADD += $(GETLOADAVG_LIBS)
|
||||
|
||||
# for crypt
|
||||
su_LDADD += $(LIB_CRYPT)
|
||||
|
||||
# for various ACL functions
|
||||
copy_LDADD += $(LIB_ACL)
|
||||
ls_LDADD += $(LIB_ACL)
|
||||
@ -402,60 +397,6 @@ RELEASE_YEAR = \
|
||||
`sed -n '/.*COPYRIGHT_YEAR = \([0-9][0-9][0-9][0-9]\) };/s//\1/p' \
|
||||
$(top_srcdir)/lib/version-etc.c`
|
||||
|
||||
all-local: su$(EXEEXT)
|
||||
|
||||
installed_su = $(DESTDIR)$(bindir)/`echo su|sed '$(transform)'`
|
||||
|
||||
setuid_root_mode = a=rx,u+s
|
||||
|
||||
install_su = \
|
||||
if test "$(INSTALL_SU)" = yes; then \
|
||||
p=su; \
|
||||
echo " $(INSTALL_PROGRAM) $$p $(installed_su)"; \
|
||||
$(INSTALL_PROGRAM) $$p $(installed_su); \
|
||||
echo " chown root $(installed_su)"; \
|
||||
chown root $(installed_su); \
|
||||
echo " chmod $(setuid_root_mode) $(installed_su)"; \
|
||||
chmod $(setuid_root_mode) $(installed_su); \
|
||||
else \
|
||||
:; \
|
||||
fi
|
||||
|
||||
install-root: su$(EXEEXT)
|
||||
@$(install_su)
|
||||
|
||||
install-exec-hook: su$(EXEEXT)
|
||||
@if test "$(INSTALL_SU)" = yes; then \
|
||||
TMPFILE=$(DESTDIR)$(bindir)/.su-$$$$; \
|
||||
rm -f $$TMPFILE; \
|
||||
echo > $$TMPFILE; \
|
||||
## See if we can create a setuid root executable in $(bindir).
|
||||
## If not, then don't even try to install su.
|
||||
can_create_suid_root_executable=no; \
|
||||
chown root $$TMPFILE > /dev/null 2>&1 \
|
||||
&& chmod $(setuid_root_mode) $$TMPFILE > /dev/null 2>&1 \
|
||||
&& can_create_suid_root_executable=yes; \
|
||||
rm -f $$TMPFILE; \
|
||||
if test $$can_create_suid_root_executable = yes; then \
|
||||
$(install_su); \
|
||||
else \
|
||||
echo "WARNING: insufficient access; not installing su"; \
|
||||
echo "NOTE: to install su, run 'make install-root' as root"; \
|
||||
rm -f $(installed_su); \
|
||||
fi; \
|
||||
else :; \
|
||||
fi
|
||||
|
||||
uninstall-local:
|
||||
# Remove su only if it's one we installed.
|
||||
@if test "$(INSTALL_SU)" = yes; then \
|
||||
if grep '$(PACKAGE_NAME)' $(installed_su) > /dev/null 2>&1; then \
|
||||
echo " rm -f $(installed_su)"; \
|
||||
rm -f $(installed_su); \
|
||||
else :; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
copy_sources = copy.c cp-hash.c extent-scan.c extent-scan.h
|
||||
|
||||
# Use 'ginstall' in the definition of PROGRAMS and in dependencies to avoid
|
||||
|
520
src/su.c
520
src/su.c
@ -1,520 +0,0 @@
|
||||
/* su for GNU. Run a shell with substitute user and group IDs.
|
||||
Copyright (C) 1992-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* 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.
|
||||
|
||||
This program intentionally does not support a "wheel group" that
|
||||
restricts who can su to UID 0 accounts. RMS considers that to
|
||||
be fascist.
|
||||
|
||||
Compile-time options:
|
||||
-DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
|
||||
-DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
|
||||
|
||||
-DSYSLOG_NON_ROOT Log all su's, not just those to root (UID 0).
|
||||
Never logs attempted su's to nonexistent accounts.
|
||||
|
||||
Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "getpass.h"
|
||||
|
||||
#if HAVE_SYSLOG_H && HAVE_SYSLOG
|
||||
# include <syslog.h>
|
||||
#else
|
||||
# undef SYSLOG_SUCCESS
|
||||
# undef SYSLOG_FAILURE
|
||||
# undef SYSLOG_NON_ROOT
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ENDGRENT
|
||||
# define endgrent() ((void) 0)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ENDPWENT
|
||||
# define endpwent() ((void) 0)
|
||||
#endif
|
||||
|
||||
#if HAVE_SHADOW_H
|
||||
# include <shadow.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
|
||||
/* The official name of this program (e.g., no 'g' prefix). */
|
||||
#define PROGRAM_NAME "su"
|
||||
|
||||
#define AUTHORS proper_name ("David MacKenzie")
|
||||
|
||||
#if HAVE_PATHS_H
|
||||
# include <paths.h>
|
||||
#endif
|
||||
|
||||
/* The default PATH for simulated logins to non-superuser accounts. */
|
||||
#ifdef _PATH_DEFPATH
|
||||
# define DEFAULT_LOGIN_PATH _PATH_DEFPATH
|
||||
#else
|
||||
# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"
|
||||
#endif
|
||||
|
||||
/* The default PATH for simulated logins to superuser accounts. */
|
||||
#ifdef _PATH_DEFPATH_ROOT
|
||||
# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT
|
||||
#else
|
||||
# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"
|
||||
#endif
|
||||
|
||||
/* 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"
|
||||
|
||||
char *crypt (char const *key, char const *salt);
|
||||
|
||||
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;
|
||||
|
||||
static struct option const longopts[] =
|
||||
{
|
||||
{"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'},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
{GETOPT_VERSION_OPTION_DECL},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Add NAME=VAL to the environment, checking for out of memory errors. */
|
||||
|
||||
static void
|
||||
xsetenv (char const *name, char const *val)
|
||||
{
|
||||
size_t namelen = strlen (name);
|
||||
size_t vallen = strlen (val);
|
||||
char *string = xmalloc (namelen + 1 + vallen + 1);
|
||||
strcpy (string, name);
|
||||
string[namelen] = '=';
|
||||
strcpy (string + namelen + 1, val);
|
||||
if (putenv (string) != 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
|
||||
#if defined SYSLOG_SUCCESS || defined SYSLOG_FAILURE
|
||||
/* 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;
|
||||
|
||||
# ifndef SYSLOG_NON_ROOT
|
||||
if (pw->pw_uid)
|
||||
return;
|
||||
# endif
|
||||
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. */
|
||||
errno = 0;
|
||||
uid_t ruid = getuid ();
|
||||
uid_t NO_UID = -1;
|
||||
struct passwd *pwd = (ruid == NO_UID && errno ? NULL : getpwuid (ruid));
|
||||
old_user = (pwd ? pwd->pw_name : "");
|
||||
}
|
||||
tty = ttyname (STDERR_FILENO);
|
||||
if (!tty)
|
||||
tty = "none";
|
||||
/* 4.2BSD openlog doesn't have the third parameter. */
|
||||
openlog (last_component (program_name), 0
|
||||
# ifdef LOG_AUTH
|
||||
, LOG_AUTH
|
||||
# endif
|
||||
);
|
||||
syslog (LOG_NOTICE,
|
||||
# ifdef SYSLOG_NON_ROOT
|
||||
"%s(to %s) %s on %s",
|
||||
# else
|
||||
"%s%s on %s",
|
||||
# endif
|
||||
successful ? "" : "FAILED SU ",
|
||||
# ifdef SYSLOG_NON_ROOT
|
||||
new_user,
|
||||
# endif
|
||||
old_user, tty);
|
||||
closelog ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ask the user for a password.
|
||||
Return true if the user gives the correct password for entry PW,
|
||||
false if not. Return true without asking for a password if run by UID 0
|
||||
or if PW has an empty password. */
|
||||
|
||||
static bool
|
||||
correct_password (const struct passwd *pw)
|
||||
{
|
||||
char *unencrypted, *encrypted, *correct;
|
||||
#if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
|
||||
/* Shadow passwd stuff for SVR3 and maybe other systems. */
|
||||
struct spwd *sp = getspnam (pw->pw_name);
|
||||
|
||||
endspent ();
|
||||
if (sp)
|
||||
correct = sp->sp_pwdp;
|
||||
else
|
||||
#endif
|
||||
correct = pw->pw_passwd;
|
||||
|
||||
if (getuid () == 0 || !correct || correct[0] == '\0')
|
||||
return true;
|
||||
|
||||
unencrypted = getpass (_("Password:"));
|
||||
if (!unencrypted)
|
||||
{
|
||||
error (0, 0, _("getpass: cannot open /dev/tty"));
|
||||
return false;
|
||||
}
|
||||
encrypted = crypt (unencrypted, correct);
|
||||
memset (unencrypted, 0, strlen (unencrypted));
|
||||
return STREQ (encrypted, correct);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
xsetenv ("HOME", pw->pw_dir);
|
||||
xsetenv ("SHELL", shell);
|
||||
xsetenv ("USER", pw->pw_name);
|
||||
xsetenv ("LOGNAME", pw->pw_name);
|
||||
xsetenv ("PATH", (pw->pw_uid
|
||||
? DEFAULT_LOGIN_PATH
|
||||
: DEFAULT_ROOT_LOGIN_PATH));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set HOME, SHELL, and if not becoming a super-user,
|
||||
USER and LOGNAME. */
|
||||
if (change_environment)
|
||||
{
|
||||
xsetenv ("HOME", pw->pw_dir);
|
||||
xsetenv ("SHELL", shell);
|
||||
if (pw->pw_uid)
|
||||
{
|
||||
xsetenv ("USER", pw->pw_name);
|
||||
xsetenv ("LOGNAME", pw->pw_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Become the user and group(s) specified by PW. */
|
||||
|
||||
static void
|
||||
change_identity (const struct passwd *pw)
|
||||
{
|
||||
#ifdef HAVE_INITGROUPS
|
||||
errno = 0;
|
||||
if (initgroups (pw->pw_name, pw->pw_gid) == -1)
|
||||
error (EXIT_CANCELED, errno, _("cannot set groups"));
|
||||
endgrent ();
|
||||
#endif
|
||||
if (setgid (pw->pw_gid))
|
||||
error (EXIT_CANCELED, errno, _("cannot set group id"));
|
||||
if (setuid (pw->pw_uid))
|
||||
error (EXIT_CANCELED, errno, _("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 = xnmalloc (n_args, sizeof *args);
|
||||
size_t argno = 1;
|
||||
|
||||
if (simulate_login)
|
||||
{
|
||||
char *arg0;
|
||||
char *shell_basename;
|
||||
|
||||
shell_basename = last_component (shell);
|
||||
arg0 = xmalloc (strlen (shell_basename) + 2);
|
||||
arg0[0] = '-';
|
||||
strcpy (arg0 + 1, shell_basename);
|
||||
args[0] = arg0;
|
||||
}
|
||||
else
|
||||
args[0] = last_component (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);
|
||||
error (0, errno, "%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 != '#' && STREQ (line, shell))
|
||||
{
|
||||
endusershell ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
endusershell ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
emit_try_help ();
|
||||
else
|
||||
{
|
||||
printf (_("Usage: %s [OPTION]... [-] [USER [ARG]...]\n"), program_name);
|
||||
fputs (_("\
|
||||
Change the effective user id and group id to that of USER.\n\
|
||||
\n\
|
||||
-, -l, --login make the shell a login shell\n\
|
||||
-c, --command=COMMAND pass a single COMMAND to the shell with -c\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 (HELP_OPTION_DESCRIPTION, stdout);
|
||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
||||
fputs (_("\
|
||||
\n\
|
||||
A mere - implies -l. If USER not given, assume root.\n\
|
||||
"), stdout);
|
||||
emit_ancillary_info ();
|
||||
}
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int optc;
|
||||
const char *new_user = DEFAULT_USER;
|
||||
char *command = NULL;
|
||||
char *shell = NULL;
|
||||
struct passwd *pw;
|
||||
struct passwd pw_copy;
|
||||
|
||||
initialize_main (&argc, &argv);
|
||||
set_program_name (argv[0]);
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
initialize_exit_failure (EXIT_CANCELED);
|
||||
atexit (close_stdout);
|
||||
|
||||
fast_startup = false;
|
||||
simulate_login = false;
|
||||
change_environment = true;
|
||||
|
||||
while ((optc = getopt_long (argc, argv, "c:flmps:", longopts, NULL)) != -1)
|
||||
{
|
||||
switch (optc)
|
||||
{
|
||||
case 'c':
|
||||
command = optarg;
|
||||
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_GETOPT_HELP_CHAR;
|
||||
|
||||
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
|
||||
|
||||
default:
|
||||
usage (EXIT_CANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc && STREQ (argv[optind], "-"))
|
||||
{
|
||||
simulate_login = true;
|
||||
++optind;
|
||||
}
|
||||
if (optind < argc)
|
||||
new_user = argv[optind++];
|
||||
|
||||
pw = getpwnam (new_user);
|
||||
if (! (pw && pw->pw_name && pw->pw_name[0] && pw->pw_dir && pw->pw_dir[0]
|
||||
&& pw->pw_passwd))
|
||||
error (EXIT_CANCELED, 0, _("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. GNU/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 (!correct_password (pw))
|
||||
{
|
||||
#ifdef SYSLOG_FAILURE
|
||||
log_su (pw, false);
|
||||
#endif
|
||||
error (EXIT_CANCELED, 0, _("incorrect password"));
|
||||
}
|
||||
#ifdef SYSLOG_SUCCESS
|
||||
else
|
||||
{
|
||||
log_su (pw, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
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. */
|
||||
error (0, 0, _("using restricted shell %s"), pw->pw_shell);
|
||||
shell = NULL;
|
||||
}
|
||||
shell = xstrdup (shell ? shell : pw->pw_shell);
|
||||
modify_environment (pw, shell);
|
||||
|
||||
change_identity (pw);
|
||||
if (simulate_login && chdir (pw->pw_dir) != 0)
|
||||
error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
|
||||
|
||||
/* error() flushes stderr, but does not check for write failure.
|
||||
Normally, we would catch this via our atexit() hook of
|
||||
close_stdout, but execv() gets in the way. If stderr
|
||||
encountered a write failure, there is no need to try calling
|
||||
error() again. */
|
||||
if (ferror (stderr))
|
||||
exit (EXIT_CANCELED);
|
||||
|
||||
run_shell (shell, command, argv + optind, MAX (0, argc - optind));
|
||||
}
|
@ -280,7 +280,6 @@ TESTS = \
|
||||
misc/stty-invalid \
|
||||
misc/stty-pairs \
|
||||
misc/stty-row-col \
|
||||
misc/su-fail \
|
||||
misc/sum \
|
||||
misc/sum-sysv \
|
||||
misc/tac \
|
||||
|
@ -208,7 +208,6 @@ nohup_setup () { args=--version; }
|
||||
printf_setup () { args=foo; }
|
||||
seq_setup () { args=10; }
|
||||
sleep_setup () { args=0; }
|
||||
su_setup () { args=--version; }
|
||||
stdbuf_setup () { args="-oL true"; }
|
||||
timeout_setup () { args=--version; }
|
||||
|
||||
|
@ -36,7 +36,6 @@ my %exit_status =
|
||||
nohup => 125,
|
||||
sort => 2,
|
||||
stdbuf => 125,
|
||||
su => 125,
|
||||
test => 0,
|
||||
timeout => 125,
|
||||
true => 0,
|
||||
|
@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Test su failure cases
|
||||
|
||||
# Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
# 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ ../src
|
||||
print_ver_ su
|
||||
|
||||
require_built_ su
|
||||
|
||||
# Very little that we can test without a root password
|
||||
su --- / true # unknown option
|
||||
test $? = 125 || fail=1
|
||||
su no_such_user
|
||||
test $? = 125 || fail=1
|
||||
|
||||
Exit $fail
|
Reference in New Issue
Block a user