]> granicus.if.org Git - sudo/commitdiff
Add new linebuf code to do appends of dynamically allocated strings
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 19 Aug 2007 20:48:09 +0000 (20:48 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 19 Aug 2007 20:48:09 +0000 (20:48 +0000)
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.

Makefile.in
configure
configure.in
lbuf.c [new file with mode: 0644]
lbuf.h [new file with mode: 0644]
parse.c
sudo.c
sudo_usage.h.in [new file with mode: 0644]

index a7cfef65995b3c2a95e628b8cd698c3b5067efcf..3a07a11c6602bbf14bbcc81906985d9098a58f9e 100644 (file)
@@ -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
index 18ad293f60be2276a08232abe0d4da172e9ca78b..76f9b55ed8a57785f397d57c29d0ad624097e612 100755 (executable)
--- a/configure
+++ b/configure
@@ -458,7 +458,7 @@ ac_includes_default="\
 # include <unistd.h>
 #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 <sys/param.h>
-
-#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 <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#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
 
 
 
-
-
 
 
 
index ad6bda14198f04edecc671ef806c628bb0d93561..1e612f083c67f3ce67c511786193956485904147 100644 (file)
@@ -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 (file)
index 0000000..4266e07
--- /dev/null
+++ b/lbuf.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif /* HAVE_STRING_H */
+#include <ctype.h>
+
+#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 (file)
index 0000000..a9e1a05
--- /dev/null
+++ b/lbuf.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 6db0d15bd7c7ddede60dfa9ba8be06461cab1f7f..287ea0887e50e99477539435491d68595019f0a7 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -20,7 +20,6 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
-#include <sys/ioctl.h>
 #include <stdio.h>
 #ifdef STDC_HEADERS
 # include <stdlib.h>
@@ -46,6 +45,7 @@
 
 #include "sudo.h"
 #include "parse.h"
+#include "lbuf.h"
 #include <gram.h>
 
 #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 2b0c626f379e2a83bef2b0bd33be75fc4822834c..38f4dbb3dcd54975a614b4f18db0f2566f95c713 100644 (file)
--- 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 | <command>}",
-       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 (file)
index 0000000..b0c5c1e
--- /dev/null
@@ -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 | <command>}"
+#define SUDO_USAGE4 " -e [-S] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-p prompt] [-u username|#uid] file ..."
+
+#endif /* _SUDO_USAGE_H */