diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 544d21f..0000000 --- a/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -root = true - -[*] -end_of_line = lf -trim_trailing_whitespace = true -insert_final_newline = true - -[{*.c,*.h}] -indent_style = space -indent_size = 4 -tab_width = 8 diff --git a/.gitignore b/.gitignore index bb95251..7a98dc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -/config/MCONFIG -/config/config.h -/config/config.h.in -/autoconf/aclocal.m4 -/autoconf/clean.sh -/autoconf/helpers/ +/MCONFIG +/aconfig.h +/aconfig.h.in /autom4te.cache /config.log /config.status @@ -15,7 +12,5 @@ *.8 *.a *.o -*.i -*.s *~ \#* diff --git a/CHANGES b/CHANGES index 6b7b53c..6df0d97 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,3 @@ -Changes in 5.2: - Fix breakage on newer Linux when a single interface has - multiple IP addresses. - - Changes in 5.1: Add -P option to write a PID file. Patch by Ferenc Wagner. diff --git a/config/MCONFIG.in b/MCONFIG.in similarity index 100% rename from config/MCONFIG.in rename to MCONFIG.in diff --git a/Makefile b/Makefile index 2e790fd..9ff12d8 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ SUB = lib common tftp tftpd -%.build: config/MCONFIG config/config.h version.h +%.build: MCONFIG aconfig.h version.h $(MAKE) -C $(patsubst %.build, %, $@) -%.install: config/MCONFIG config/config.h version.h +%.install: MCONFIG aconfig.h version.h $(MAKE) -C $(patsubst %.install, %, $@) install %.clean: @@ -15,12 +15,12 @@ SUB = lib common tftp tftpd %.distclean: $(MAKE) -C $(patsubst %.distclean, %, $@) distclean -all: config/MCONFIG $(patsubst %, %.build, $(SUB)) +all: MCONFIG $(patsubst %, %.build, $(SUB)) tftp.build: lib.build common.build tftpd.build: lib.build common.build -install: config/MCONFIG $(patsubst %, %.install, $(SUB)) +install: MCONFIG $(patsubst %, %.install, $(SUB)) clean: localclean $(patsubst %, %.clean, $(SUB)) @@ -30,40 +30,46 @@ localclean: distclean: localdistclean $(patsubst %, %.distclean, $(SUB)) localdistclean: localclean - rm -f config/config/MCONFIG config.status config.log config/config.h *~ \#* + rm -f MCONFIG config.status config.log aconfig.h *~ \#* rm -rf *.cache find . -type f \( -name \*.orig -o -name \*.rej \) | xargs rm -f spotless: distclean - rm -f configure config/config.h.in tftp.spec + rm -f configure aconfig.h.in tftp.spec -autoconf: configure config/config.h.in +autoconf: configure aconfig.h.in -config: config/MCONFIG config/config.h +config: MCONFIG aconfig.h release: $(MAKE) autoconf $(MAKE) tftp.spec $(MAKE) distclean -config/MCONFIG: configure config/MCONFIG.in config/config.h.in +MCONFIG: configure MCONFIG.in aconfig.h.in if test -x config.status; then \ ./config.status --recheck && ./config.status ; \ else \ ./configure ; \ fi -config/config.h: config/MCONFIG +aconfig.h: MCONFIG : Generated by side effect -configure: configure.ac - sh autogen.sh +# Adding "configure" to the dependencies serializes this with running +# autoconf, because there are apparently race conditions between +# autoconf and autoheader. +aconfig.h.in: configure.in configure aclocal.m4 + rm -f aconfig.h.in aconfig.h + autoheader -config/config.h.in: configure - : Generated by side effect +configure: configure.in aclocal.m4 + rm -rf MCONFIG configure config.log aconfig.h *.cache + autoconf version.h: version echo \#define VERSION \"tftp-hpa `cat version`\" > version.h tftp.spec: tftp.spec.in version sed -e "s/@@VERSION@@/`cat version`/g" < $< > $@ || rm -f $@ + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..c07702c --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,280 @@ +dnl ----------------------------------------------------------------------- +dnl +dnl Copyright 1999-2008 H. Peter Anvin - All Rights Reserved +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation, Inc., 53 Temple Place Ste 330, +dnl Bostom MA 02111-1307, USA; either version 2 of the License, or +dnl (at your option) any later version; incorporated herein by reference. +dnl +dnl ----------------------------------------------------------------------- + +dnl -------------------------------------------------------------------------- +dnl PA_ADD_CFLAGS() +dnl +dnl Attempt to add the given option to CFLAGS, if it doesn't break compilation +dnl -------------------------------------------------------------------------- +AC_DEFUN(PA_ADD_CFLAGS, +[AC_MSG_CHECKING([if $CC accepts $1]) + pa_add_cflags__old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_TRY_LINK([#include ], + [printf("Hello, World!\n");], + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no]) + CFLAGS="$pa_add_cflags__old_cflags")]) + +dnl -------------------------------------------------------------------------- +dnl PA_SIGSETJMP +dnl +dnl Do we have sigsetjmp/siglongjmp? (AC_CHECK_FUNCS doesn't seem to work +dnl for these particular functions.) +dnl -------------------------------------------------------------------------- +AC_DEFUN(PA_SIGSETJMP, +[AC_MSG_CHECKING([for sigsetjmp]) + AC_TRY_LINK([ +#ifdef HAVE_SETJMP_H +#include +#endif], + [sigjmp_buf buf; + sigsetjmp(buf,1); + siglongjmp(buf,2);], + AC_MSG_RESULT([yes]) + $1, + AC_MSG_RESULT([no]) + $2)]) + +dnl -------------------------------------------------------------------------- +dnl PA_MSGHDR_MSG_CONTROL +dnl +dnl Does struct msghdr have the msg_control field? +dnl -------------------------------------------------------------------------- +AH_TEMPLATE([HAVE_MSGHDR_MSG_CONTROL], +[Define if struct msghdr has the msg_control field.]) + +AC_DEFUN(PA_MSGHDR_MSG_CONTROL, + [AC_CHECK_MEMBER(struct msghdr.msg_control, + [AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL)], + [], + [ +#include +#include +#include + ])]) + +dnl ------------------------------------------------------------------------ +dnl PA_STRUCT_IN_PKTINFO +dnl +dnl Look for definition of struct in_pktinfo, which at least has an +dnl ipi_addr member. Some versions of glibc lack struct in_pktinfo; +dnl if so we need to include the definition ourselves -- but we only +dnl want to do that if absolutely necessary! +dnl ------------------------------------------------------------------------ +AH_TEMPLATE([HAVE_STRUCT_IN_PKTINFO], +[Define if struct in_pktinfo is defined.]) + +AC_DEFUN(PA_STRUCT_IN_PKTINFO, + [AC_CHECK_MEMBER(struct in_pktinfo.ipi_addr, + [AC_DEFINE(HAVE_STRUCT_IN_PKTINFO)], + [], + [ +#include +#include +#include +#include +#include +#include + ])]) + + +dnl ------------------------------------------------------------------------ +dnl PA_STRUCT_SOCKADDR_IN6 +dnl +dnl Look for definition of struct sockaddr_in6, which at least has an +dnl sin6_addr member +dnl +AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_IN6], +[Define if struct sockaddr_in6 is defined.]) + +AC_DEFUN(PA_STRUCT_SOCKADDR_IN6, + [AC_CHECK_MEMBER(struct sockaddr_in6.sin6_addr, + [ + AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6) + HAVE_INET6=true; + ], + [ + HAVE_INET6=false; + ], + [ +#include +#include +#include +#include + ])]) + +dnl ------------------------------------------------------------------------ +dnl PA_STRUCT_ADDRINFO +dnl +dnl Look for definition of struct addrinfo, which at least has an +dnl ai_addr member +dnl +AH_TEMPLATE([HAVE_STRUCT_ADDRINFO], +[Define if struct addrinfo is defined.]) + +AC_DEFUN(PA_STRUCT_ADDRINFO, + [AC_CHECK_MEMBER(struct addrinfo.ai_addr, + [AC_DEFINE(HAVE_STRUCT_ADDRINFO)], + [], + [ +#include +#include +#include + ])]) + +dnl ------------------------------------------------------------------------ +dnl PA_STRUCT_IN6_PKTINFO +dnl +dnl Look for definition of struct in6_pktinfo, which at least has an +dnl ipi6_addr member +dnl +AH_TEMPLATE([HAVE_STRUCT_IN6_PKTINFO], +[Define if struct in6_pktinfo is defined.]) + +AC_DEFUN(PA_STRUCT_IN6_PKTINFO, + [AC_CHECK_MEMBER(struct in6_pktinfo.ipi6_addr, + [AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO)], + [], + [ +#include +#include +#include +#include + ])]) + +dnl -------------------------------------------------------------------------- +dnl PA_HAVE_TCPWRAPPERS +dnl +dnl Do we have the tcpwrappers -lwrap? This can't be done using AC_CHECK_LIBS +dnl due to the need to provide "allow_severity" and "deny_severity" variables +dnl -------------------------------------------------------------------------- +AH_TEMPLATE([HAVE_TCPWRAPPERS], +[Define if we have tcpwrappers (-lwrap) and .]) + +AC_DEFUN(PA_HAVE_TCPWRAPPERS, +[AC_CHECK_LIB([wrap], [main]) + AC_MSG_CHECKING([for tcpwrappers]) + AC_TRY_LINK( +[ +#include +int allow_severity = 0; +int deny_severity = 0; +], +[ + hosts_ctl("sample_daemon", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN); +], +[ + AC_DEFINE(HAVE_TCPWRAPPERS) + AC_MSG_RESULT([yes]) +], +[ + AC_MSG_RESULT([no]) +])]) + +dnl ------------------------------------------------------------------------ +dnl PA_CHECK_INTTYPES_H_SANE +dnl +dnl At least some versions of AIX 4 have macros which are +dnl completely broken. Try to detect those. +dnl -------------------------------------------------------------------------- +AH_TEMPLATE([INTTYPES_H_IS_SANE], +[Define if the macros in are usable]) + +AC_DEFUN(PA_CHECK_INTTYPES_H_SANE, +[AC_CHECK_HEADERS(inttypes.h, + [ + AC_MSG_CHECKING([if inttypes.h is sane]) + AC_TRY_LINK( + [ +#include +#include + ], + [uintmax_t max = UINTMAX_C(0); + printf("%"PRIuMAX"\n", max);], + AC_MSG_RESULT([yes]) + AC_DEFINE(INTTYPES_H_IS_SANE), + AC_MSG_RESULT([no (AIX, eh?)])) + ]) +]) + +dnl ------------------------------------------------------------------------ +dnl PA_WITH_BOOL +dnl +dnl PA_WITH_BOOL(option, default, help, enable, disable) +dnl +dnl Provides a more convenient way to specify --with-option and +dnl --without-option, with a default. default should be either 0 or 1. +dnl ------------------------------------------------------------------------ +AC_DEFUN(PA_WITH_BOOL, +[AC_ARG_WITH([$1], [$3], +if test ["$withval"] != no; then +[$4] +else +[$5] +fi, +if test [$2] -ne 0; then +[$4] +else +[$5] +fi)]) + +dnl -------------------------------------------------------------------------- +dnl PA_HEADER_DEFINES +dnl +dnl PA_HEADER_DEFINES(header, type, value) +dnl -------------------------------------------------------------------------- +AC_DEFUN(PA_HEADER_DEFINES, +[AC_MSG_CHECKING([if $1 defines $3]) + AH_TEMPLATE([HAVE_$3_DEFINITION], [Define if $1 defines $3]) + AC_TRY_COMPILE([ +#include <$1> +], +[ +int main() +{ + $2 dummy = $3; + return 0; +} +], +[ + pa_header_define=`echo HAVE_$3_DEFINITION | tr '[a-z]' '[A-Z]'` + AC_DEFINE_UNQUOTED($pa_header_define) + AC_MSG_RESULT(yes) +], +[ + AC_MSG_RESULT(no) +])]) + +dnl -------------------------------------------------------------------------- +dnl PA_SEARCH_LIBS_AND_ADD +dnl +dnl PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add]) +dnl -------------------------------------------------------------------------- + +AC_DEFUN(PA_SEARCH_LIBS_AND_ADD, + [ + AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found]) + AC_SEARCH_LIBS($1, $2, + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1)) + pa_add_$1=false; + ], + [ + XTRA=true; + if test $# -eq 3; then + AC_LIBOBJ($3) + else + AC_LIBOBJ($1) + fi + pa_add_$1=true; + ])]) diff --git a/autoconf/m4/pa_add_cflags.m4 b/autoconf/m4/pa_add_cflags.m4 deleted file mode 100644 index 26d55c4..0000000 --- a/autoconf/m4/pa_add_cflags.m4 +++ /dev/null @@ -1,9 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ADD_CFLAGS(variable, flag [,actual_flag [,success [,failure]]]]) -dnl -dnl Attempt to add the given option to xFLAGS, if it doesn't break -dnl compilation. If the option to be tested is different than the -dnl option that should actually be added, add the option to be -dnl actually added as a second argument. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_ADD_CFLAGS], [PA_ADD_FLAGS(CFLAGS, [$1], [$2], [$3], [$4])]) diff --git a/autoconf/m4/pa_add_flags.m4 b/autoconf/m4/pa_add_flags.m4 deleted file mode 100644 index 23f96f1..0000000 --- a/autoconf/m4/pa_add_flags.m4 +++ /dev/null @@ -1,39 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ADD_FLAGS(flagvar, flags) -dnl -dnl Add [flags] to the variable [flagvar] if and only if it is accepted -dnl by all languages affected by [flagvar], if those languages have -dnl been previously seen in the script. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_ADD_FLAGS], -[ - AS_VAR_PUSHDEF([old], [_$0_$1_orig]) - AS_VAR_PUSHDEF([ok], [_$0_$1_ok]) - AS_VAR_PUSHDEF([flags], [$1]) - - AS_VAR_COPY([old], [flags]) - AS_VAR_SET([flags], ["$flags $2"]) - AS_VAR_SET([ok], [yes]) - - PA_LANG_FOREACH(PA_FLAGS_LANGLIST($1), - [AS_VAR_IF([ok], [yes], - [AC_MSG_CHECKING([if $]_AC_CC[ accepts $2]) - PA_BUILD_IFELSE([], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AS_VAR_SET([ok], [no])])]) - ]) - - AS_VAR_IF([ok], [yes], - [m4_ifnblank([$3],[AS_VAR_SET([flags], ["$old $3"])]) - m4_foreach_w([_pa_add_flags_flag], [m4_ifblank([$3],[$2],[$3])], - [AC_DEFINE(PA_SYM([$1_]_pa_add_flags_flag), 1, - [Define to 1 if compiled with the ]_pa_add_flags_flag[ compiler flag])]) - $4], - [AS_VAR_SET([flags], ["$old"]) - $5]) - - AS_VAR_POPDEF([flags]) - AS_VAR_POPDEF([ok]) - AS_VAR_POPDEF([old]) -]) diff --git a/autoconf/m4/pa_add_headers.m4 b/autoconf/m4/pa_add_headers.m4 deleted file mode 100644 index d3c478a..0000000 --- a/autoconf/m4/pa_add_headers.m4 +++ /dev/null @@ -1,13 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ADD_HEADERS(headers...) -dnl -dnl Call AC_CHECK_HEADERS(), and add to ac_includes_default if found -dnl -------------------------------------------------------------------------- -AC_DEFUN([_PA_ADD_HEADER], -[AC_CHECK_HEADERS([$1],[ac_includes_default="$ac_includes_default -#include <$1>" -]) -]) - -AC_DEFUN([PA_ADD_HEADERS], -[m4_map_args_w([$1],[_PA_ADD_HEADER(],[)])]) diff --git a/autoconf/m4/pa_add_langflags.m4 b/autoconf/m4/pa_add_langflags.m4 deleted file mode 100644 index 05c3114..0000000 --- a/autoconf/m4/pa_add_langflags.m4 +++ /dev/null @@ -1,27 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ADD_LANGFLAGS(flag...) -dnl -dnl Attempt to add the option in the given list to each compiler flags -dnl (CFLAGS, CXXFLAGS, ...), if it doesn't break compilation. -dnl -------------------------------------------------------------------------- -m4_defun([_PA_LANGFLAG_VAR], -[m4_case([$1], - [C], [CFLAGS], - [C++], [CXXFLAGS], - [Fortran 77], [FFLAGS], - [Fortran], [FCFLAGS], - [Erlang], [ERLCFLAGS], - [Objective C], [OBJCFLAGS], - [Objective C++], [OBJCXXFLAGS], - [Go], [GOFLAGS], - [m4_fatal([PA_ADD_LANGFLAGS: Unknown language: $1])])]) - -AC_DEFUN([PA_ADD_LANGFLAGS], -[m4_pushdef([_pa_langflags],m4_dquote($1))dnl -m4_set_foreach(_PA_LANG_SEEN_SET,[_pa_lang],dnl -[_pa_flag_found=no - m4_foreach_w([_pa_flag], _pa_langflags, - [AS_IF([test $_pa_flag_found = no], - [PA_ADD_FLAGS(_PA_LANGFLAG_VAR(_pa_lang),_pa_flag,[],[_pa_flag_found=yes])]) - ])]) -m4_popdef([_pa_langflags])]) diff --git a/autoconf/m4/pa_arg_bool.m4 b/autoconf/m4/pa_arg_bool.m4 deleted file mode 100644 index 5289ed4..0000000 --- a/autoconf/m4/pa_arg_bool.m4 +++ /dev/null @@ -1,19 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ARG_BOOL(option,helptext,default,enabled_action,disabled_action) -dnl -dnl The last three arguments are optional; default can be yes or no. -dnl -dnl Simpler-to-use versions of AC_ARG_ENABLED, that include the -dnl test for $enableval and the AS_HELP_STRING definition. This is only -dnl to be used for boolean options. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_ARG_BOOL], -[m4_pushdef([pa_default],m4_default(m4_normalize([$3]),[no])) - m4_pushdef([pa_option],m4_case(pa_default,[yes],[disable],[enable])) - AC_ARG_ENABLE([$1], - [AS_HELP_STRING([--]m4_defn([pa_option])[-$1],[$2])], - [pa_arg_bool_enableval="$enableval"], - [pa_arg_bool_enableval="]m4_defn([pa_default])["]) - m4_popdef([pa_option], [pa_default]) - AS_IF([test x"$pa_arg_bool_enableval" != xno], [$4], [$5]) -]) diff --git a/autoconf/m4/pa_arg_disabled.m4 b/autoconf/m4/pa_arg_disabled.m4 deleted file mode 100644 index 42f4ce8..0000000 --- a/autoconf/m4/pa_arg_disabled.m4 +++ /dev/null @@ -1,4 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ARG_DISABLED(option,helptext,disabled_action,enabled_action) -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_ARG_DISABLED],[PA_ARG_BOOL([$1],[$2],yes,[$4],[$3])]) diff --git a/autoconf/m4/pa_arg_enabled.m4 b/autoconf/m4/pa_arg_enabled.m4 deleted file mode 100644 index 7d66a21..0000000 --- a/autoconf/m4/pa_arg_enabled.m4 +++ /dev/null @@ -1,4 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_ARG_ENABLED(option,helptext,enabled_action,disabled_action) -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_ARG_ENABLED],[PA_ARG_BOOL([$1],[$2],no,[$3],[$4])]) diff --git a/autoconf/m4/pa_build_ifelse.m4 b/autoconf/m4/pa_build_ifelse.m4 deleted file mode 100644 index 1aacfcd..0000000 --- a/autoconf/m4/pa_build_ifelse.m4 +++ /dev/null @@ -1,16 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_BUILD_IFELSE(input [,success [,failure]]) -dnl -dnl Same as AC_LINK_IFELSE for languages where linking is applicable, -dnl otherwise AC_COMPILE_IFELSE. -dnl -dnl If the first argument is empty, use _AC_LANG_IO_PROGRAM. -dnl -------------------------------------------------------------------------- -m4_defun([_PA_BUILD_IFELSE], -[m4_case(_AC_LANG, - [Erlang], [AC_COMPILE_IFELSE($@)], - [AC_LINK_IFELSE($@)])]) - -AC_DEFUN([PA_BUILD_IFELSE], -[_PA_BUILD_IFELSE([m4_ifblank([$1],[AC_LANG_SOURCE(_AC_LANG_IO_PROGRAM)], - [$1])],[$2],[$3])]) diff --git a/autoconf/m4/pa_c_typeof.m4 b/autoconf/m4/pa_c_typeof.m4 deleted file mode 100644 index 909b171..0000000 --- a/autoconf/m4/pa_c_typeof.m4 +++ /dev/null @@ -1,32 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_C_TYPEOF -dnl -dnl Find if typeof() exists, or an equivalent (__typeof__, decltype, -dnl __decltype__) -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_C_TYPEOF], -[AC_CACHE_CHECK([if $CC supports typeof], [pa_cv_typeof], - [pa_cv_typeof=no - for pa_typeof_try in typeof __typeof __typeof__ decltype __decltype __decltype__ _Decltype - do - AS_IF([test $pa_cv_typeof = no], - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([ -AC_INCLUDES_DEFAULT -int testme(int x); -int testme(int x) -{ - $pa_typeof_try(x) y = x*x; - return y; -} -])], - [pa_cv_typeof=$pa_typeof_try])]) - done - ]) - AS_IF([test $pa_cv_typeof = no], - [], - [AC_DEFINE([HAVE_TYPEOF], 1, - [Define to 1 if you have some version of the typeof operator.]) - AS_IF([test $pa_cv_typeof = typeof], - [], - [AC_DEFINE_UNQUOTED([typeof], [$pa_cv_typeof], - [Define if your typeof operator is not named `typeof'.])])])]) diff --git a/autoconf/m4/pa_check_bad_stdc_inline.m4 b/autoconf/m4/pa_check_bad_stdc_inline.m4 deleted file mode 100644 index 3fbc53a..0000000 --- a/autoconf/m4/pa_check_bad_stdc_inline.m4 +++ /dev/null @@ -1,26 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_CHECK_BAD_STDC_INLINE -dnl -dnl Some versions of gcc seem to apply -Wmissing-prototypes to C99 -dnl inline functions, which means we need to use GNU inline syntax -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_CHECK_BAD_STDC_INLINE], -[AC_MSG_CHECKING([if $CC supports C99 external inlines]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ -AC_INCLUDES_DEFAULT - -/* Don't mistake GNU inlines for c99 */ -#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__) -# error "Using gnu inline standard" -#endif - -inline int foo(int x) -{ - return x+1; -} - ])], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_STDC_INLINE], 1, - [Define to 1 if your compiler supports C99 extern inline])], - [AC_MSG_RESULT([no]) - PA_ADD_CFLAGS([-fgnu89-inline])])]) diff --git a/autoconf/m4/pa_check_inttypes_h_sane.m4 b/autoconf/m4/pa_check_inttypes_h_sane.m4 deleted file mode 100644 index 589e0a2..0000000 --- a/autoconf/m4/pa_check_inttypes_h_sane.m4 +++ /dev/null @@ -1,17 +0,0 @@ -dnl ------------------------------------------------------------------------ -dnl PA_CHECK_INTTYPES_H_SANE -dnl -dnl At least some versions of AIX 4 have macros which are -dnl completely broken. Try to detect those. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_CHECK_INTTYPES_H_SANE], -[AC_CHECK_HEADERS_ONCE(inttypes.h) -AS_IF([test "x$ac_cv_header_inttypes_h" = xyes],[ - AC_MSG_CHECKING([if inttypes.h is sane]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], - [uintmax_t max = UINTMAX_C(0); - printf("%"PRIuMAX"\n", max);])], - [AC_MSG_RESULT([yes]) - AC_DEFINE(INTTYPES_H_IS_SANE, 1, - [Define if the macros in are usable])], - [AC_MSG_RESULT([no (AIX, eh?)])])])]) diff --git a/autoconf/m4/pa_cross_compile.m4 b/autoconf/m4/pa_cross_compile.m4 deleted file mode 100644 index f082973..0000000 --- a/autoconf/m4/pa_cross_compile.m4 +++ /dev/null @@ -1,41 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_CROSS_COMPILE -dnl -dnl Get the canonical name for the build and host (runtime) systems; -dnl then figure out if this is cross-compilation. Specifically, this -dnl disables invoking WINE on non-Windows systems which are configured -dnl to run WINE automatically. -dnl -dnl Use PA_CROSS_COMPILE_TOOL if the target system (output of a code- -dnl generation tool) is applicable. -dnl -dnl This doesn't explicitly print any messages as that is automatically -dnl done elsewhere. -dnl -------------------------------------------------------------------------- -AC_DEFUN_ONCE([PA_CROSS_COMPILE], -[ - AC_BEFORE([$0], [AC_LANG_COMPILER]) - AC_BEFORE([$0], [AC_LANG]) - AC_BEFORE([$0], [AC_PROG_CC]) - AC_BEFORE([$0], [AC_PROG_CPP]) - AC_BEFORE([$0], [AC_PROG_CXX]) - AC_BEFORE([$0], [AC_PROG_CXXCPP]) - AC_BEFORE([$0], [AC_PROG_OBJC]) - AC_BEFORE([$0], [AC_PROG_OBJCPP]) - AC_BEFORE([$0], [AC_PROG_OBJCXX]) - AC_BEFORE([$0], [AC_PROG_OBJCXXCPP]) - AC_BEFORE([$0], [AC_PROG_F77]) - AC_BEFORE([$0], [AC_PROG_FC]) - AC_BEFORE([$0], [AC_PROG_GO]) - - # Disable WINE - WINELOADER=/dev/null - export WINELOADER - WINESERVER=/dev/null - export WINESERVER - WINEPREFIX=/dev/null - export WINEPREFIX - - AC_CANONICAL_BUILD - AC_CANONICAL_HOST -]) diff --git a/autoconf/m4/pa_flags_langlist.m4 b/autoconf/m4/pa_flags_langlist.m4 deleted file mode 100644 index 2ef5ded..0000000 --- a/autoconf/m4/pa_flags_langlist.m4 +++ /dev/null @@ -1,19 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_FLAGS_LANGLIST(flagvar) -dnl -dnl Return a list of languages affected by the variable flagvar. -dnl If flagvar is unknown, assume it affects the current language. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_FLAGS_LANGLIST], -[m4_dquote(m4_case([$1], - [CPPFLAGS], [[C],[C++],[Objective C],[Objective C++]], - [CFLAGS], [[C]], - [CXXFLAGS], [[C++]], - [FFLAGS], [[Fortran 77]], - [FCFLAGS], [[Fortran]], - [ERLCFLAGS], [[Erlang]], - [OBJCFLAGS], [[Objective C]], - [OBJCXXFLAGS], [[Objective C++]], - [GOFLAGS], [[Go]], - [LDFLAGS], [[C],[C++],[Fortran 77],[Fortran],[Objective C],[Objective C++],[Go]], - m4_dquote(_AC_LANG)))]) diff --git a/autoconf/m4/pa_have_tcpwrappers.m4 b/autoconf/m4/pa_have_tcpwrappers.m4 deleted file mode 100644 index fba87ce..0000000 --- a/autoconf/m4/pa_have_tcpwrappers.m4 +++ /dev/null @@ -1,26 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_HAVE_TCPWRAPPERS -dnl -dnl Do we have the tcpwrappers -lwrap? This can't be done using AC_CHECK_LIBS -dnl due to the need to provide "allow_severity" and "deny_severity" variables -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_HAVE_TCPWRAPPERS], -[AC_CHECK_LIB([wrap], [main]) - AC_MSG_CHECKING([for tcpwrappers]) - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [[ -#include -int allow_severity = 0; -int deny_severity = 0; - ]], - [[ - hosts_ctl("sample_daemon", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN); - ]])], - [ - AC_DEFINE(HAVE_TCPWRAPPERS, 1, - [Define if we have tcpwrappers (-lwrap) and .]) - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - ])]) diff --git a/autoconf/m4/pa_lang_foreach.m4 b/autoconf/m4/pa_lang_foreach.m4 deleted file mode 100644 index 650913d..0000000 --- a/autoconf/m4/pa_lang_foreach.m4 +++ /dev/null @@ -1,15 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_LANG_FOREACH(subset, body) -dnl -dnl Expand [body] for each language encountered in the configure script also -dnl present in [subset], or all if [subset] is empty -dnl -------------------------------------------------------------------------- -AC_DEFUN([_PA_LANG_DO],dnl -[AC_LANG([$2])dnl -$1]) - -AC_DEFUN([PA_LANG_FOREACH],dnl -[m4_pushdef([_pa_lang_foreach_current],[_AC_LANG])dnl -m4_map_args([m4_curry([_PA_LANG_DO],[$2])],m4_unquote(PA_LANG_SEEN_LIST($1)))dnl -AC_LANG(_pa_lang_foreach_current)dnl -m4_popdef([_pa_lang_foreach_current])]) diff --git a/autoconf/m4/pa_lang_seen_list.m4 b/autoconf/m4/pa_lang_seen_list.m4 deleted file mode 100644 index d524013..0000000 --- a/autoconf/m4/pa_lang_seen_list.m4 +++ /dev/null @@ -1,20 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_LANG_SEEN_LIST(subset) -dnl -dnl List of the language lang has been used in the configuration -dnl script so far, possibly subset by [subset]. -dnl -dnl This relies on overriding _AC_LANG_SET(from, to), -dnl the internal implementation of _AC_LANG. -dnl -------------------------------------------------------------------------- -m4_ifndef([_PA_LANG_SET], -[m4_rename([_AC_LANG_SET], [_PA_LANG_SET])dnl -m4_defun([_AC_LANG_SET], [m4_set_add([_PA_LANG_SEEN_SET],[$2])dnl -_PA_LANG_SET($@)])]) - -AC_DEFUN([PA_LANG_SEEN_LIST], -[m4_set_delete([_pa_lang_seen_subset])dnl -m4_pushdef([_pa_lang_seen_subset_list],m4_ifnblank([$1],[$1],m4_dquote(m4_set_list([_PA_LANG_SEEN_SET]))))dnl -m4_set_add_all([_pa_lang_seen_subset],_pa_lang_seen_subset_list)dnl -m4_cdr(m4_set_intersection([_pa_lang_seen_subset],[_PA_LANG_SEEN_SET]))dnl -m4_popdef([_pa_lang_seen_subset_list])]) diff --git a/autoconf/m4/pa_option_debug.m4 b/autoconf/m4/pa_option_debug.m4 deleted file mode 100644 index ae7d9db..0000000 --- a/autoconf/m4/pa_option_debug.m4 +++ /dev/null @@ -1,13 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_OPTION_DEBUG(with_debug, without_debug) -dnl -dnl Set debug flags and optimization flags depending on if -dnl --enable-debug is set or not. Some flags are set regardless... -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_OPTION_DEBUG], -[PA_ARG_DISABLED([gdb], [disable gdb debug extensions], - [PA_ADD_LANGFLAGS([-g3])], [PA_ADD_LANGFLAGS([-ggdb3 -g3])]) - PA_ARG_ENABLED([debug], [optimize for debugging], - [PA_ADD_LANGFLAGS([-Og -O0]) - $1], - [$2])]) diff --git a/autoconf/m4/pa_option_profiling.m4 b/autoconf/m4/pa_option_profiling.m4 deleted file mode 100644 index 39a3f6c..0000000 --- a/autoconf/m4/pa_option_profiling.m4 +++ /dev/null @@ -1,8 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_OPTION_PROFILING(with_profiling, without_profiling) -dnl -dnl Try to enable profiling if --enable-profiling is set. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_OPTION_PROFILING], -[PA_ARG_ENABLED([profiling], [compile with profiling (-pg option)], -[PA_ADD_LANGFLAGS([-pg])])]) diff --git a/autoconf/m4/pa_prog_cc.m4 b/autoconf/m4/pa_prog_cc.m4 deleted file mode 100644 index 0debe5d..0000000 --- a/autoconf/m4/pa_prog_cc.m4 +++ /dev/null @@ -1,13 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_PROG_CC() -dnl -dnl Similar to AC_PROG_CC, but add a prototype for main() to -dnl AC_INCLUDES_DEFAULT to avoid -Werror from breaking compilation. -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_PROG_CC], -[AC_PROG_CC - AS_IF([test x$ac_cv_prog != xno], - [ac_includes_default="$ac_includes_default -#ifndef __cplusplus -extern int main(void); -#endif"])]) diff --git a/autoconf/m4/pa_search_libs_and_add.m4 b/autoconf/m4/pa_search_libs_and_add.m4 deleted file mode 100644 index b006128..0000000 --- a/autoconf/m4/pa_search_libs_and_add.m4 +++ /dev/null @@ -1,22 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_SEARCH_LIBS_AND_ADD -dnl -dnl PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add]) -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_SEARCH_LIBS_AND_ADD], - [ - AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found]) - AC_SEARCH_LIBS($1, $2, - [ - AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1)) - pa_add_$1=false; - ], - [ - XTRA=true; - if test $# -eq 3; then - AC_LIBOBJ($3) - else - AC_LIBOBJ($1) - fi - pa_add_$1=true; - ])]) diff --git a/autoconf/m4/pa_sigsetjmp.m4 b/autoconf/m4/pa_sigsetjmp.m4 deleted file mode 100644 index 898b562..0000000 --- a/autoconf/m4/pa_sigsetjmp.m4 +++ /dev/null @@ -1,25 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_SIGSETJMP -dnl -dnl Do we have sigsetjmp/siglongjmp? (AC_CHECK_FUNCS doesn't seem to work -dnl for these particular functions.) -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_SIGSETJMP], -[AC_MSG_CHECKING([for sigsetjmp]) - AC_LINK_IFELSE([AC_LANG_SOURCE( -[ -AC_INCLUDES_DEFAULT -#include - -int main(void) { - sigjmp_buf buf; - if (sigsetjmp(buf,1)) - return 0; - siglongjmp(buf,2); - return 1; - } -])], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SIGSETJMP], 1, - [Define to 1 if your system has sigsetjmp/siglongjmp])], - [AC_MSG_RESULT([no])])]) diff --git a/autoconf/m4/pa_sym.m4 b/autoconf/m4/pa_sym.m4 deleted file mode 100644 index d3a8965..0000000 --- a/autoconf/m4/pa_sym.m4 +++ /dev/null @@ -1,11 +0,0 @@ -dnl -------------------------------------------------------------------------- -dnl PA_SYM(prefix, string) -dnl -dnl Convert a (semi-) arbitrary string to a CPP symbol -dnl Compact underscores and convert non-C characters to underscore, -dnl except + which is converted to X (so C++ -> CXX). -dnl -------------------------------------------------------------------------- -AC_DEFUN([PA_SYM], -[m4_bpatsubsts(m4_quote(m4_toupper([$*])), - [,],[],[\+],[X],[[^ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]+],[_],dnl -[^._?\(.*\)_.$],[[\1]])]) diff --git a/autogen.sh b/autogen.sh index 0c892cc..728a381 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,83 +1,2 @@ -#!/bin/sh -x -# -# Run this script to regenerate autoconf files -# -recheck=false -for arg; do - case x"$arg" in - x--recheck) - recheck=true - config=$(sh config.status --config 2>/dev/null) - ;; - x--clearenv) - unset AUTOCONF AUTOMAKE ACLOCAL AUTOHEADER ACLOCAL_PATH - ;; - *) - echo "$0: unknown option: $arg" 1>&2 - ;; - esac -done - -# This allows for overriding the default autoconf programs -AUTOCONF="${AUTOCONF:-${AUTOTOOLS_PREFIX}autoconf}" -AUTOMAKE="${AUTOMAKE:-${AUTOTOOLS_PREFIX}automake}" -ACLOCAL="${ACLOCAL:-${AUTOTOOLS_PREFIX}aclocal}" -AUTOHEADER="${AUTOHEADER:-${AUTOTOOLS_PREFIX}autoheader}" - -mkdir -p autoconf autoconf/helpers config -autolib="`"$AUTOMAKE" --print-libdir`" -if test ! x"$autolib" = x; then - for prg in install-sh compile config.guess config.sub; do - # Update autoconf helpers if and only if newer ones are available - if test -f "$autolib"/"$prg" && \ - ( set -e ; \ - test -f autoconf/helpers/"$prg" && sed -n \ - -e 's/^scriptver=/scriptversion=/' \ - -e 's/^timestamp=/scriptversion=/' \ - -e 's/^scriptversion=['\''"]?\([^'\''"]*\).*$/\1/p' \ - "$autolib"/"$prg" autoconf/helpers/"$prg" | \ - sort -c 2>/dev/null ; \ - test $? -ne 0 ) - then - cp -f "$autolib"/"$prg" autoconf/helpers - fi - done -fi -mv -f autoconf/aclocal.m4 autoconf/aclocal.m4.old -mkdir -p autoconf/m4.old autoconf/m4 -mv -f autoconf/m4/*.m4 autoconf/m4.old/ 2>/dev/null || true -ACLOCAL_PATH="${ACLOCAL_PATH}${ACLOCAL_PATH:+:}`pwd`/autoconf/m4.old" -export ACLOCAL_PATH -"$ACLOCAL" --install --output=autoconf/aclocal.m4 -I autoconf/m4 -if test ! -f autoconf/aclocal.m4; then - # aclocal failed, revert to previous files - mv -f autoconf/m4.old/*.m4 autoconf/m4/ - mv -f autoconf/aclocal.m4.old autoconf/aclocal.m4 - exit 1 -fi -rm -rf autoconf/*m4.old -"$AUTOHEADER" -B autoconf -"$AUTOCONF" -B autoconf -( - echo '#!/bin/sh' - "$AUTOCONF" -B autoconf \ - -t AC_CONFIG_HEADERS:'rm -f $*' \ - -t AC_CONFIG_FILES:'rm -f $*' - echo 'rm -f config.log config.status' - echo 'rm -rf autom4te.cache' -) > autoconf/clean.sh -chmod +x autoconf/clean.sh -sh autoconf/clean.sh - -rm -f configure~ || true - -# Try to regenerate unconfig.h if Perl is available and unconfig.pl -# is present in the autoconf directory. -if [ -n "$(which perl)" -a -f autoconf/unconfig.pl ]; then - perl autoconf/unconfig.pl . config/config.h.in config/unconfig.h -fi - -if $recheck; then - # This bizarre statement has to do with how config.status quotes its output - echo exec sh configure $config | sh - -fi +#!/bin/sh +make autoconf diff --git a/common/Makefile b/common/Makefile index 89e351d..a825213 100644 --- a/common/Makefile +++ b/common/Makefile @@ -1,10 +1,10 @@ SRCROOT = .. VERSION = $(shell cat ../version) --include ../config/MCONFIG +-include ../MCONFIG include ../MRULES -OBJS = tftpsubs.$(O) signal.$(O) +OBJS = tftpsubs.$(O) LIB = libcommon.a all: $(LIB) diff --git a/common/signal.c b/common/signal.c deleted file mode 100644 index ccd4af8..0000000 --- a/common/signal.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * signal.c - * - * User-friendly wrapper around sigaction(). - */ - -#include "config.h" - -int tftp_signal(int signum, sighandler_t handler, int flags) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_handler = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = flags; - - return sigaction(signum, &sa, NULL); -} diff --git a/config.h b/config.h index a8c55ac..0e35438 100644 --- a/config.h +++ b/config.h @@ -1,6 +1,6 @@ /* -*- c -*- ------------------------------------------------------------- * * - * Copyright 2001-2024 H. Peter Anvin - All Rights Reserved + * Copyright 2001-2006 H. Peter Anvin - All Rights Reserved * * This program is free software available under the same license * as the "OpenBSD" operating system, distributed at @@ -17,23 +17,12 @@ #ifndef CONFIG_H #define CONFIG_H 1 -/* Feature enables for specific environments */ -#ifdef __APPLE__ -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070 -#define __APPLE_USE_RFC_3542 1 -#endif -#endif - /* Must be included before we include any system headers! */ -#include "config/config.h" /* autogenerated configuration header */ +#include "aconfig.h" /* autogenerated configuration header */ /* Standard includes */ #include -#include -#include -#include -#include #ifdef HAVE_SYS_TYPES_H #include @@ -43,6 +32,21 @@ #include #endif +#ifdef STDC_HEADERS +#include +#include +#else +#ifdef HAVE_STDLIB_H +#include +#endif +#endif + +#ifdef HAVE_MEMORY_H +#ifndef STDC_HEADERS +#include +#endif +#endif + #ifdef HAVE_STRING_H #include #endif @@ -69,8 +73,15 @@ #include #endif -#ifdef HAVE_SYS_TIME_H +#ifdef TIME_WITH_SYS_TIME #include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif #endif #ifdef HAVE_GRP_H @@ -81,6 +92,9 @@ #include #endif +#include +#include + #ifdef HAVE_SYS_SOCKET_H #include #else @@ -115,10 +129,10 @@ /* Some broken systems care about text versus binary, but real Unix systems don't... */ -#if !HAVE_DECL_O_TEXT +#ifndef HAVE_O_TEXT_DEFINITION #define O_TEXT 0 #endif -#if !HAVE_DECL_O_BINARY +#ifndef HAVE_O_BINARY_DEFINITION #define O_BINARY 0 #endif @@ -253,9 +267,11 @@ typedef int socklen_t; #include -#if !HAVE_DECL_IPPORT_TFTP && !defined(IPPORT_TFTP) +#ifndef HAVE_IPPORT_TFTP_DEFINITION +#ifndef IPPORT_TFTP #define IPPORT_TFTP 69 #endif +#endif /* arpa/{inet,tftp}.h, and possible missing pieces */ @@ -277,11 +293,9 @@ typedef int socklen_t; void *xmalloc(size_t); char *xstrdup(const char *); -#ifndef HAVE_SIGHANDLER_T -typedef void (*sighandler_t)(int); +#ifndef HAVE_BSD_SIGNAL +void (*bsd_signal(int, void (*)(int))) (int); #endif -int tftp_signal(int, sighandler_t, int); - #ifndef HAVE_DUP2 int dup2(int, int); #endif diff --git a/configure.ac b/configure.ac deleted file mode 100644 index deaa4fc..0000000 --- a/configure.ac +++ /dev/null @@ -1,283 +0,0 @@ -dnl Process this file with autoconf 2.71 or later to produce -dnl a configure script. -AC_PREREQ([2.71]) -AC_INIT -AC_CONFIG_SRCDIR([MRULES]) -AC_PREFIX_DEFAULT([/usr]) -AC_CONFIG_AUX_DIR([autoconf/helpers]) - -dnl This prevents us from running Wine and thinking we are not -dnl cross-compiling when in fact we are; running Wine here is at -dnl the best very slow and doesn't buy us a single thing at all. -PA_CROSS_COMPILE - -dnl Enable any available C extensions -PA_PROG_CC -AC_USE_SYSTEM_EXTENSIONS - -dnl Options for debugging and profiling -PA_OPTION_DEBUG -PA_OPTION_PROFILING - -dnl LLVM doesn't error out on invalid -W options unless this option is -dnl specified first. Enable this so this script can actually discover -dnl which -W options are possible for this compiler. -PA_ADD_CFLAGS([-Werror=unknown-warning-option]) - -dnl Force gcc and gcc-compatible compilers treat signed integers -dnl as 2's complement -PA_ADD_CFLAGS([-fwrapv]) - -dnl Force clang to behave in a predictable manner, in order to make bugs -dnl possible to track down. gcc appears to have this behavior by default. -PA_ADD_CFLAGS([-ftrivial-auto-var-init=zero]) - -dnl Some environments abuse __STRICT_ANSI__ to disable some -dnl function declarations -PA_ADD_CFLAGS([-U__STRICT_ANSI__]) - -dnl Don't put things in common if we can avoid it. We don't want to -dnl assume all compilers support common, and this will help find those -dnl problems. This also works around an OSX linker problem. -PA_ADD_CFLAGS([-fno-common]) - -dnl Tests which may trigger warnings on some compilers -AC_C_CONST -AC_C_INLINE -AC_C_RESTRICT - -dnl Checks for header files. -AC_CHECK_INCLUDES_DEFAULT - -dnl See if we need extra libraries -XTRA=false - -AC_SEARCH_LIBS([strerror],[cposix]) - -AC_CHECK_HEADERS_ONCE(inttypes.h) -AC_CHECK_HEADERS_ONCE(stdint.h) -AC_CHECK_HEADERS_ONCE(grp.h) -AC_CHECK_HEADERS_ONCE(libgen.h) -AC_CHECK_HEADERS_ONCE(setjmp.h) -AC_CHECK_HEADERS_ONCE(strings.h) -AC_CHECK_HEADERS_ONCE(sysexits.h) -AC_CHECK_HEADERS_ONCE(unistd.h) -AC_CHECK_HEADERS_ONCE(sys/filio.h) -AC_CHECK_HEADERS_ONCE(sys/stat.h) -AC_CHECK_HEADERS_ONCE(sys/time.h) -PA_CHECK_INTTYPES_H_SANE - -dnl This is needed on some versions of FreeBSD... -AC_CHECK_HEADERS_ONCE(machine/param.h) - -dnl Windows... -PA_ADD_HEADERS(windows.h) -PA_ADD_HEADERS(winsock2.h) -AS_IF([test "x$ac_cv_header_winsock2_h" != xyes], - [PA_ADD_HEADERS(winsock.h)]) - -PA_ADD_HEADERS(fcntl.h) -PA_ADD_HEADERS(sys/types.h) -PA_ADD_HEADERS(arpa/inet.h) -PA_ADD_HEADERS(sys/socket.h) -PA_ADD_HEADERS(sys/file.h) -PA_ADD_HEADERS(netinet/in.h) -PA_ADD_HEADERS(sys/uio.h) -PA_ADD_HEADERS(netdb.h) - -AC_TYPE_OFF_T -AC_TYPE_PID_T -AC_TYPE_MODE_T -AC_TYPE_SIZE_T -AC_CHECK_TYPES(intmax_t) -AC_CHECK_TYPES(long long) -AC_CHECK_TYPES(uint16_t) -AC_CHECK_TYPES(uint32_t) -AC_CHECK_TYPES(u_short) -AC_CHECK_TYPES(u_long) - -AC_CHECK_TYPES(socklen_t) - -AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , - [AC_MSG_ERROR(socket library not found)]) - -AC_CHECK_FUNCS(fcntl) -AC_CHECK_FUNCS(flock) -AC_CHECK_FUNCS(setsid) -AC_CHECK_FUNCS(recvmsg) -AC_CHECK_FUNCS(ftruncate) -AC_CHECK_FUNCS(setresuid) -AC_CHECK_FUNCS(setreuid) -AC_CHECK_FUNCS(setresgid) -AC_CHECK_FUNCS(setregid) -AC_CHECK_FUNCS(initgroups) -AC_CHECK_FUNCS(setgroups) -AC_CHECK_TYPES(sighandler_t) - -dnl Solaris 8 has [u]intmax_t but not strtoumax(). How utterly braindamaged. -AC_CHECK_FUNCS(strtoumax) -AC_CHECK_FUNCS(strtoull) - -AC_CHECK_MEMBERS(struct msghdr.msg_control) -AC_CHECK_MEMBERS(struct in_pktinfo.ipi_addr) -AC_CHECK_MEMBERS(struct addrinfo.ai_addr) - -AC_CHECK_DECLS([O_NONBLOCK, O_BINARY, O_TEXT]) -AC_CHECK_DECLS([F_SETLK]) -AC_CHECK_DECLS([LOCK_SH, LOCK_EX]) - -PA_SIGSETJMP - -dnl -dnl Get common paths -dnl -SRCROOT=`cd $srcdir && pwd` -OBJROOT=`pwd` - -PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty) -PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty) -PA_SEARCH_LIBS_AND_ADD(getopt_long, getopt, getopt_long) -PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv]) -AS_IF([$pa_add_getaddrinfo], -[AC_SEARCH_LIBS(gethostbyname, [nsl resolv], - [AC_SEARCH_LIBS(herror, [nsl resolv], , - [AC_MSG_ERROR(herror not found)])], - [AC_MSG_ERROR(gethostbyname not found)])], -[AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], , - [AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)]) - AC_SEARCH_LIBS(gai_strerror, [nsl resolv], , - [AC_MSG_ERROR(getaddrinfo but not gai_strerror found)])]) - -PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv]) -AS_IF([$pa_add_inet_ntop], - [AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], , - [AC_MSG_ERROR(inet_ntoa not found)])]) - -AC_SEARCH_LIBS(inet_aton, [nsl resolv], ,[AC_MSG_ERROR(inet_aton not found)]) - -PA_SEARCH_LIBS_AND_ADD(daemon) -PA_SEARCH_LIBS_AND_ADD(dup2) - -AS_IF([$XTRA], [XTRALIBS="$OBJROOT/lib/libxtra.a $XTRALIBS"]) - -dnl -dnl These libraries apply to the server only -dnl - -common_libs="$LIBS" - -AC_CHECK_DECLS(IPPORT_TFTP) - -PA_ARG_DISABLED([tcpwrappers], - [disable tcpwrapper permissions checking], [], - [ - AC_SEARCH_LIBS(yp_get_default_domain, [nsl resolv]) - PA_HAVE_TCPWRAPPERS - ]) - -AC_CHECK_HEADERS_ONCE([regex.h]) -PA_ARG_DISABLED([remap], - [disable regex-based filename remapping], [], - [AS_IF([test x"$ac_cv_header_regex_h" = xyes], - [AC_SEARCH_LIBS(regcomp, [regex rx], - [AC_DEFINE([WITH_REGEX], 1, - [Define if we are compiling with regex filename remapping.]) - TFTPDOBJS="remap.\$(O) $TFTPOBJS"])])]) - -TFTPD_LIBS="$LIBS $XTRALIBS" -LIBS="$common_libs" - -dnl -dnl These libraries apply to the client only -dnl - -AH_TEMPLATE([WITH_READLINE], -[Define if we are compiling with readline/editline command-line editing.]) - -PA_ARG_DISABLED([readline], - [disable the use of readline command-line editing], [], - [ - AC_CHECK_HEADER([readline/readline.h], - [ - dnl readline may need libtermcap or somesuch... - AC_SEARCH_LIBS(tputs, [termcap terminfo]) - - AC_SEARCH_LIBS(readline, [readline history], - [AC_DEFINE(WITH_READLINE)]) - AC_CHECK_HEADERS(readline/history.h) - ], - [AC_CHECK_HEADER([editline/readline.h], - [ - dnl editline may need libtermcap or somesuch... - AC_SEARCH_LIBS(tputs, [termcap terminfo]) - - AC_SEARCH_LIBS(editline, [edit], - [AC_DEFINE(WITH_READLINE)]) - ])]) -],:) - -TFTP_LIBS="$LIBS $XTRALIBS" -LIBS="$common_libs" - -dnl -dnl Check for IPV6 and disable-ipv6 -dnl - -AC_CHECK_MEMBERS(struct sockaddr_in6.sin6_addr) -AC_MSG_CHECKING([for IPv6 support]) -PA_ARG_DISABLED([ipv6], - [disable support for IPv6], - [AC_MSG_RESULT(disabled)], - [AS_IF([test x"$ac_cv_member_struct_sockaddr_in6_sin6_addr$ac_cv_member_struct_addrinfo_ai_addr" = xyesyes], - [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_IPV6, 1, [define if IPv6 support is enabled])], - [AC_MSG_RESULT(no) - AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])])]) - -AC_SUBST(SRCROOT) -AC_SUBST(OBJROOT) - -AC_SUBST(TFTP_LIBS) -AC_SUBST(TFTPD_LIBS) -AC_SUBST(TFTPDOBJS) - -AC_PROG_LN_S -AC_PROG_RANLIB - -dnl -dnl Make sure the install program has an absolute path if it -dnl has a path at all. autoconf doesn't do this "in order -dnl to not pollute the cache." Sigh. -dnl Note: the $ needs to be double-quoted for reasons unknown. -dnl -AC_PROG_INSTALL -[if echo "$INSTALL" | grep '^[^/].*/' > /dev/null 2>&1; then - INSTALL='\${SRCROOT}'/"$INSTALL" -fi] - -PA_ADD_CFLAGS(-W) -PA_ADD_CFLAGS(-Wall) -PA_ADD_CFLAGS(-Wpointer-arith) -PA_ADD_CFLAGS(-Wbad-function-cast) -PA_ADD_CFLAGS(-Wcast-equal) -PA_ADD_CFLAGS(-Wstrict-prototypes) -PA_ADD_CFLAGS(-Wmissing-prototypes) -PA_ADD_CFLAGS(-Wmissing-declarations) -PA_ADD_CFLAGS(-Wnested-externs) -PA_ADD_CFLAGS(-Winline) -PA_ADD_CFLAGS(-Wwrite-strings) -PA_ADD_CFLAGS(-Wundef) -PA_ADD_CFLAGS(-Wshadow) -PA_ADD_CFLAGS(-Wsign-compare) -PA_ADD_CFLAGS(-fno-strict-aliasing) - -dnl -dnl Test compiler features. On some compilers, this can be affected -dnl by -Werror options, so run this *after* those options are added. -dnl -PA_CHECK_BAD_STDC_INLINE -PA_C_TYPEOF - -AC_CONFIG_HEADERS([config/config.h]) -AC_CONFIG_FILES([config/MCONFIG]) -AC_OUTPUT diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..7ab7c5a --- /dev/null +++ b/configure.in @@ -0,0 +1,303 @@ +dnl +dnl autoconf input file to generate MCONFIG +dnl + +AC_PREREQ(2.61) +AC_INIT(MCONFIG.in) +AC_PREFIX_DEFAULT(/usr) + +AC_USE_SYSTEM_EXTENSIONS +AC_ISC_POSIX +AC_PROG_CC + +AC_C_CONST +AC_C_INLINE + +PA_ADD_CFLAGS(-W) +PA_ADD_CFLAGS(-Wall) +PA_ADD_CFLAGS(-Wpointer-arith) +PA_ADD_CFLAGS(-Wbad-function-cast) +PA_ADD_CFLAGS(-Wcast-equal) +PA_ADD_CFLAGS(-Wstrict-prototypes) +PA_ADD_CFLAGS(-Wmissing-prototypes) +PA_ADD_CFLAGS(-Wmissing-declarations) +PA_ADD_CFLAGS(-Wnested-externs) +PA_ADD_CFLAGS(-Winline) +PA_ADD_CFLAGS(-Wwrite-strings) +PA_ADD_CFLAGS(-Wundef) +PA_ADD_CFLAGS(-Wshadow) +PA_ADD_CFLAGS(-Wsign-compare) +PA_ADD_CFLAGS(-pipe) +PA_ADD_CFLAGS(-fno-strict-aliasing) + +AC_HEADER_STDC +AC_CHECK_HEADERS(inttypes.h) +AC_CHECK_HEADERS(stdint.h) +PA_CHECK_INTTYPES_H_SANE +AC_CHECK_HEADERS(fcntl.h) +AC_CHECK_HEADERS(grp.h) +AC_CHECK_HEADERS(libgen.h) +AC_CHECK_HEADERS(memory.h) +AC_CHECK_HEADERS(setjmp.h) +AC_CHECK_HEADERS(stddef.h) +AC_CHECK_HEADERS(stdlib.h) +AC_CHECK_HEADERS(string.h) +AC_CHECK_HEADERS(strings.h) +AC_CHECK_HEADERS(sysexits.h) +AC_CHECK_HEADERS(time.h) +AC_CHECK_HEADERS(unistd.h) +AC_CHECK_HEADERS(sys/file.h) +AC_CHECK_HEADERS(sys/filio.h) +AC_CHECK_HEADERS(sys/stat.h) +AC_CHECK_HEADERS(sys/time.h) +AC_CHECK_HEADERS(sys/types.h) +AC_CHECK_HEADERS(arpa/inet.h) +AC_CHECK_HEADERS(netdb.h) +AC_HEADER_TIME +dnl This is needed on some versions of FreeBSD... +AC_CHECK_HEADERS(machine/param.h) +AC_CHECK_HEADERS(sys/socket.h) +AC_CHECK_HEADERS(winsock2.h) +AC_CHECK_HEADERS(winsock.h) + +AC_SYS_LARGEFILE + +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_MODE_T +AC_TYPE_SIZE_T +AC_CHECK_TYPES(intmax_t) +AC_CHECK_TYPES(long long) +AC_CHECK_TYPES(uint16_t) +AC_CHECK_TYPES(uint32_t) +AC_CHECK_TYPES(u_short) +AC_CHECK_TYPES(u_long) + +dnl +dnl isn't among the list of standard headers that autoconf checks, +dnl but POSIX requires for socklen_t to be defined. +dnl +AC_CHECK_TYPES(socklen_t,,, +[ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +]) + +AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , [AC_MSG_ERROR(socket library not found)]) + +AC_CHECK_FUNCS(fcntl) +AC_CHECK_FUNCS(setsid) +AC_CHECK_FUNCS(recvmsg) +AC_CHECK_FUNCS(ftruncate) +AC_CHECK_FUNCS(setreuid) +AC_CHECK_FUNCS(setregid) +AC_CHECK_FUNCS(initgroups) +AC_CHECK_FUNCS(setgroups) + +dnl Solaris 8 has [u]intmax_t but not strtoumax(). How utterly braindamaged. +AC_CHECK_FUNCS(strtoumax) +AC_CHECK_FUNCS(strtoull) + +PA_MSGHDR_MSG_CONTROL +PA_STRUCT_IN_PKTINFO +PA_STRUCT_ADDRINFO + +PA_HEADER_DEFINES(fcntl.h, int, O_NONBLOCK) +PA_HEADER_DEFINES(fcntl.h, int, O_BINARY) +PA_HEADER_DEFINES(fcntl.h, int, O_TEXT) + +PA_HEADER_DEFINES(fcntl.h, int, F_SETLK) + +PA_HEADER_DEFINES(sys/file.h, int, LOCK_SH) +PA_HEADER_DEFINES(sys/file.h, int, LOCK_EX) + +AH_TEMPLATE([HAVE_SIGSETJMP], +[Define if we have sigsetjmp, siglongjmp and sigjmp_buf.]) +PA_SIGSETJMP([AC_DEFINE(HAVE_SIGSETJMP)]) + +dnl +dnl Get common paths +dnl +SRCROOT=`cd $srcdir && pwd` +OBJROOT=`pwd` + +XTRA=false +PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty) +PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty) +PA_SEARCH_LIBS_AND_ADD(bsd_signal, bsd, bsdsignal) +PA_SEARCH_LIBS_AND_ADD(getopt_long, getopt, getopt_long) +PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv]) +if $pa_add_getaddrinfo +then + AC_SEARCH_LIBS(gethostbyname, [nsl resolv], + [AC_SEARCH_LIBS(herror, [nsl resolv], , + [AC_MSG_ERROR(herror not found)])], + [AC_MSG_ERROR(gethostbyname not found)]) +else + AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], , + [AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)]) + AC_SEARCH_LIBS(gai_strerror, [nsl resolv], , + [AC_MSG_ERROR(getaddrinfo but not gai_strerror found)]) +fi + +PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv]) +if $pa_add_inet_ntop +then + AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], , + [AC_MSG_ERROR(inet_ntoa not found)]) +fi +AC_SEARCH_LIBS(inet_aton, [nsl resolv], ,[AC_MSG_ERROR(inet_aton not found)]) + +AC_CHECK_FUNCS(daemon, , [XTRA=true; AC_LIBOBJ(daemon)]) +AC_CHECK_FUNCS(dup2, , [XTRA=true; AC_LIBOBJ(dup2)]) +if $XTRA +then + XTRALIBS="$OBJROOT/lib/libxtra.a $XTRALIBS" +fi + +dnl +dnl These libraries apply to the server only +dnl + +common_libs="$LIBS" + +PA_HEADER_DEFINES(netinet/in.h, int, IPPORT_TFTP) + +PA_WITH_BOOL(tcpwrappers, 1, +[ --without-tcpwrappers disable tcpwrapper permissions checking], +[ + AC_SEARCH_LIBS(yp_get_default_domain, [nsl resolv]) + PA_HAVE_TCPWRAPPERS +],:) + + +AH_TEMPLATE([WITH_REGEX], +[Define if we are compiling with regex filename remapping.]) + +PA_WITH_BOOL(remap, 1, +[ --without-remap disable regex-based filename remapping], +[ + AC_CHECK_HEADER(regex.h, + [ + AC_SEARCH_LIBS(regcomp, [regex rx], + [ + AC_DEFINE(WITH_REGEX) + TFTPDOBJS="remap.${OBJEXT} $TFTPDOBJS" + ]) + ]) +],:) + +TFTPD_LIBS="$LIBS $XTRALIBS" +LIBS="$common_libs" + +dnl +dnl These libraries apply to the client only +dnl + +AH_TEMPLATE([WITH_READLINE], +[Define if we are compiling with readline/editline command-line editing.]) + +PA_WITH_BOOL(readline, 1, +[ --without-readline disable the use of readline command-line editing], +[ + AC_CHECK_HEADER(readline/readline.h, + [ + dnl readline may need libtermcap or somesuch... + AC_SEARCH_LIBS(tputs, [termcap terminfo]) + + AC_SEARCH_LIBS(readline, [readline history], + [AC_DEFINE(WITH_READLINE)]) + AC_CHECK_HEADERS(readline/history.h) + ], + [AC_CHECK_HEADER(editline/readline.h, + [ + dnl editline may need libtermcap or somesuch... + AC_SEARCH_LIBS(tputs, [termcap terminfo]) + + AC_SEARCH_LIBS(editline, [edit], + [AC_DEFINE(WITH_READLINE)]) + ])]) +],:) + +TFTP_LIBS="$LIBS $XTRALIBS" +LIBS="$common_libs" + +dnl +dnl Check for IPV6 and disable-ipv6 +dnl +PA_STRUCT_SOCKADDR_IN6 +AC_MSG_CHECKING([for IPv6 support]) +PA_WITH_BOOL(ipv6, 1, +[ --without-ipv6 disable the support for IPv6], +[ + if $HAVE_INET6 + then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_IPV6, 1, [Define if IPv6 support is enabled.]) + PA_STRUCT_IN6_PKTINFO + else + AC_MSG_RESULT(no) + AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled]) + fi +], +[AC_MSG_RESULT(disabled)]) + + +AC_SUBST(SRCROOT) +AC_SUBST(OBJROOT) + +AC_SUBST(TFTP_LIBS) +AC_SUBST(TFTPD_LIBS) +AC_SUBST(TFTPDOBJS) + +AC_PROG_LN_S +AC_PROG_RANLIB + +dnl +dnl Make sure the install program has an absolute path if it +dnl has a path at all. autoconf doesn't do this "in order +dnl to not pollute the cache." Sigh. +dnl Note: the $ needs to be double-quoted for reasons unknown. +dnl +AC_PROG_INSTALL +[if echo "$INSTALL" | grep '^[^/].*/' > /dev/null 2>&1; then + INSTALL='\${SRCROOT}'/"$INSTALL" +fi] + +AC_CONFIG_HEADERS(aconfig.h) +AC_OUTPUT(MCONFIG) diff --git a/lib/Makefile b/lib/Makefile index a7fd057..a43ce19 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,7 +4,7 @@ SRCROOT = .. --include ../config/MCONFIG +-include ../MCONFIG include ../MRULES ifeq ($(LIBOBJS),) @@ -25,3 +25,5 @@ libxtra.a: $(LIBOBJS) -rm -f libxtra.a $(AR) libxtra.a $(LIBOBJS) $(RANLIB) libxtra.a + + diff --git a/lib/bsdsignal.c b/lib/bsdsignal.c new file mode 100644 index 0000000..0aae136 --- /dev/null +++ b/lib/bsdsignal.c @@ -0,0 +1,27 @@ +/* + * bsdsignal.c + * + * Use sigaction() to simulate BSD signal() + */ + +#include "config.h" + +void (*bsd_signal(int signum, void (*handler) (int))) (int) { + struct sigaction action, oldaction; + + memset(&action, 0, sizeof action); + action.sa_handler = handler; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, signum); + action.sa_flags = SA_RESTART; + + if (sigaction(signum, &action, &oldaction) == -1) { +#ifdef SIG_ERR + return SIG_ERR; +#else + return NULL; +#endif + } + + return oldaction.sa_handler; +} diff --git a/tftp/Makefile b/tftp/Makefile index 9faa62f..20f4c18 100644 --- a/tftp/Makefile +++ b/tftp/Makefile @@ -1,7 +1,7 @@ SRCROOT = .. VERSION = $(shell cat ../version) --include ../config/MCONFIG +-include ../MCONFIG include ../MRULES OBJS = tftp.$(O) main.$(O) diff --git a/tftp/extern.h b/tftp/extern.h index 9c578e6..78474fc 100644 --- a/tftp/extern.h +++ b/tftp/extern.h @@ -31,13 +31,10 @@ * SUCH DAMAGE. */ -#ifndef EXTERN_H -#define EXTERN_H - -#include "config.h" +#ifndef RECVFILE_H +#define RECVFILE_H void tftp_recvfile(int, const char *, const char *); void tftp_sendfile(int, const char *, const char *); -extern sigjmp_buf toplevel; #endif diff --git a/tftp/main.c b/tftp/main.c index ecdc0e0..1b8a881 100644 --- a/tftp/main.c +++ b/tftp/main.c @@ -188,7 +188,7 @@ char *xstrdup(const char *); const char *program; -static void usage(int errcode) +static inline void usage(int errcode) { fprintf(stderr, #ifdef HAVE_IPV6 @@ -305,7 +305,7 @@ int main(int argc, char *argv[]) sp->s_proto = (char *)"udp"; } - tftp_signal(SIGINT, intr, 0); + bsd_signal(SIGINT, intr); if (peerargc) { /* Set peer */ @@ -768,8 +768,8 @@ void intr(int sig) { (void)sig; /* Quiet unused warning */ + bsd_signal(SIGALRM, SIG_IGN); alarm(0); - tftp_signal(SIGALRM, SIG_DFL, 0); siglongjmp(toplevel, -1); } @@ -806,7 +806,6 @@ static void command(void) exit(0); /* EOF */ #else fputs(prompt, stdout); - fflush(stdout); if (fgets(line, LBUFLEN, stdin) == 0) { if (feof(stdin)) { exit(0); diff --git a/tftp/tftp.c b/tftp/tftp.c index 9c9c5af..d15da22 100644 --- a/tftp/tftp.c +++ b/tftp/tftp.c @@ -48,7 +48,8 @@ extern int maxtimeout; #define PKTSIZE SEGSIZE+4 char ackbuf[PKTSIZE]; int timeout; -static sigjmp_buf timeoutbuf; +sigjmp_buf toplevel; +sigjmp_buf timeoutbuf; static void nak(int, const char *); static int makerequest(int, const char *, struct tftphdr *, const char *); @@ -84,7 +85,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode) is_request = 1; /* First packet is the actual WRQ */ amount = 0; - tftp_signal(SIGALRM, timer, 0); + bsd_signal(SIGALRM, timer); do { if (is_request) { size = makerequest(WRQ, name, dp, mode) - 4; @@ -190,7 +191,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode) firsttrip = 1; amount = 0; - tftp_signal(SIGALRM, timer, 0); + bsd_signal(SIGALRM, timer); do { if (firsttrip) { size = makerequest(RRQ, name, ap, mode); @@ -278,16 +279,15 @@ makerequest(int request, const char *name, struct tftphdr *tp, const char *mode) { char *cp; - size_t len; tp->th_opcode = htons((u_short) request); cp = (char *)&(tp->th_stuff); - len = strlen(name) + 1; - memcpy(cp, name, len); - cp += len; - len = strlen(mode) + 1; - memcpy(cp, mode, len); - cp += len; + strcpy(cp, name); + cp += strlen(name); + *cp++ = '\0'; + strcpy(cp, mode); + cp += strlen(mode); + *cp++ = '\0'; return (cp - (char *)tp); } diff --git a/tftpd/Makefile b/tftpd/Makefile index 5963581..a05335d 100644 --- a/tftpd/Makefile +++ b/tftpd/Makefile @@ -1,7 +1,7 @@ SRCROOT = .. VERSION = $(shell cat ../version) --include ../config/MCONFIG +-include ../MCONFIG include ../MRULES OBJS = tftpd.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS) diff --git a/tftpd/misc.c b/tftpd/misc.c index 9070f96..07684dd 100644 --- a/tftpd/misc.c +++ b/tftpd/misc.c @@ -19,11 +19,19 @@ #include "tftpd.h" /* - * Set the signal handler and flags, and error out on failure. + * Set the signal handler and flags. Basically a user-friendly + * wrapper around sigaction(). */ -void set_signal(int signum, sighandler_t handler, int flags) +void set_signal(int signum, void (*handler) (int), int flags) { - if (tftp_signal(signum, handler, flags)) { + struct sigaction sa; + + memset(&sa, 0, sizeof sa); + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = flags; + + if (sigaction(signum, &sa, NULL)) { syslog(LOG_ERR, "sigaction: %m"); exit(EX_OSERR); } diff --git a/tftpd/recvfrom.c b/tftpd/recvfrom.c index 320678d..3ee5642 100644 --- a/tftpd/recvfrom.c +++ b/tftpd/recvfrom.c @@ -26,12 +26,10 @@ #if defined(HAVE_RECVMSG) && defined(HAVE_MSGHDR_MSG_CONTROL) -#ifdef HAVE_SYS_UIO_H -# include -#endif +#include #ifdef IP_PKTINFO -# ifndef HAVE_STRUCT_IN_PKTINFO_IPI_ADDR +# ifndef HAVE_STRUCT_IN_PKTINFO # ifdef __linux__ /* Assume this version of glibc simply lacks the definition */ struct in_pktinfo { @@ -53,59 +51,52 @@ struct in_pktinfo { #endif /* - * Check to see if this is a valid local address, meaning that we can - * legally bind to it. + * Check to see if this is a valid local address. If so, we should + * end up having the same local and remote address when trying to + * bind to it. */ static int address_is_local(const union sock_addr *addr) { - union sock_addr sa1, sa2; + union sock_addr sa; int sockfd = -1; int e; int rv = 0; socklen_t addrlen; - memcpy(&sa1, addr, sizeof sa1); - /* Multicast or universal broadcast address? */ - if (sa1.sa.sa_family == AF_INET) { - if (ntohl(sa1.si.sin_addr.s_addr) >= (224UL << 24)) + if (addr->sa.sa_family == AF_INET) { + if (ntohl(addr->si.sin_addr.s_addr) >= (224UL << 24)) return 0; - sa1.si.sin_port = 0; /* Any port */ } #ifdef HAVE_IPV6 - else if (sa1.sa.sa_family == AF_INET6) { - if (IN6_IS_ADDR_MULTICAST(&sa1.s6.sin6_addr)) + else if (addr->sa.sa_family == AF_INET6) { + if (IN6_IS_ADDR_MULTICAST(&addr->s6.sin6_addr)) return 0; - sa1.s6.sin6_port = 0; /* Any port */ } #endif else return 0; - sockfd = socket(sa1.sa.sa_family, SOCK_DGRAM, 0); + sockfd = socket(addr->sa.sa_family, SOCK_DGRAM, 0); if (sockfd < 0) goto err; - if (bind(sockfd, &sa1.sa, SOCKLEN(&sa1))) + if (connect(sockfd, &addr->sa, SOCKLEN(addr))) goto err; addrlen = SOCKLEN(addr); - if (getsockname(sockfd, (struct sockaddr *)&sa2, &addrlen)) + if (getsockname(sockfd, (struct sockaddr *)&sa, &addrlen)) goto err; - if (sa1.sa.sa_family != sa2.sa.sa_family) - goto err; - - if (sa2.sa.sa_family == AF_INET) - rv = sa1.si.sin_addr.s_addr == sa2.si.sin_addr.s_addr; + if (addr->sa.sa_family == AF_INET) + rv = sa.si.sin_addr.s_addr == addr->si.sin_addr.s_addr; #ifdef HAVE_IPV6 - else if (sa2.sa.sa_family == AF_INET6) - rv = IN6_ARE_ADDR_EQUAL(&sa1.s6.sin6_addr, &sa2.s6.sin6_addr); + else if (addr->sa.sa_family == AF_INET6) + rv = IN6_ARE_ADDR_EQUAL(&sa.s6.sin6_addr, &addr->s6.sin6_addr); #endif else rv = 0; - -err: + err: e = errno; if (sockfd >= 0) @@ -115,31 +106,10 @@ err: return rv; } -static void normalize_ip6_compat(union sock_addr *myaddr) -{ -#ifdef HAVE_IPV6 - static const uint8_t ip6_compat_prefix[12] = - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; - struct sockaddr_in in; - - if (myaddr->sa.sa_family == AF_INET6 && - !memcmp(&myaddr->s6.sin6_addr, ip6_compat_prefix, - sizeof ip6_compat_prefix)) { - bzero(&in, sizeof in); - in.sin_family = AF_INET; - in.sin_port = myaddr->s6.sin6_port; - memcpy(&in.sin_addr, (const char *)&myaddr->s6.sin6_addr + - sizeof ip6_compat_prefix, sizeof in.sin_addr); - memcpy(&myaddr->si, &in, sizeof in); - } -#else - (void)myaddr; -#endif -} - int myrecvfrom(int s, void *buf, int len, unsigned int flags, - union sock_addr *from, union sock_addr *myaddr) + struct sockaddr *from, socklen_t * fromlen, + union sock_addr *myaddr) { struct msghdr msg; struct iovec iov; @@ -172,16 +142,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, /* Try to enable getting the return address */ #ifdef IP_RECVDSTADDR - if (from->sa.sa_family == AF_INET) + if (from->sa_family == AF_INET) setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)); #endif #ifdef IP_PKTINFO - if (from->sa.sa_family == AF_INET) + if (from->sa_family == AF_INET) setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)); #endif #ifdef HAVE_IPV6 #ifdef IPV6_RECVPKTINFO - if (from->sa.sa_family == AF_INET6) + if (from->sa_family == AF_INET6) setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); #endif #endif @@ -190,8 +160,8 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, msg.msg_controllen = sizeof(control_un); msg.msg_flags = 0; - msg.msg_name = &from->sa; - msg.msg_namelen = sizeof(*from); + msg.msg_name = from; + msg.msg_namelen = *fromlen; iov.iov_base = buf; iov.iov_len = len; msg.msg_iov = &iov; @@ -200,9 +170,11 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, if ((n = recvmsg(s, &msg, flags)) < 0) return n; /* Error */ + *fromlen = msg.msg_namelen; + if (myaddr) { bzero(myaddr, sizeof(*myaddr)); - myaddr->sa.sa_family = from->sa.sa_family; + myaddr->sa.sa_family = from->sa_family; if (msg.msg_controllen < sizeof(struct cmsghdr) || (msg.msg_flags & MSG_CTRUNC)) @@ -211,7 +183,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; cmptr = CMSG_NXTHDR(&msg, cmptr)) { - if (from->sa.sa_family == AF_INET) { + if (from->sa_family == AF_INET) { myaddr->sa.sa_family = AF_INET; #ifdef IP_RECVDSTADDR if (cmptr->cmsg_level == IPPROTO_IP && @@ -232,7 +204,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, #endif } #ifdef HAVE_IPV6 - else if (from->sa.sa_family == AF_INET6) { + else if (from->sa_family == AF_INET6) { myaddr->sa.sa_family = AF_INET6; #ifdef IP6_RECVDSTADDR if (cmptr->cmsg_level == IPPROTO_IPV6 && @@ -243,23 +215,17 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, #ifdef HAVE_STRUCT_IN6_PKTINFO if (cmptr->cmsg_level == IPPROTO_IPV6 && - ( -#ifdef IPV6_RECVPKTINFO - cmptr->cmsg_type == IPV6_RECVPKTINFO || -#endif + (cmptr->cmsg_type == IPV6_RECVPKTINFO || cmptr->cmsg_type == IPV6_PKTINFO)) { - memcpy(&pktinfo6, CMSG_DATA(cmptr), - sizeof(struct in6_pktinfo)); - memcpy(&myaddr->s6.sin6_addr, &pktinfo6.ipi6_addr, - sizeof(struct in6_addr)); + memcpy(&pktinfo6, CMSG_DATA(cmptr), + sizeof(struct in6_pktinfo)); + memcpy(&myaddr->s6.sin6_addr, &pktinfo6.ipi6_addr, + sizeof(struct in6_addr)); } #endif } #endif } - - normalize_ip6_compat(myaddr); - /* If the address is not a valid local address, * then bind to any address... */ @@ -272,9 +238,6 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, #endif } } - - normalize_ip6_compat(from); - return n; } @@ -282,16 +245,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags, int myrecvfrom(int s, void *buf, int len, unsigned int flags, - union sock_addr *from, union sock_addr *myaddr) + struct sockaddr *from, socklen_t * fromlen, + union sock_addr *myaddr) { /* There is no way we can get the local address, fudge it */ - socklen_t fromlen = sizeof(*from); bzero(myaddr, sizeof(*myaddr)); - myaddr->sa.sa_family = from->sa.sa_family; + myaddr->sa.sa_family = from->sa_family; sa_set_port(myaddr, htons(IPPORT_TFTP)); - return recvfrom(s, buf, len, flags, &from->sa, &fromlen); + return recvfrom(s, buf, len, flags, from, fromlen); } #endif diff --git a/tftpd/recvfrom.h b/tftpd/recvfrom.h index 7773a0d..e3c4055 100644 --- a/tftpd/recvfrom.h +++ b/tftpd/recvfrom.h @@ -19,4 +19,5 @@ int myrecvfrom(int s, void *buf, int len, unsigned int flags, - union sock_addr *from, union sock_addr *myaddr); + struct sockaddr *from, socklen_t *fromlen, + union sock_addr *myaddr); diff --git a/tftpd/remap.c b/tftpd/remap.c index 413d117..1e7abe7 100644 --- a/tftpd/remap.c +++ b/tftpd/remap.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2001-2024 H. Peter Anvin - All Rights Reserved + * Copyright 2001-2007 H. Peter Anvin - All Rights Reserved * * This program is free software available under the same license * as the "OpenBSD" operating system, distributed at @@ -22,7 +22,7 @@ #include "tftpd.h" #include "remap.h" -#define DEADMAN_MAX_STEPS 4096 /* Timeout after this many steps */ +#define DEADMAN_MAX_STEPS 1024 /* Timeout after this many steps */ #define MAXLINE 16384 /* Truncate a line at this many bytes */ #define RULE_REWRITE 0x01 /* This is a rewrite rule */ @@ -31,20 +31,12 @@ #define RULE_RESTART 0x08 /* Restart at the top after matching this rule */ #define RULE_ABORT 0x10 /* Terminate processing with an error */ #define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */ -#define RULE_IPV4 0x40 /* IPv4 only */ -#define RULE_IPV6 0x80 /* IPv6 only */ - -#define RULE_HASFILE 0x100 /* Valid if rule results in a valid filename */ -#define RULE_RRQ 0x200 /* Get (read) only */ -#define RULE_WRQ 0x400 /* Put (write) only */ -#define RULE_SEDG 0x800 /* sed-style global */ - -int deadman_max_steps = DEADMAN_MAX_STEPS; struct rule { struct rule *next; int nrule; - unsigned int rule_flags; + int rule_flags; + char rule_mode; regex_t rx; const char *pattern; }; @@ -64,30 +56,22 @@ static int xform_tolower(int c) return tolower(c); } -/* - * Do \-substitution. Call with string == NULL to get length only. - * "start" indicates an offset into the input buffer where the pattern - * match was started. - */ -static int do_genmatchstring(char *string, const char *pattern, - const char *ibuf, - const regmatch_t * pmatch, - match_pattern_callback macrosub, - int start, int *nextp) +/* Do \-substitution. Call with string == NULL to get length only. */ +static int genmatchstring(char *string, const char *pattern, + const char *input, const regmatch_t * pmatch, + match_pattern_callback macrosub) { int (*xform) (int) = xform_null; int len = 0; int n, mlen, sublen; int endbytes; - const char *input = ibuf + start; /* Get section before match; note pmatch[0] is the whole match */ endbytes = strlen(input) - pmatch[0].rm_eo; - len = start + pmatch[0].rm_so; + len = pmatch[0].rm_so + endbytes; if (string) { - /* Copy the prefix before "start" as well! */ - memcpy(string, ibuf, start + pmatch[0].rm_so); - string += start + pmatch[0].rm_so; + memcpy(string, input, pmatch[0].rm_so); + string += pmatch[0].rm_so; } /* Transform matched section */ @@ -113,7 +97,7 @@ static int do_genmatchstring(char *string, const char *pattern, mlen = pmatch[n].rm_eo - pmatch[n].rm_so; len += mlen; if (string) { - const char *p = input + start + pmatch[n].rm_so; + const char *p = input + pmatch[n].rm_so; while (mlen--) *string++ = xform(*p++); } @@ -156,12 +140,7 @@ static int do_genmatchstring(char *string, const char *pattern, } } - /* Pointer to post-substitution tail */ - if (nextp) - *nextp = len; - /* Copy section after match */ - len += endbytes; if (string) { memcpy(string, input + pmatch[0].rm_eo, endbytes); string[endbytes] = '\0'; @@ -170,26 +149,6 @@ static int do_genmatchstring(char *string, const char *pattern, return len; } -/* - * Ditto, but allocate the string in a new buffer - */ - -static int genmatchstring(char **string, const char *pattern, - const char *ibuf, - const regmatch_t * pmatch, - match_pattern_callback macrosub, - int start, int *nextp) -{ - int len; - char *buf; - - len = do_genmatchstring(NULL, pattern, ibuf, pmatch, - macrosub, start, NULL); - *string = buf = tfmalloc(len + 1); - return do_genmatchstring(buf, pattern, ibuf, pmatch, - macrosub, start, nextp); -} - /* * Extract a string terminated by non-escaped whitespace; ignoring * leading whitespace. Consider an unescaped # to be a comment marker, @@ -247,17 +206,11 @@ static int parseline(char *line, struct rule *r, int lineno) r->rule_flags |= RULE_REWRITE; break; case 'g': - if (r->rule_flags & RULE_GLOBAL) - r->rule_flags |= RULE_SEDG; - else - r->rule_flags |= RULE_GLOBAL; + r->rule_flags |= RULE_GLOBAL; break; case 'e': r->rule_flags |= RULE_EXIT; break; - case 'E': - r->rule_flags |= RULE_HASFILE; - break; case 's': r->rule_flags |= RULE_RESTART; break; @@ -270,17 +223,9 @@ static int parseline(char *line, struct rule *r, int lineno) case '~': r->rule_flags |= RULE_INVERSE; break; - case '4': - r->rule_flags |= RULE_IPV4; - break; - case '6': - r->rule_flags |= RULE_IPV6; - break; - case 'G': - r->rule_flags |= RULE_RRQ; - break; - case 'P': - r->rule_flags |= RULE_WRQ; + case 'G': + case 'P': + r->rule_mode = *p; break; default: syslog(LOG_ERR, @@ -291,21 +236,15 @@ static int parseline(char *line, struct rule *r, int lineno) } } - if (r->rule_flags & RULE_REWRITE) { - if (r->rule_flags & RULE_INVERSE) { - syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n", - lineno, line); - return -1; /* Error */ - } - if ((r->rule_flags & (RULE_GLOBAL|RULE_SEDG|RULE_HASFILE)) - == (RULE_GLOBAL|RULE_HASFILE)) { - syslog(LOG_ERR, "E rules cannot be combined with g (but gg is OK), line %d: %s\n", - lineno, line); - return -1; /* Error */ - } - } else { - /* RULE_GLOBAL and RULE_SEDG are meaningless without RULE_REWRITE */ - r->rule_flags &= ~(RULE_GLOBAL|RULE_SEDG); + /* RULE_GLOBAL only applies when RULE_REWRITE specified */ + if (!(r->rule_flags & RULE_REWRITE)) + r->rule_flags &= ~RULE_GLOBAL; + + if ((r->rule_flags & (RULE_INVERSE | RULE_REWRITE)) == + (RULE_INVERSE | RULE_REWRITE)) { + syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n", + lineno, line); + return -1; /* Error */ } /* Read and compile the regex */ @@ -386,24 +325,17 @@ void freerules(struct rule *r) } /* Execute a rule set on a string; returns a malloc'd new string. */ -char *rewrite_string(const struct formats *pf, - const char *input, const struct rule *rules, - int mode, int af, match_pattern_callback macrosub, +char *rewrite_string(const char *input, const struct rule *rules, + char mode, match_pattern_callback macrosub, const char **errmsg) { char *current = tfstrdup(input); - char *newstr, *newerstr; - const char *accerr; + char *newstr; const struct rule *ruleptr = rules; regmatch_t pmatch[10]; - int i; int len; int was_match = 0; - int deadman = deadman_max_steps; - int matchsense; - int pmatches; - unsigned int bad_flags; - int ggoffset; + int deadman = DEADMAN_MAX_STEPS; /* Default error */ *errmsg = "Remap table failure"; @@ -412,121 +344,86 @@ char *rewrite_string(const struct formats *pf, syslog(LOG_INFO, "remap: input: %s", current); } - bad_flags = 0; - if (mode != RRQ) bad_flags |= RULE_RRQ; - if (mode != WRQ) bad_flags |= RULE_WRQ; - if (af != AF_INET) bad_flags |= RULE_IPV4; - if (af != AF_INET6) bad_flags |= RULE_IPV6; - for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) { - if (ruleptr->rule_flags & bad_flags) - continue; /* This rule is excluded by flags */ + if (ruleptr->rule_mode && ruleptr->rule_mode != mode) + continue; /* Rule not applicable, try next */ - matchsense = ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0; - pmatches = ruleptr->rule_flags & RULE_INVERSE ? 0 : 10; - - /* Clear the pmatch[] array */ - for (i = 0; i < 10; i++) - pmatch[i].rm_so = pmatch[i].rm_eo = -1; - - was_match = 0; + if (!deadman--) { + syslog(LOG_WARNING, + "remap: Breaking loop, input = %s, last = %s", input, + current); + free(current); + return NULL; /* Did not terminate! */ + } do { - if (!deadman--) - goto dead; + if (regexec(&ruleptr->rx, current, 10, pmatch, 0) == + (ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) { + /* Match on this rule */ + was_match = 1; - if (regexec(&ruleptr->rx, current, pmatches, pmatch, 0) - != matchsense) - break; /* No match, break out of do loop */ - - /* Match on this rule */ - was_match = 1; - - if (ruleptr->rule_flags & RULE_ABORT) { - if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: abort: %s", - ruleptr->nrule, current); - } - if (ruleptr->pattern[0]) { - /* Custom error message */ - genmatchstring(&newstr, ruleptr->pattern, current, - pmatch, macrosub, 0, NULL); - *errmsg = newstr; - } else { - *errmsg = NULL; - } - free(current); - return (NULL); - } - - if (ruleptr->rule_flags & RULE_REWRITE) { - len = genmatchstring(&newstr, ruleptr->pattern, current, - pmatch, macrosub, 0, &ggoffset); - - if (ruleptr->rule_flags & RULE_SEDG) { - /* sed-style partial-matching global */ - while (ggoffset < len && - regexec(&ruleptr->rx, newstr + ggoffset, - pmatches, pmatch, - ggoffset ? REG_NOTBOL : 0) - == matchsense) { - if (!deadman--) { - free(current); - current = newstr; - goto dead; - } - len = genmatchstring(&newerstr, ruleptr->pattern, - newstr, pmatch, macrosub, - ggoffset, &ggoffset); - free(newstr); - newstr = newerstr; - } + if (ruleptr->rule_flags & RULE_INVERSE) { + /* No actual match, so clear out the pmatch array */ + int i; + for (i = 0; i < 10; i++) + pmatch[i].rm_so = pmatch[i].rm_eo = -1; } - if ((ruleptr->rule_flags & RULE_HASFILE) && - pf->f_validate(newstr, mode, pf, &accerr)) { + if (ruleptr->rule_flags & RULE_ABORT) { if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: ignored rewrite (%s): %s", - ruleptr->nrule, accerr, newstr); + syslog(LOG_INFO, "remap: rule %d: abort: %s", + ruleptr->nrule, current); } - free(newstr); - was_match = 0; - break; + if (ruleptr->pattern[0]) { + /* Custom error message */ + len = + genmatchstring(NULL, ruleptr->pattern, current, + pmatch, macrosub); + newstr = tfmalloc(len + 1); + genmatchstring(newstr, ruleptr->pattern, current, + pmatch, macrosub); + *errmsg = newstr; + } else { + *errmsg = NULL; + } + free(current); + return (NULL); } - free(current); - current = newstr; - if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: rewrite: %s", - ruleptr->nrule, current); - } - } else if (ruleptr->rule_flags & RULE_HASFILE) { - if (pf->f_validate(current, mode, pf, &accerr)) { + if (ruleptr->rule_flags & RULE_REWRITE) { + len = genmatchstring(NULL, ruleptr->pattern, current, + pmatch, macrosub); + newstr = tfmalloc(len + 1); + genmatchstring(newstr, ruleptr->pattern, current, + pmatch, macrosub); + free(current); + current = newstr; if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: not exiting (%s)\n", - ruleptr->nrule, accerr); + syslog(LOG_INFO, "remap: rule %d: rewrite: %s", + ruleptr->nrule, current); } - was_match = 0; - break; } + } else { + break; /* No match, terminate unconditionally */ } - /* If the rule is (old-style) global, keep going until no match */ - } while ((ruleptr->rule_flags & (RULE_GLOBAL|RULE_SEDG)) == RULE_GLOBAL); + /* If the rule is global, keep going until no match */ + } while (ruleptr->rule_flags & RULE_GLOBAL); - if (!was_match) - continue; /* Next rule */ + if (was_match) { + was_match = 0; - if (ruleptr->rule_flags & (RULE_EXIT|RULE_HASFILE)) { - if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: exit", - ruleptr->nrule); - } - return current; /* Exit here, we're done */ - } else if (ruleptr->rule_flags & RULE_RESTART) { - ruleptr = rules; /* Start from the top */ - if (verbosity >= 3) { - syslog(LOG_INFO, "remap: rule %d: restart", - ruleptr->nrule); + if (ruleptr->rule_flags & RULE_EXIT) { + if (verbosity >= 3) { + syslog(LOG_INFO, "remap: rule %d: exit", + ruleptr->nrule); + } + return current; /* Exit here, we're done */ + } else if (ruleptr->rule_flags & RULE_RESTART) { + ruleptr = rules; /* Start from the top */ + if (verbosity >= 3) { + syslog(LOG_INFO, "remap: rule %d: restart", + ruleptr->nrule); + } } } } @@ -535,11 +432,4 @@ char *rewrite_string(const struct formats *pf, syslog(LOG_INFO, "remap: done"); } return current; - -dead: /* Deadman expired */ - syslog(LOG_ERR, - "remap: Breaking loop after %d steps, input = %s, last = %s", - deadman_max_steps, input, current); - free(current); - return NULL; /* Did not terminate! */ } diff --git a/tftpd/remap.h b/tftpd/remap.h index c8d76ff..69ca08d 100644 --- a/tftpd/remap.h +++ b/tftpd/remap.h @@ -35,13 +35,8 @@ struct rule *parserulefile(FILE *); void freerules(struct rule *); /* Execute a rule set on a string; returns a malloc'd new string. */ -struct formats; -char *rewrite_string(const struct formats *, const char *, - const struct rule *, int, int, +char *rewrite_string(const char *, const struct rule *, char, match_pattern_callback, const char **); -/* Remapping deadman counter */ -extern int deadman_max_steps; - #endif /* WITH_REGEX */ #endif /* TFTPD_REMAP_H */ diff --git a/tftpd/tftpd.8.in b/tftpd/tftpd.8.in index 3d43325..78b4cfb 100644 --- a/tftpd/tftpd.8.in +++ b/tftpd/tftpd.8.in @@ -1,5 +1,5 @@ .\" -*- nroff -*- --------------------------------------------------------- * -.\" +.\" .\" Copyright (c) 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\"----------------------------------------------------------------------- */ -.TH TFTPD 8 "7 June 2014" "tftp-hpa @@VERSION@@" "System Manager's Manual" +.TH TFTPD 8 "14 September 2009" "tftp-hpa @@VERSION@@" "System Manager's Manual" .SH NAME .B tftpd \- Trivial File Transfer Protocol server @@ -155,7 +155,7 @@ or .B utimeout option is negotiated. The default is 1000000 (1 second.) .TP -\fB\-\-map-file\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP +\fB\-\-mapfile\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP Specify the use of filename remapping. The .I remap-file is a file containing the remapping rules. See the section on filename @@ -163,10 +163,6 @@ remapping below. This option may not be compiled in, see the output of .B "in.tftpd \-V" to verify whether or not it is available. .TP -.\fB\-\-map-steps\fP \fIsteps\fP -Specify the number of remapping rules that may be executed before the -filename mapping fails. The default is 4096. -.TP \fB\-\-verbose\fP, \fB\-v\fP Increase the logging verbosity of .BR tftpd . @@ -242,7 +238,7 @@ option, but crash with an error if they actually get the option accepted by the server. .SH "FILENAME REMAPPING" The -.B \-\-map-file +.B \-\-mapfile option specifies a file which contains filename remapping rules. Each non-comment line (comments begin with hash marks, .BR # ) @@ -274,18 +270,7 @@ by the The replacement pattern may contain escape sequences; see below. .TP .B g -Repeat this rule until it no longer matches. This is always used with -.BR r . -.TP -.B gg -Repeat this rule until it no longer matches, but only on the portion -of the string that has not yet been matched, similar to how the -.B s -command with the -.B g -option works in -.BR sed (1). -This is always used with +Repeat this rule until it no longer matches. This is always used with .BR r . .TP .B i @@ -296,17 +281,6 @@ case-insensitively. By default it is case sensitive. .B e If this rule matches, end rule processing after executing the rule. .TP -.B E -If this rule matches, -\fIand the result matches a filename that can be transferred\fP, -end rule processing after executing the rule. If this is combined with -.BR r , -then if the substitution does \fInot\fP result in a valid filename, -the substitution is undone. This cannot be combined with -.BR g , -but \fIcan\fP be combined with -.BR gg . -.TP .B s If this rule matches, start rule processing over from the very first rule after executing this rule. @@ -321,22 +295,16 @@ This rule applies to GET (RRQ) requests only. .B P This rule applies to PUT (WRQ) requests only. .TP -.B 4 -This rule applies to IPv4 sessions only. -.TP -.B 6 -This rule applies to IPv6 sessions only. -.TP .B ~ Inverse the sense of this rule, i.e. execute the .I operation only if the .I regex .I doesn't -match. Cannot used together with +match. Cannot used together with .BR r . .PP -The following escape sequences are recognized as part of a +The following escape sequences are recognized as part of the .IR "replacement pattern" : .TP \fB\\0\fP @@ -350,14 +318,12 @@ subexpressions, \\( ... \\), of the pattern. .TP \fB\\i\fP -The IP address of the requesting host, in dotted-quad notation for -IPv4 (e.g. 192.0.2.169) or conventional colon form for IPv6 -(e.g. 2001:db8::1). +The IP address of the requesting host, in dotted-quad notation +(e.g. 192.0.2.169). .TP \fB\\x\fP -The IP address of the requesting host, in expanded hexadecimal -notation (e.g. C00002A9 for IPv4, or 20010DB8000000000000000000000001 -for IPv6). +The IP address of the requesting host, in hexadecimal notation +(e.g. C00002A9). .TP \fB\\\\\fP Literal backslash. @@ -417,14 +383,14 @@ Access to files can, and should, be restricted by invoking .B tftpd with a list of directories by including pathnames as server program arguments on the command line. In this case access is restricted to -files whose names are prefixed by one of the given directories. If +files whole names are prefixed by one of the given directories. If possible, it is recommended that the .B \-\-secure flag is used to set up a chroot() environment for the server to run in once a connection has been set up. .PP Finally, the filename remapping -.RB ( \-\-map-file +.RB ( \-\-mapfile flag) support can be used to provide a limited amount of additional access control. .SH "CONFORMING TO" diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index e0041dc..1873e70 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -1,7 +1,7 @@ /* * Copyright (c) 1983 Regents of the University of California. * Copyright (c) 1999-2009 H. Peter Anvin - * Copyright (c) 2011-2014 Intel Corporation; author: H. Peter Anvin + * Copyright (c) 2011 Intel Corporation; author: H. Peter Anvin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,7 +76,7 @@ static int ai_fam = AF_INET; #define TRIES 6 /* Number of attempts to send each packet */ #define TIMEOUT_LIMIT ((1 << TRIES)-1) -const char *tftpd_progname; +const char *__progname; static int peer; static unsigned long timeout = TIMEOUT; /* Current timeout value */ static unsigned long rexmtval = TIMEOUT; /* Basic timeout value */ @@ -93,6 +93,7 @@ static unsigned int max_blksize = MAX_SEGSIZE; static char tmpbuf[INET6_ADDRSTRLEN], *tmp_p; static union sock_addr from; +static socklen_t fromlen; static off_t tsize; static int tsize_ok; @@ -106,12 +107,11 @@ int portrange = 0; unsigned int portrange_from, portrange_to; int verbosity = 0; +struct formats; #ifdef WITH_REGEX static struct rule *rewrite_rules = NULL; #endif -static FILE *file; - int tftp(struct tftphdr *, int); static void nak(int, const char *); static void timer(int); @@ -153,7 +153,7 @@ static void handle_exit(int sig) } /* Handle timeout signal or timeout event */ -static void timer(int sig) +void timer(int sig) { (void)sig; /* Suppress unused warning */ timeout <<= 1; @@ -163,14 +163,14 @@ static void timer(int sig) } #ifdef WITH_REGEX -static struct rule *read_remap_rules(const char *rulefile) +static struct rule *read_remap_rules(const char *file) { FILE *f; struct rule *rulep; - f = fopen(rulefile, "rt"); + f = fopen(file, "rt"); if (!f) { - syslog(LOG_ERR, "Cannot open map file: %s: %m", rulefile); + syslog(LOG_ERR, "Cannot open map file: %s: %m", file); exit(EX_NOINPUT); } rulep = parserulefile(f); @@ -185,8 +185,7 @@ static struct rule *read_remap_rules(const char *rulefile) */ static int lock_file(int fd, int lock_write) { - (void)lock_write; -#if defined(HAVE_FCNTL) && HAVE_DECL_F_SETLK +#if defined(HAVE_FCNTL) && defined(HAVE_F_SETLK_DEFINITION) struct flock fl; fl.l_type = lock_write ? F_WRLCK : F_RDLCK; @@ -194,7 +193,7 @@ static int lock_file(int fd, int lock_write) fl.l_start = 0; fl.l_len = 0; /* Whole file */ return fcntl(fd, F_SETLK, &fl); -#elif defined(HAVE_FLOCK) && HAVE_DECL_LOCK_SH && HAVE_DECL_LOCK_EX +#elif defined(HAVE_LOCK_SH_DEFINITION) return flock(fd, lock_write ? LOCK_EX|LOCK_NB : LOCK_SH|LOCK_NB); #else return 0; /* Hope & pray... */ @@ -325,9 +324,8 @@ static int split_port(char **ap, char **pp) enum long_only_options { OPT_VERBOSITY = 256, - OPT_MAP_STEPS }; - + static struct option long_options[] = { { "ipv4", 0, NULL, '4' }, { "ipv6", 0, NULL, '6' }, @@ -348,7 +346,6 @@ static struct option long_options[] = { { "retransmit", 1, NULL, 'T' }, { "port-range", 1, NULL, 'R' }, { "map-file", 1, NULL, 'm' }, - { "map-steps", 1, NULL, OPT_MAP_STEPS }, { "pidfile", 1, NULL, 'P' }, { NULL, 0, NULL, 0 } }; @@ -378,7 +375,6 @@ int main(int argc, char **argv) int spec_umask = 0; int c; int setrv; - int die; int waittime = 900; /* Default time to wait for a connect */ const char *user = "nobody"; /* Default user */ char *p, *ep; @@ -391,9 +387,9 @@ int main(int argc, char **argv) /* basename() is way too much of a pain from a portability standpoint */ p = strrchr(argv[0], '/'); - tftpd_progname = (p && p[1]) ? p + 1 : argv[0]; + __progname = (p && p[1]) ? p + 1 : argv[0]; - openlog(tftpd_progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); + openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); srand(time(NULL) ^ getpid()); @@ -497,17 +493,6 @@ int main(int argc, char **argv) } rewrite_file = optarg; break; - case OPT_MAP_STEPS: - { - unsigned long steps = strtoul(optarg, &ep, 0); - if (*optarg && *ep && steps > 0 && steps <= INT_MAX) { - deadman_max_steps = steps; - } else { - syslog(LOG_ERR, "Bad --map-steps option: %s", optarg); - exit(EX_USAGE); - } - break; - } #endif case 'v': verbosity++; @@ -889,7 +874,9 @@ int main(int argc, char **argv) set_socket_nonblock(fd, 0); #endif - n = myrecvfrom(fd, buf, sizeof(buf), 0, &from, &myaddr); + fromlen = sizeof(from); + n = myrecvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&from, &fromlen, &myaddr); if (n < 0) { if (E_WOULD_BLOCK(errno) || errno == EINTR) { @@ -951,14 +938,14 @@ int main(int argc, char **argv) syslog daemon gets restarted by the time we get here. */ if (secure && standalone) { closelog(); - openlog(tftpd_progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); + openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); } #ifdef HAVE_TCPWRAPPERS /* Verify if this was a legal request for us. This has to be done before the chroot, while /etc is still accessible. */ request_init(&wrap_request, - RQ_DAEMON, tftpd_progname, + RQ_DAEMON, __progname, RQ_FILE, fd, RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0); sock_methods(&wrap_request); @@ -990,29 +977,21 @@ int main(int argc, char **argv) exit(EX_IOERR); } - /* Set up the supplementary group access list if possible - /etc/group still need to be accessible at this point. - If we get EPERM, this is already a restricted process, e.g. - using user namespaces on Linux. */ - die = 0; -#ifdef HAVE_SETGROUPS - setrv = setgroups(0, NULL); - if (setrv && errno != EPERM) { - syslog(LOG_ERR, "cannot clear group list"); - die = EX_OSERR; - } -#endif + /* Set up the supplementary group access list if possible */ + /* /etc/group still need to be accessible at this point */ #ifdef HAVE_INITGROUPS setrv = initgroups(user, pw->pw_gid); - if (!setrv) { - die = 0; - } else if (errno != EPERM) { + if (setrv) { syslog(LOG_ERR, "cannot set groups for user %s", user); - die = EX_OSERR; + exit(EX_OSERR); + } +#else +#ifdef HAVE_SETGROUPS + if (setgroups(0, NULL)) { + syslog(LOG_ERR, "cannot clear group list"); } #endif - if (die) - exit(die); +#endif /* Chroot and drop privileges */ if (secure) { @@ -1024,30 +1003,19 @@ int main(int argc, char **argv) chdir("/"); /* Cygwin chroot() bug workaround */ #endif } - -#ifdef HAVE_SETRESGID - setrv = setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid); -#elif defined(HAVE_SETREGID) +#ifdef HAVE_SETREGID setrv = setregid(pw->pw_gid, pw->pw_gid); #else setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid); #endif - if (setrv && errno == EPERM) { - setrv = 0; /* Assume already restricted by system policy */ - } -#ifdef HAVE_SETRESUID - setrv = setrv || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); -#elif defined(HAVE_SETREUID) +#ifdef HAVE_SETREUID setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid); #else /* Important: setuid() must come first */ setrv = setrv || setuid(pw->pw_uid) || (geteuid() != pw->pw_uid && seteuid(pw->pw_uid)); #endif - if (setrv && errno == EPERM) { - setrv = 0; /* Assume already restricted by system policy */ - } if (setrv) { syslog(LOG_ERR, "cannot drop privileges: %m"); @@ -1071,16 +1039,23 @@ int main(int argc, char **argv) tp = (struct tftphdr *)buf; tp_opcode = ntohs(tp->th_opcode); if (tp_opcode == RRQ || tp_opcode == WRQ) - tftp(tp, n); + tftp(tp, n); exit(0); } -static char *rewrite_access(const struct formats *, - char *, int, int, const char **); +static char *rewrite_access(char *, int, const char **); static int validate_access(char *, int, const struct formats *, const char **); static void tftp_sendfile(const struct formats *, struct tftphdr *, int); static void tftp_recvfile(const struct formats *, struct tftphdr *, int); +struct formats { + const char *f_mode; + char *(*f_rewrite) (char *, int, const char **); + int (*f_validate) (char *, int, const struct formats *, const char **); + void (*f_send) (const struct formats *, struct tftphdr *, int); + void (*f_recv) (const struct formats *, struct tftphdr *, int); + int f_convert; +}; static const struct formats formats[] = { { "netascii", rewrite_access, validate_access, tftp_sendfile, @@ -1137,9 +1112,9 @@ int tftp(struct tftphdr *tp, int size) nak(EBADOP, "Unknown mode"); exit(0); } - file = NULL; - if (!(filename = (*pf->f_rewrite) - (pf, origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) { + if (!(filename = + (*pf->f_rewrite) (origfilename, tp_opcode, + &errmsgptr))) { nak(EACCESS, errmsgptr); /* File denied by mapping rule */ exit(0); } @@ -1162,18 +1137,12 @@ int tftp(struct tftphdr *tp, int size) tmp_p, origfilename, filename); } - /* - * If "file" is already set, then a file was already validated - * and opened during remap processing. - */ - if (!file) { - ecode = - (*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr); - if (ecode) { - nak(ecode, errmsgptr); - exit(0); - } - } + ecode = + (*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr); + if (ecode) { + nak(ecode, errmsgptr); + exit(0); + } opt = ++cp; } else if (argn & 1) { val = ++cp; @@ -1260,7 +1229,7 @@ static int set_blksize2(uintmax_t *vp) static int set_rollover(uintmax_t *vp) { uintmax_t ro = *vp; - + if (ro > 65535) return 0; @@ -1359,7 +1328,7 @@ static void do_opt(const char *opt, const char *val, char **ap) nak(EOPTNEG, "Insufficient space for options"); exit(0); } - + memcpy(p, opt, optlen+1); p += optlen+1; memcpy(p, retbuf, retlen+1); @@ -1429,12 +1398,12 @@ static int rewrite_macros(char macro, char *output) /* * Modify the filename, if applicable. If it returns NULL, deny the access. */ -static char *rewrite_access(const struct formats *pf, char *filename, - int mode, int af, const char **msg) +static char *rewrite_access(char *filename, int mode, const char **msg) { if (rewrite_rules) { char *newname = - rewrite_string(pf, filename, rewrite_rules, mode, af, + rewrite_string(filename, rewrite_rules, + mode != RRQ ? 'P' : 'G', rewrite_macros, msg); filename = newname; } @@ -1442,17 +1411,15 @@ static char *rewrite_access(const struct formats *pf, char *filename, } #else -static char *rewrite_access(const struct formats *pf, char *filename, - int mode, int af, const char **msg) +static char *rewrite_access(char *filename, int mode, const char **msg) { - (void)pf; (void)mode; /* Avoid warning */ (void)msg; - (void)af; return filename; } #endif +static FILE *file; /* * Validate file access. Since we * have no uid or gid, for now require @@ -1677,21 +1644,17 @@ static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oac /* * Receive a file. */ -static void tftp_recvfile(const struct formats *pf, - struct tftphdr *oack, int oacklen) +static void tftp_recvfile(const struct formats *pf, struct tftphdr *oap, int oacklen) { struct tftphdr *dp; int n, size; /* These are "static" to avoid longjmp funnies */ - static struct tftphdr *oap; static struct tftphdr *ap; /* ack buffer */ static u_short block = 0; static int acksize; u_short dp_opcode, dp_block; unsigned long r_timeout; - oap = oack; - dp = w_init(); do { timeout = rexmtval; diff --git a/tftpd/tftpd.h b/tftpd/tftpd.h index 277e5d2..e1d8bf0 100644 --- a/tftpd/tftpd.h +++ b/tftpd/tftpd.h @@ -23,13 +23,4 @@ char *tfstrdup(const char *); extern int verbosity; -struct formats { - const char *f_mode; - char *(*f_rewrite) (const struct formats *, char *, int, int, const char **); - int (*f_validate) (char *, int, const struct formats *, const char **); - void (*f_send) (const struct formats *, struct tftphdr *, int); - void (*f_recv) (const struct formats *, struct tftphdr *, int); - int f_convert; -}; - #endif diff --git a/version b/version index d346e2a..a75b92f 100644 --- a/version +++ b/version @@ -1 +1 @@ -5.3 +5.1