From: Todd C. Miller Date: Sun, 19 Aug 2007 20:48:09 +0000 (+0000) Subject: Add new linebuf code to do appends of dynamically allocated strings X-Git-Tag: SUDO_1_7_0~429 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2315b317e2bfbe4f39bd349bc904fd7d4ce3bb82;p=sudo Add new linebuf code to do appends of dynamically allocated strings and word-wrapped output. Currently used for sudo's usage() and sudo -l output. Sudo usage strings are now in sudo_usage.h which is generated at configure time. --- diff --git a/Makefile.in b/Makefile.in index a7cfef659..3a07a11c6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,8 +100,8 @@ PROGS = @PROGS@ SRCS = alloc.c alloca.c check.c closefrom.c def_data.c defaults.c env.c \ error.c fileops.c find_path.c fnmatch.c getcwd.c getprogname.c \ - getspwuid.c gettime.c goodpath.c gram.c gram.y interfaces.c ldap.c \ - logging.c match.c mkstemp.c memrchr.c parse.c pwutil.c \ + getspwuid.c gettime.c goodpath.c gram.c gram.y interfaces.c lbuf.c \ + ldap.c logging.c match.c mkstemp.c memrchr.c parse.c pwutil.c \ set_perms.c sigaction.c snprintf.c strcasecmp.c strerror.c strlcat.c \ strlcpy.c sudo.c sudo_noexec.c sudo_edit.c testsudoers.c tgetpass.c \ toke.c toke.l tsgetgrpw.c utimes.c visudo.c zero_bytes.c redblack.c \ @@ -113,7 +113,7 @@ AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ auth/sudo_auth.c HDRS = compat.h def_data.h defaults.h error.h ins_2001.h ins_classic.h \ - ins_csops.h ins_goons.h insults.h interfaces.h logging.h parse.h \ + ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h logging.h parse.h \ sudo.h gram.h version.h auth/sudo_auth.h emul/fnmatch.h emul/utime.h \ redblack.h @@ -123,8 +123,8 @@ COMMON_OBJS = alias.o alloc.o defaults.o error.o gram.o match.o toke.o \ redblack.o zero_bytes.o SUDO_OBJS = check.o env.o getspwuid.o gettime.o goodpath.o fileops.o \ - find_path.o interfaces.o logging.o parse.o pwutil.o set_perms.o \ - sudo.o sudo_edit.o tgetpass.o @SUDO_OBJS@ $(AUTH_OBJS) \ + find_path.o interfaces.o lbuf.o logging.o parse.o pwutil.o \ + set_perms.o sudo.o sudo_edit.o tgetpass.o @SUDO_OBJS@ $(AUTH_OBJS) \ $(COMMON_OBJS) VISUDO_OBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o pwutil.o \ @@ -143,7 +143,7 @@ DISTFILES = $(SRCS) $(HDRS) BUGS ChangeLog HISTORY INSTALL INSTALL.configure \ def_data.in indent.pro install-sh ltmain.sh mkdefaults \ mkinstalldirs pathnames.h.in sample.pam sample.syslog.conf \ sample.sudoers schema.OpenLDAP schema.iPlanet sudo.cat \ - sudo.man.in sudo.pod sudo.psf sudoers sudoers.cat \ + sudo.man.in sudo.pod sudo.psf sudo_usage.h.in sudoers sudoers.cat \ sudoers.man.in sudoers.pod sudoers2ldif visudo.cat \ visudo.man.in visudo.pod auth/API @@ -253,6 +253,8 @@ interfaces.o: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/interfaces.c ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c +lbuf.o: $(srcdir)/lbuf.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/lbuf.c logging.o: $(srcdir)/logging.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/logging.c match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/interfaces.h $(devdir)/gram.h @@ -283,7 +285,7 @@ strlcat.o: $(srcdir)/strlcat.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcat.c strlcpy.o: $(srcdir)/strlcpy.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcpy.c -sudo.o: $(srcdir)/sudo.c $(SUDODEP) $(srcdir)/interfaces.h $(srcdir)/version.h +sudo.o: $(srcdir)/sudo.c $(SUDODEP) sudo_usage.h $(srcdir)/interfaces.h $(srcdir)/version.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo.c sudo_edit.o: $(srcdir)/sudo_edit.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_edit.c diff --git a/configure b/configure index 18ad293f6..76f9b55ed 100755 --- a/configure +++ b/configure @@ -458,7 +458,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS LIBTOOL CFLAGS PROGS CPPFLAGS LDFLAGS SUDO_LDFLAGS SUDO_OBJS SUDO_LIBS NET_LIBS AFS_LIBS OSDEFS AUTH_OBJS MANTYPE MAN_POSTINSTALL SUDOERS_MODE SUDOERS_UID SUDOERS_GID DEV devdir mansectsu mansectform mansrcdir NOEXECDIR noexec_file INSTALL_NOEXEC DONT_LEAK_PATH_INFO timedir timeout password_timeout sudo_umask passprompt long_otp_prompt lecture logfac goodpri badpri loglen ignore_dot mail_no_user mail_no_host mail_no_perms mailto mailsub badpass_message fqdn runas_default env_editor passwd_tries tty_tickets insults root_sudo path_info EGREPPROG CC ac_ct_CC EXEEXT OBJEXT CPP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SED EGREP FGREP GREP LD NM LN_S AR ac_ct_AR STRIP ac_ct_STRIP RANLIB ac_ct_RANLIB lt_ECHO UNAMEPROG TRPROG NROFFPROG YACC LIBOBJS ALLOCA KRB5CONFIG LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS LIBTOOL CFLAGS PROGS CPPFLAGS LDFLAGS SUDO_LDFLAGS SUDO_OBJS SUDO_LIBS NET_LIBS AFS_LIBS OSDEFS AUTH_OBJS MANTYPE MAN_POSTINSTALL SUDOERS_MODE SUDOERS_UID SUDOERS_GID DEV devdir mansectsu mansectform mansrcdir NOEXECDIR noexec_file INSTALL_NOEXEC DONT_LEAK_PATH_INFO BSDAUTH_USAGE LOGINCAP_USAGE timedir timeout password_timeout sudo_umask passprompt long_otp_prompt lecture logfac goodpri badpri loglen ignore_dot mail_no_user mail_no_host mail_no_perms mailto mailsub badpass_message fqdn runas_default env_editor passwd_tries tty_tickets insults root_sudo path_info EGREPPROG CC ac_ct_CC EXEEXT OBJEXT CPP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SED EGREP FGREP GREP LD NM LN_S AR ac_ct_AR STRIP ac_ct_STRIP RANLIB ac_ct_RANLIB lt_ECHO UNAMEPROG TRPROG NROFFPROG YACC LIBOBJS ALLOCA KRB5CONFIG LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -1046,7 +1046,6 @@ Optional Packages: --with-DCE enable DCE support --with-logincap enable BSD login class support --with-bsdauth enable BSD authentication support - --with-systrace[=DIR] enable systrace(4) support --with-project enable Solaris project support --without-lecture don't print lecture for first-time sudoer --with-logging log via syslog, file, or both @@ -1608,6 +1607,8 @@ echo "$as_me: Configuring Sudo version 1.7" >&6;} + + @@ -2202,17 +2203,6 @@ esac fi; -# Check whether --with-systrace or --without-systrace was given. -if test "${with_systrace+set}" = set; then - withval="$with_systrace" - case $with_systrace in - no) with_systrace="" - ;; - *) ;; -esac -fi; - - # Check whether --with-project or --without-project was given. if test "${with_project+set}" = set; then withval="$with_project" @@ -7102,7 +7092,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 7105 "configure" +#line 7095 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -7200,7 +7190,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 7203 "configure" +#line 7193 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -7349,7 +7339,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - $ECHO '#line 7352 "configure"' > conftest.$ac_ext + $ECHO '#line 7342 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8000,11 +7990,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8003: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7993: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8007: \$? = $ac_status" >&5 + echo "$as_me:7997: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -8275,11 +8265,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8278: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8268: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8282: \$? = $ac_status" >&5 + echo "$as_me:8272: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -8372,11 +8362,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8375: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8365: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8379: \$? = $ac_status" >&5 + echo "$as_me:8369: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8426,11 +8416,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8429: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8419: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8433: \$? = $ac_status" >&5 + echo "$as_me:8423: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13063,7 +13053,7 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF - + LOGINCAP_USAGE='[-c class|-] ' fi done @@ -18679,182 +18669,6 @@ echo "${ECHO_T}$sudo_cv___progname" >&6 fi done -if test -n "$with_systrace"; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SYSTRACE 1 -_ACEOF - - if test "$with_systrace" = "yes"; then - - - -for ac_header in dev/systrace.h sys/systrace.h linux/systrace.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - break -fi - -done - - else - CPPFLAGS="$CPPFLAGS -I${with_systrace}" - fi - SUDO_OBJS="${SUDO_OBJS} mon_systrace.o" - -for ac_func in setproctitle -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - -fi if test -n "$with_kerb4"; then cat >>confdefs.h <<\_ACEOF #define HAVE_KERB4 1 @@ -21885,6 +21699,7 @@ else AUTH_OBJS="$AUTH_OBJS bsdauth.o" fi + BSDAUTH_USAGE='[-a auth_type] ' else - fi @@ -22957,7 +22772,7 @@ _ACEOF exec_prefix="$oexec_prefix" fi - ac_config_files="$ac_config_files Makefile sudo.man visudo.man sudoers.man" + ac_config_files="$ac_config_files Makefile sudo.man visudo.man sudoers.man sudo_usage.h" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -23643,6 +23458,7 @@ do "sudo.man" ) CONFIG_FILES="$CONFIG_FILES sudo.man" ;; "visudo.man" ) CONFIG_FILES="$CONFIG_FILES visudo.man" ;; "sudoers.man" ) CONFIG_FILES="$CONFIG_FILES sudoers.man" ;; + "sudo_usage.h" ) CONFIG_FILES="$CONFIG_FILES sudo_usage.h" ;; "libtool" ) CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "pathnames.h" ) CONFIG_HEADERS="$CONFIG_HEADERS pathnames.h" ;; @@ -23757,6 +23573,8 @@ s,@NOEXECDIR@,$NOEXECDIR,;t t s,@noexec_file@,$noexec_file,;t t s,@INSTALL_NOEXEC@,$INSTALL_NOEXEC,;t t s,@DONT_LEAK_PATH_INFO@,$DONT_LEAK_PATH_INFO,;t t +s,@BSDAUTH_USAGE@,$BSDAUTH_USAGE,;t t +s,@LOGINCAP_USAGE@,$LOGINCAP_USAGE,;t t s,@timedir@,$timedir,;t t s,@timeout@,$timeout,;t t s,@password_timeout@,$password_timeout,;t t @@ -24957,8 +24775,6 @@ fi - - diff --git a/configure.in b/configure.in index ad6bda141..1e612f083 100644 --- a/configure.in +++ b/configure.in @@ -40,6 +40,8 @@ AC_SUBST(NOEXECDIR) AC_SUBST(noexec_file) AC_SUBST(INSTALL_NOEXEC) AC_SUBST(DONT_LEAK_PATH_INFO) +AC_SUBST(BSDAUTH_USAGE) +AC_SUBST(LOGINCAP_USAGE) dnl dnl Variables that get substituted in docs (not overridden by environment) dnl @@ -1626,7 +1628,7 @@ if test "$OS" != "ultrix"; then fi fi if test ${with_logincap-'no'} != "no"; then - AC_CHECK_HEADERS(login_cap.h) + AC_CHECK_HEADERS(login_cap.h, [LOGINCAP_USAGE='[[-c class|-]] ']) fi if test ${with_project-'no'} != "no"; then AC_CHECK_HEADER(project.h, AC_DEFINE(HAVE_PROJECT_H) @@ -2159,7 +2161,8 @@ dnl if test ${with_bsdauth-'no'} != "no"; then if test X"$with_bsdauth" != X"maybe" -o X"$AUTH_EXCL" = X""; then AC_CHECK_HEADER(bsd_auth.h, AC_DEFINE(HAVE_BSD_AUTH_H) - [SUDO_ADD_AUTH([BSD authentication], [bsdauth.o], [true])], -) + [SUDO_ADD_AUTH([BSD authentication], [bsdauth.o], [true])] + [BSDAUTH_USAGE='[[-a auth_type]] '], -) fi fi @@ -2314,7 +2317,7 @@ fi dnl dnl Substitute into the Makefile and man pages dnl -AC_CONFIG_FILES([Makefile sudo.man visudo.man sudoers.man]) +AC_CONFIG_FILES([Makefile sudo.man visudo.man sudoers.man sudo_usage.h]) AC_OUTPUT dnl diff --git a/lbuf.c b/lbuf.c new file mode 100644 index 000000000..4266e070a --- /dev/null +++ b/lbuf.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#include + +#include "sudo.h" +#include "lbuf.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo$"; +#endif /* lint */ + +#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ) +# define TIOCGSIZE TIOCGWINSZ +# define ttysize winsize +# define ts_cols ws_col +#endif + +int +get_ttycols() +{ + char *p; + int cols; +#ifdef TIOCGSIZE + struct ttysize win; + + if (ioctl(STDERR_FILENO, TIOCGSIZE, &win) == 0 && win.ts_cols != 0) + return((int)win.ts_cols); +#endif + + /* Fall back on $COLUMNS. */ + if ((p = getenv("COLUMNS")) == NULL || (cols = atoi(p)) <= 0) + cols = 80; + return(cols); +} + +void +lbuf_init(lbuf, buf, indent, continuation) + struct lbuf *lbuf; + char *buf; + int indent; + int continuation; +{ + lbuf->continuation = continuation; + lbuf->indent = indent; + lbuf->len = 0; + lbuf->size = 0; + lbuf->buf = NULL; +} + +void +lbuf_destroy(lbuf) + struct lbuf *lbuf; +{ + efree(lbuf->buf); + lbuf->buf = NULL; +} + +/* + * Append strings to the buffer, expanding it as needed. + */ +void +#ifdef __STDC__ +lbuf_append(struct lbuf *lbuf, ...) +#else +lbuf_append(lbuf, va_alist) + struct lbuf *lbuf; + va_dcl +#endif +{ + va_list ap; + int len = 0; + char *s; + +#ifdef __STDC__ + va_start(ap, lbuf); +#else + va_start(ap); +#endif + while ((s = va_arg(ap, char *)) != NULL) + len += strlen(s); + va_end(ap); + + /* Expand buffer as needed. */ + if (lbuf->len + len >= lbuf->size) { + do { + lbuf->size += 256; + } while (lbuf->len + len >= lbuf->size); + lbuf->buf = erealloc(lbuf->buf, lbuf->size); + } + +#ifdef __STDC__ + va_start(ap, lbuf); +#else + va_start(ap); +#endif + /* Append each string. */ + while ((s = va_arg(ap, char *)) != NULL) { + len = strlen(s); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + } + lbuf->buf[lbuf->len] = '\0'; + va_end(ap); +} + +/* + * Print the buffer with word wrap based on the tty width. + * The lbuf is reset on return. + */ +void +lbuf_print(lbuf) + struct lbuf *lbuf; +{ + char *cp; + int i, have, contlen; + static int cols = -1; + + if (cols == -1) + cols = get_ttycols(); + contlen = lbuf->continuation ? 2 : 0; + + /* For very small widths just give up... */ + if (cols <= lbuf->indent + contlen + 20) { + puts(lbuf->buf); + goto done; + } + + /* + * Print the buffer, splitting the line as needed on a word + * boundary. + */ + cp = lbuf->buf; + have = cols; + while (cp != NULL && *cp != '\0') { + char *ep = NULL; + int need = lbuf->len - (int)(cp - lbuf->buf); + + if (need > have) { + have -= contlen; /* subtract for continuation char */ + if ((ep = memrchr(cp, ' ', have)) == NULL) + ep = memchr(cp + have, ' ', need - have); + if (ep != NULL) + need = (int)(ep - cp); + } + if (cp != lbuf->buf) { + /* indent continued lines */ + for (i = 0; i < lbuf->indent; i++) + putchar(' '); + } + fwrite(cp, need, 1, stdout); + cp = ep; + + /* + * If there is more to print, reset have, incremement cp past + * the whitespace, and print a line continuaton char if needed. + */ + if (cp != NULL) { + have = cols - lbuf->indent; + do { + cp++; + } while (isspace((unsigned char)*cp)); + if (lbuf->continuation) { + putchar(' '); + putchar(lbuf->continuation); + } + } + putchar('\n'); + } + +done: + lbuf->len = 0; /* reset the buffer for re-use. */ +} diff --git a/lbuf.h b/lbuf.h new file mode 100644 index 000000000..a9e1a05e7 --- /dev/null +++ b/lbuf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Sudo$" + */ + +#ifndef _SUDO_LBUF_H +#define _SUDO_LBUF_H + +/* + * Line buffer struct. + */ +struct lbuf { + char *buf; + int continuation; + int indent; + int len; + int size; +}; + +void lbuf_init __P((struct lbuf *, char *, int, int)); +void lbuf_destroy __P((struct lbuf *)); +void lbuf_append __P((struct lbuf *, ...)); +void lbuf_print __P((struct lbuf *)); + +#endif /* _SUDO_LBUF_H */ diff --git a/parse.c b/parse.c index 6db0d15bd..287ea0887 100644 --- a/parse.c +++ b/parse.c @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef STDC_HEADERS # include @@ -46,6 +45,7 @@ #include "sudo.h" #include "parse.h" +#include "lbuf.h" #include #ifndef lint @@ -61,19 +61,9 @@ extern struct defaults *defaults; /* * Local prototypes. */ -static void print_member __P((char *, int, int, int)); +static void print_member __P((struct lbuf *, char *, int, int, int)); static void display_defaults __P((struct passwd *)); static void display_bound_defaults __P((int)); -static void print_wrap __P((int, int, int, ...)); - -#define print_def(a) print_wrap(4, 0, 1, a); -#define print_def2(a, b) print_wrap(4, 0, 2, a, b); -#define print_def3(a, b, c) print_wrap(4, 0, 3, a, b, c); -#define print_def4(a, b, c, d) print_wrap(4, 0, 4, a, b, c, d); -#define print_priv(a) print_wrap(8, '\\', 1, a); -#define print_priv2(a, b) print_wrap(8, '\\', 2, a, b); -#define print_priv3(a, b, c) print_wrap(8, '\\', 3, a, b, c); -#define print_priv4(a, b, c, d) print_wrap(8, '\\', 4, a, b, c, d); /* * Parse the specified sudoers file. @@ -208,6 +198,7 @@ display_privs(v, pw) VOID *v; struct passwd *pw; { + struct lbuf lbuf; struct cmndspec *cs; struct member *m; struct privilege *priv; @@ -231,8 +222,9 @@ display_privs(v, pw) if (!def_ignore_local_sudoers) { display_defaults(pw); - print_priv3("User ", pw->pw_name, - " may run the following commands on this host:\n"); + lbuf_init(&lbuf, NULL, 8, '\\'); + printf("User %s may run the following commands on this host:\n", + pw->pw_name); for (us = userspecs; us != NULL; us = us->next) { if (user_matches(pw, us->user) != ALLOW || @@ -243,39 +235,45 @@ display_privs(v, pw) tags.noexec = def_noexec; tags.setenv = def_setenv; tags.nopasswd = !def_authenticate; - print_priv(" "); + lbuf_append(&lbuf, " ", NULL); for (cs = priv->cmndlist; cs != NULL; cs = cs->next) { if (cs != priv->cmndlist) - print_priv(", "); - print_priv("("); + lbuf_append(&lbuf, ", ", NULL); + lbuf_append(&lbuf, "(", NULL); if (cs->runaslist != NULL) { for (m = cs->runaslist; m != NULL; m = m->next) { if (m != cs->runaslist) - print_priv(", "); - print_member(m->name, m->type, m->negated, RUNASALIAS); + lbuf_append(&lbuf, ", ", NULL); + print_member(&lbuf, m->name, m->type, m->negated, + RUNASALIAS); } } else { - print_priv(def_runas_default); + lbuf_append(&lbuf, def_runas_default, NULL); } - print_priv(") "); + lbuf_append(&lbuf, ") ", NULL); if (TAG_CHANGED(setenv)) { - print_priv(cs->tags.setenv ? "SETENV: " : "NOSETENV: "); + lbuf_append(&lbuf, cs->tags.setenv ? "SETENV: " : + "NOSETENV: ", NULL); tags.setenv = cs->tags.setenv; } if (TAG_CHANGED(noexec)) { - print_priv(cs->tags.noexec ? "NOEXEC: " : "EXEC: "); + lbuf_append(&lbuf, cs->tags.noexec ? "NOEXEC: " : + "EXEC: ", NULL); tags.noexec = cs->tags.noexec; } if (TAG_CHANGED(nopasswd)) { - print_priv(cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: "); + lbuf_append(&lbuf, cs->tags.nopasswd ? "NOPASSWD: " : + "PASSWD: ", NULL); tags.nopasswd = cs->tags.nopasswd; } m = cs->cmnd; - print_member(m->name, m->type, m->negated, CMNDALIAS); + print_member(&lbuf, m->name, m->type, m->negated, + CMNDALIAS); } - print_priv("\n"); + lbuf_print(&lbuf); } } + lbuf_destroy(&lbuf); } #ifdef HAVE_LDAP if (v != NULL) @@ -291,9 +289,12 @@ display_defaults(pw) struct passwd *pw; { struct defaults *d; + struct lbuf lbuf; char *prefix; int per_runas = 0, per_cmnd = 0; + lbuf_init(&lbuf, NULL, 4, 0); + for (d = defaults, prefix = NULL; d != NULL; d = d->next) { switch (d->type) { case DEFAULTS_HOST: @@ -312,20 +313,23 @@ display_defaults(pw) continue; } if (prefix == NULL) { - print_def4("Matching Defaults entries for ", pw->pw_name, - " on this host:\n", " "); - } else { - print_def(prefix); + printf("Matching Defaults entries for %s on this host:\n", + pw->pw_name); + prefix = " "; } + lbuf_append(&lbuf, prefix, NULL); if (d->val != NULL) { - print_def3(d->var, d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=", - d->val); + lbuf_append(&lbuf, d->var, d->op == '+' ? "+=" : + d->op == '-' ? "-=" : "=", d->val, NULL); } else - print_def2(d->op == FALSE ? "!" : "", d->var); + lbuf_append(&lbuf, d->op == FALSE ? "!" : "", d->var, NULL); prefix = ", "; } - if (prefix) - print_priv("\n\n"); + if (prefix) { + lbuf_print(&lbuf); + putchar('\n'); + } + lbuf_destroy(&lbuf); if (per_runas) display_bound_defaults(DEFAULTS_RUNAS); @@ -340,6 +344,7 @@ static void display_bound_defaults(dtype) int dtype; { + struct lbuf lbuf; struct defaults *d; struct member *m, *binding; char *dname, *dsep; @@ -369,29 +374,32 @@ display_bound_defaults(dtype) default: return; } - print_def3("Per-", dname, " Defaults entries:"); + lbuf_init(&lbuf, NULL, 4, 0); + printf("Per-%s Defaults entries:\n", dname); for (d = defaults, binding = NULL; d != NULL; d = d->next) { if (d->type != dtype) continue; if (d->binding != binding) { binding = d->binding; - print_def3("\n", " Defaults", dsep); + lbuf_append(&lbuf, " Defaults", dsep, NULL); for (m = binding; m != NULL; m = m->next) { if (m != binding) - print_def(","); - print_member(m->name, m->type, m->negated, atype); - print_def(" "); + lbuf_append(&lbuf, ",", NULL); + print_member(&lbuf, m->name, m->type, m->negated, atype); + lbuf_append(&lbuf, " ", NULL); } } else - print_def(", "); + lbuf_append(&lbuf, ", ", NULL); if (d->val != NULL) { - print_def3(d->var, d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=", - d->val); + lbuf_append(&lbuf, d->var, d->op == '+' ? "+=" : + d->op == '-' ? "-=" : "=", d->val, NULL); } else - print_def2(d->op == FALSE ? "!" : "", d->var); + lbuf_append(&lbuf, d->op == FALSE ? "!" : "", d->var, NULL); } - print_priv("\n\n"); + lbuf_print(&lbuf); + lbuf_destroy(&lbuf); + putchar('\n'); } /* @@ -450,7 +458,8 @@ display_cmnd(v, pw) * Print the contents of a struct member to stdout */ static void -print_member(name, type, negated, alias_type) +print_member(lbuf, name, type, negated, alias_type) + struct lbuf *lbuf; char *name; int type, negated, alias_type; { @@ -460,115 +469,26 @@ print_member(name, type, negated, alias_type) switch (type) { case ALL: - print_priv(negated ? "!ALL" : "ALL"); + lbuf_append(lbuf, negated ? "!ALL" : "ALL", NULL); break; case COMMAND: c = (struct sudo_command *) name; - print_priv4(negated ? "!" : "", c->cmnd, c->args ? " " : "", - c->args ? c->args : ""); + lbuf_append(lbuf, negated ? "!" : "", c->cmnd, c->args ? " " : "", + c->args ? c->args : "", NULL); break; case ALIAS: if ((a = find_alias(name, alias_type)) != NULL) { for (m = a->first_member; m != NULL; m = m->next) { if (m != a->first_member) - print_priv(", "); - print_member(m->name, m->type, + lbuf_append(lbuf, ", ", NULL); + print_member(lbuf, m->name, m->type, negated ? !m->negated : m->negated, alias_type); } break; } /* FALLTHROUGH */ default: - print_priv2(negated ? "!" : "", name); + lbuf_append(lbuf, negated ? "!" : "", name, NULL); break; } } - -#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ) -# define TIOCGSIZE TIOCGWINSZ -# define ttysize winsize -# define ts_cols ws_col -#endif - -int -get_ttycols() -{ - char *p; - int cols; -#ifdef TIOCGSIZE - struct ttysize win; - - if (ioctl(STDERR_FILENO, TIOCGSIZE, &win) == 0 && win.ts_cols != 0) - return((int)win.ts_cols); -#endif - - /* Fall back on $COLUMNS. */ - if ((p = getenv("COLUMNS")) == NULL || (cols = atoi(p)) <= 0) - cols = 80; - return(cols); -} - -/* - * Simplistic print function with line wrap. - * XXX - does not expand tabs, etc and only checks for newlines - * at the end of an arg. Should probably use cols-2 to leave - * room for a space and the continuation char. - */ -static void -#ifdef __STDC__ -print_wrap(int indent, int lc, int nargs, ...) -#else -print_wrap(indent, lc, nargs, va_alist) - int indent; - int lc; - int nargs; - va_dcl -#endif -{ - static int left, cols = -1; - int i, n, len; - va_list ap; - char *s = NULL; - - if (cols == -1) - left = cols = get_ttycols(); - -#ifdef __STDC__ - va_start(ap, nargs); -#else - va_start(ap); -#endif - for (len = 0, i = 1; i <= nargs; i++) { - s = va_arg(ap, char *); - if ((n = strlen(s)) > 0) - len += s[n - 1] == '\n' ? n - 1 : n; - } - va_end(ap); - - if (len > left && cols > indent && len < cols - indent) { - if (lc) - putchar(lc); /* XXX - there may not be space on the line for continuation char */ - putchar('\n'); - for (i = 0; i < indent; i++) - putchar(' '); - left = cols - indent; - } -#ifdef __STDC__ - va_start(ap, nargs); -#else - va_start(ap); -#endif - for (i = 1; i <= nargs; i++) { - s = va_arg(ap, char *); - if ((len = strlen(s)) > 0) { - fwrite(s, len, 1, stdout); - if (s[len - 1] == '\n') - left = cols; - else if (len > left) - left = 0; - else - left -= len; - } - } - va_end(ap); -} diff --git a/sudo.c b/sudo.c index 2b0c626f3..38f4dbb3d 100644 --- a/sudo.c +++ b/sudo.c @@ -93,6 +93,8 @@ #endif #include "sudo.h" +#include "sudo_usage.h" +#include "lbuf.h" #include "interfaces.h" #include "version.h" @@ -1312,71 +1314,27 @@ usage_excl(exit_val) /* * Give usage message and exit. + * The actual usage strings are in sudo_usage.h for configure substitution. */ static void usage(exit_val) int exit_val; { - char **p, **uvec[5]; - int i, linelen, linemax, ulen, plen; - static char *uvec1[] = { - " -h |", - " -K |", - " -k |", - " -L |", - " -V |", - " -v", - NULL - }; - static char *uvec2[] = { - " -l", - " [-U username]", - " [-u username|#uid]", - " [command]", - NULL - }; - static char *uvec3[] = { - " [-bEHPS]", -#ifdef HAVE_BSD_AUTH_H - " [-a auth_type]", -#endif - " [-C fd]", -#ifdef HAVE_LOGIN_CAP_H - " [-c class|-]", -#endif - " [-p prompt]", - " [-u username|#uid]", - " [VAR=value]", - " {-i | -s | }", - NULL - }; - static char *uvec4[] = { - " -e", - " [-S]", -#ifdef HAVE_BSD_AUTH_H - " [-a auth_type]", -#endif - " [-C fd]", -#ifdef HAVE_LOGIN_CAP_H - " [-c class|-]", -#endif - " [-p prompt]", - " [-u username|#uid]", - " file ...", - NULL - }; + struct lbuf lbuf; + char *uvec[5]; + int i, ulen; /* * Use usage vectors appropriate to the progname. */ if (strcmp(getprogname(), "sudoedit") == 0) { - uvec[0] = uvec4 + 1; + uvec[0] = SUDO_USAGE4 + 3; uvec[1] = NULL; } else { - uvec[0] = uvec1; - uvec[1] = uvec2; - uvec[2] = uvec3; - uvec[3] = uvec4; + uvec[0] = SUDO_USAGE1; + uvec[1] = SUDO_USAGE2; + uvec[2] = SUDO_USAGE3; + uvec[3] = SUDO_USAGE4; uvec[4] = NULL; } @@ -1384,23 +1342,12 @@ usage(exit_val) * Print usage and wrap lines as needed, depending on the * tty width. */ - ulen = (int)strlen(getprogname()) + 7; - linemax = get_ttycols(); + ulen = (int)strlen(getprogname()) + 8; + lbuf_init(&lbuf, NULL, ulen, 0); for (i = 0; uvec[i] != NULL; i++) { - printf("usage: %s", getprogname()); - linelen = linemax - ulen; - for (p = uvec[i]; *p != NULL; p++) { - plen = (int)strlen(*p); - if (linelen >= plen || linelen == linemax - ulen) { - fputs(*p, stdout); - linelen -= plen; - } else { - p--; - linelen = linemax - ulen; - printf("\n%*s", ulen, ""); - } - } - putchar('\n'); + lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL); + lbuf_print(&lbuf); } + lbuf_destroy(&lbuf); exit(exit_val); } diff --git a/sudo_usage.h.in b/sudo_usage.h.in new file mode 100644 index 000000000..b0c5c1eb9 --- /dev/null +++ b/sudo_usage.h.in @@ -0,0 +1,13 @@ +#ifndef _SUDO_USAGE_H +#define _SUDO_USAGE_H + +/* + * Usage strings for sudo. These are here because we + * need to be able to substitute values from configure. + */ +#define SUDO_USAGE1 " -h | -K | -k | -L | -V | -v" +#define SUDO_USAGE2 " -l [-U username] [-u username|#uid] [command]" +#define SUDO_USAGE3 " [-bEHPS] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-p prompt] [-u username|#uid] [VAR=value] {-i | -s | }" +#define SUDO_USAGE4 " -e [-S] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-p prompt] [-u username|#uid] file ..." + +#endif /* _SUDO_USAGE_H */