mirror of
https://kernel.googlesource.com/pub/scm/network/tftp/tftp-hpa
synced 2025-04-28 19:09:53 +03:00
Compare commits
31 commits
tftp-hpa-5
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2c86ff58dc | ||
![]() |
33ec23c0dc | ||
![]() |
9a92dec1dc | ||
![]() |
ac7f98e4d8 | ||
![]() |
74c5d8a020 | ||
![]() |
cb619257ed | ||
![]() |
fefaa2cc5c | ||
![]() |
33051a296c | ||
![]() |
e52af4207a | ||
![]() |
5e8d5c24b2 | ||
![]() |
99112f0206 | ||
![]() |
416046e2ad | ||
![]() |
b9f2335e88 | ||
![]() |
351907e3f0 | ||
![]() |
6f96fcd1b6 | ||
![]() |
1dc6d55811 | ||
![]() |
15c4f369ee | ||
![]() |
aaaa76e8e7 | ||
![]() |
1f4b33a1f7 | ||
![]() |
9c0908a778 | ||
![]() |
e83d71d394 | ||
![]() |
b2b34cecc8 | ||
![]() |
7678ae7f14 | ||
![]() |
ff819b108a | ||
![]() |
3ee2b27809 | ||
![]() |
18ac1e26f7 | ||
![]() |
8ddf0d87d7 | ||
![]() |
2ac12abbc9 | ||
![]() |
18ee96a03f | ||
![]() |
c89a63a441 | ||
![]() |
128e6a3905 |
49 changed files with 1295 additions and 891 deletions
11
.editorconfig
Normal file
11
.editorconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
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
|
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
|||
/MCONFIG
|
||||
/aconfig.h
|
||||
/aconfig.h.in
|
||||
/config/MCONFIG
|
||||
/config/config.h
|
||||
/config/config.h.in
|
||||
/autoconf/aclocal.m4
|
||||
/autoconf/clean.sh
|
||||
/autoconf/helpers/
|
||||
/autom4te.cache
|
||||
/config.log
|
||||
/config.status
|
||||
|
@ -12,5 +15,7 @@
|
|||
*.8
|
||||
*.a
|
||||
*.o
|
||||
*.i
|
||||
*.s
|
||||
*~
|
||||
\#*
|
||||
|
|
34
Makefile
34
Makefile
|
@ -3,10 +3,10 @@
|
|||
|
||||
SUB = lib common tftp tftpd
|
||||
|
||||
%.build: MCONFIG aconfig.h version.h
|
||||
%.build: config/MCONFIG config/config.h version.h
|
||||
$(MAKE) -C $(patsubst %.build, %, $@)
|
||||
|
||||
%.install: MCONFIG aconfig.h version.h
|
||||
%.install: config/MCONFIG config/config.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: MCONFIG $(patsubst %, %.build, $(SUB))
|
||||
all: config/MCONFIG $(patsubst %, %.build, $(SUB))
|
||||
|
||||
tftp.build: lib.build common.build
|
||||
tftpd.build: lib.build common.build
|
||||
|
||||
install: MCONFIG $(patsubst %, %.install, $(SUB))
|
||||
install: config/MCONFIG $(patsubst %, %.install, $(SUB))
|
||||
|
||||
clean: localclean $(patsubst %, %.clean, $(SUB))
|
||||
|
||||
|
@ -30,46 +30,40 @@ localclean:
|
|||
distclean: localdistclean $(patsubst %, %.distclean, $(SUB))
|
||||
|
||||
localdistclean: localclean
|
||||
rm -f MCONFIG config.status config.log aconfig.h *~ \#*
|
||||
rm -f config/config/MCONFIG config.status config.log config/config.h *~ \#*
|
||||
rm -rf *.cache
|
||||
find . -type f \( -name \*.orig -o -name \*.rej \) | xargs rm -f
|
||||
|
||||
spotless: distclean
|
||||
rm -f configure aconfig.h.in tftp.spec
|
||||
rm -f configure config/config.h.in tftp.spec
|
||||
|
||||
autoconf: configure aconfig.h.in
|
||||
autoconf: configure config/config.h.in
|
||||
|
||||
config: MCONFIG aconfig.h
|
||||
config: config/MCONFIG config/config.h
|
||||
|
||||
release:
|
||||
$(MAKE) autoconf
|
||||
$(MAKE) tftp.spec
|
||||
$(MAKE) distclean
|
||||
|
||||
MCONFIG: configure MCONFIG.in aconfig.h.in
|
||||
config/MCONFIG: configure config/MCONFIG.in config/config.h.in
|
||||
if test -x config.status; then \
|
||||
./config.status --recheck && ./config.status ; \
|
||||
else \
|
||||
./configure ; \
|
||||
fi
|
||||
|
||||
aconfig.h: MCONFIG
|
||||
config/config.h: config/MCONFIG
|
||||
: Generated by side effect
|
||||
|
||||
# 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
|
||||
configure: configure.ac
|
||||
sh autogen.sh
|
||||
|
||||
configure: configure.in aclocal.m4
|
||||
rm -rf MCONFIG configure config.log aconfig.h *.cache
|
||||
autoconf
|
||||
config/config.h.in: configure
|
||||
: Generated by side effect
|
||||
|
||||
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 $@
|
||||
|
||||
|
|
280
aclocal.m4
vendored
280
aclocal.m4
vendored
|
@ -1,280 +0,0 @@
|
|||
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 <stdio.h>],
|
||||
[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 <setjmp.h>
|
||||
#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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
])])
|
||||
|
||||
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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
])])
|
||||
|
||||
|
||||
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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
])])
|
||||
|
||||
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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
])])
|
||||
|
||||
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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
])])
|
||||
|
||||
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 <tcpd.h>.])
|
||||
|
||||
AC_DEFUN(PA_HAVE_TCPWRAPPERS,
|
||||
[AC_CHECK_LIB([wrap], [main])
|
||||
AC_MSG_CHECKING([for tcpwrappers])
|
||||
AC_TRY_LINK(
|
||||
[
|
||||
#include <tcpd.h>
|
||||
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 <inttypes.h> macros which are
|
||||
dnl completely broken. Try to detect those.
|
||||
dnl --------------------------------------------------------------------------
|
||||
AH_TEMPLATE([INTTYPES_H_IS_SANE],
|
||||
[Define if the macros in <inttypes.h> 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 <inttypes.h>
|
||||
#include <stdio.h>
|
||||
],
|
||||
[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;
|
||||
])])
|
9
autoconf/m4/pa_add_cflags.m4
Normal file
9
autoconf/m4/pa_add_cflags.m4
Normal file
|
@ -0,0 +1,9 @@
|
|||
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])])
|
39
autoconf/m4/pa_add_flags.m4
Normal file
39
autoconf/m4/pa_add_flags.m4
Normal file
|
@ -0,0 +1,39 @@
|
|||
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])
|
||||
])
|
13
autoconf/m4/pa_add_headers.m4
Normal file
13
autoconf/m4/pa_add_headers.m4
Normal file
|
@ -0,0 +1,13 @@
|
|||
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(],[)])])
|
27
autoconf/m4/pa_add_langflags.m4
Normal file
27
autoconf/m4/pa_add_langflags.m4
Normal file
|
@ -0,0 +1,27 @@
|
|||
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])])
|
19
autoconf/m4/pa_arg_bool.m4
Normal file
19
autoconf/m4/pa_arg_bool.m4
Normal file
|
@ -0,0 +1,19 @@
|
|||
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])
|
||||
])
|
4
autoconf/m4/pa_arg_disabled.m4
Normal file
4
autoconf/m4/pa_arg_disabled.m4
Normal file
|
@ -0,0 +1,4 @@
|
|||
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])])
|
4
autoconf/m4/pa_arg_enabled.m4
Normal file
4
autoconf/m4/pa_arg_enabled.m4
Normal file
|
@ -0,0 +1,4 @@
|
|||
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])])
|
16
autoconf/m4/pa_build_ifelse.m4
Normal file
16
autoconf/m4/pa_build_ifelse.m4
Normal file
|
@ -0,0 +1,16 @@
|
|||
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])])
|
32
autoconf/m4/pa_c_typeof.m4
Normal file
32
autoconf/m4/pa_c_typeof.m4
Normal file
|
@ -0,0 +1,32 @@
|
|||
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'.])])])])
|
26
autoconf/m4/pa_check_bad_stdc_inline.m4
Normal file
26
autoconf/m4/pa_check_bad_stdc_inline.m4
Normal file
|
@ -0,0 +1,26 @@
|
|||
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])])])
|
17
autoconf/m4/pa_check_inttypes_h_sane.m4
Normal file
17
autoconf/m4/pa_check_inttypes_h_sane.m4
Normal file
|
@ -0,0 +1,17 @@
|
|||
dnl ------------------------------------------------------------------------
|
||||
dnl PA_CHECK_INTTYPES_H_SANE
|
||||
dnl
|
||||
dnl At least some versions of AIX 4 have <inttypes.h> 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 <inttypes.h> are usable])],
|
||||
[AC_MSG_RESULT([no (AIX, eh?)])])])])
|
41
autoconf/m4/pa_cross_compile.m4
Normal file
41
autoconf/m4/pa_cross_compile.m4
Normal file
|
@ -0,0 +1,41 @@
|
|||
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
|
||||
])
|
19
autoconf/m4/pa_flags_langlist.m4
Normal file
19
autoconf/m4/pa_flags_langlist.m4
Normal file
|
@ -0,0 +1,19 @@
|
|||
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)))])
|
26
autoconf/m4/pa_have_tcpwrappers.m4
Normal file
26
autoconf/m4/pa_have_tcpwrappers.m4
Normal file
|
@ -0,0 +1,26 @@
|
|||
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 <tcpd.h>
|
||||
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 <tcpd.h>.])
|
||||
AC_MSG_RESULT([yes])
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
])])
|
15
autoconf/m4/pa_lang_foreach.m4
Normal file
15
autoconf/m4/pa_lang_foreach.m4
Normal file
|
@ -0,0 +1,15 @@
|
|||
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])])
|
20
autoconf/m4/pa_lang_seen_list.m4
Normal file
20
autoconf/m4/pa_lang_seen_list.m4
Normal file
|
@ -0,0 +1,20 @@
|
|||
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])])
|
13
autoconf/m4/pa_option_debug.m4
Normal file
13
autoconf/m4/pa_option_debug.m4
Normal file
|
@ -0,0 +1,13 @@
|
|||
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])])
|
8
autoconf/m4/pa_option_profiling.m4
Normal file
8
autoconf/m4/pa_option_profiling.m4
Normal file
|
@ -0,0 +1,8 @@
|
|||
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])])])
|
13
autoconf/m4/pa_prog_cc.m4
Normal file
13
autoconf/m4/pa_prog_cc.m4
Normal file
|
@ -0,0 +1,13 @@
|
|||
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"])])
|
22
autoconf/m4/pa_search_libs_and_add.m4
Normal file
22
autoconf/m4/pa_search_libs_and_add.m4
Normal file
|
@ -0,0 +1,22 @@
|
|||
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;
|
||||
])])
|
25
autoconf/m4/pa_sigsetjmp.m4
Normal file
25
autoconf/m4/pa_sigsetjmp.m4
Normal file
|
@ -0,0 +1,25 @@
|
|||
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 <setjmp.h>
|
||||
|
||||
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])])])
|
11
autoconf/m4/pa_sym.m4
Normal file
11
autoconf/m4/pa_sym.m4
Normal file
|
@ -0,0 +1,11 @@
|
|||
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]])])
|
85
autogen.sh
85
autogen.sh
|
@ -1,2 +1,83 @@
|
|||
#!/bin/sh
|
||||
make autoconf
|
||||
#!/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
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
SRCROOT = ..
|
||||
VERSION = $(shell cat ../version)
|
||||
|
||||
-include ../MCONFIG
|
||||
-include ../config/MCONFIG
|
||||
include ../MRULES
|
||||
|
||||
OBJS = tftpsubs.$(O)
|
||||
OBJS = tftpsubs.$(O) signal.$(O)
|
||||
LIB = libcommon.a
|
||||
|
||||
all: $(LIB)
|
||||
|
|
19
common/signal.c
Normal file
19
common/signal.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
56
config.h
56
config.h
|
@ -1,6 +1,6 @@
|
|||
/* -*- c -*- ------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
|
||||
* Copyright 2001-2024 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* This program is free software available under the same license
|
||||
* as the "OpenBSD" operating system, distributed at
|
||||
|
@ -17,12 +17,23 @@
|
|||
#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 "aconfig.h" /* autogenerated configuration header */
|
||||
#include "config/config.h" /* autogenerated configuration header */
|
||||
|
||||
/* Standard includes */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
|
@ -32,21 +43,6 @@
|
|||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#else
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#ifndef STDC_HEADERS
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
@ -73,15 +69,8 @@
|
|||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GRP_H
|
||||
|
@ -92,9 +81,6 @@
|
|||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
|
@ -129,10 +115,10 @@
|
|||
|
||||
/* Some broken systems care about text versus binary, but
|
||||
real Unix systems don't... */
|
||||
#ifndef HAVE_O_TEXT_DEFINITION
|
||||
#if !HAVE_DECL_O_TEXT
|
||||
#define O_TEXT 0
|
||||
#endif
|
||||
#ifndef HAVE_O_BINARY_DEFINITION
|
||||
#if !HAVE_DECL_O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
|
@ -267,11 +253,9 @@ typedef int socklen_t;
|
|||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifndef HAVE_IPPORT_TFTP_DEFINITION
|
||||
#ifndef IPPORT_TFTP
|
||||
#if !HAVE_DECL_IPPORT_TFTP && !defined(IPPORT_TFTP)
|
||||
#define IPPORT_TFTP 69
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* arpa/{inet,tftp}.h, and possible missing pieces */
|
||||
|
||||
|
@ -293,9 +277,11 @@ typedef int socklen_t;
|
|||
void *xmalloc(size_t);
|
||||
char *xstrdup(const char *);
|
||||
|
||||
#ifndef HAVE_BSD_SIGNAL
|
||||
void (*bsd_signal(int, void (*)(int))) (int);
|
||||
#ifndef HAVE_SIGHANDLER_T
|
||||
typedef void (*sighandler_t)(int);
|
||||
#endif
|
||||
int tftp_signal(int, sighandler_t, int);
|
||||
|
||||
#ifndef HAVE_DUP2
|
||||
int dup2(int, int);
|
||||
#endif
|
||||
|
|
283
configure.ac
Normal file
283
configure.ac
Normal file
|
@ -0,0 +1,283 @@
|
|||
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
|
303
configure.in
303
configure.in
|
@ -1,303 +0,0 @@
|
|||
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 <sys/socket.h> isn't among the list of standard headers that autoconf checks,
|
||||
dnl but POSIX requires <sys/socket.h> for socklen_t to be defined.
|
||||
dnl
|
||||
AC_CHECK_TYPES(socklen_t,,,
|
||||
[
|
||||
#include <stdio.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <stddef.h>
|
||||
#else
|
||||
# if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#else
|
||||
# if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#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)
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
SRCROOT = ..
|
||||
|
||||
-include ../MCONFIG
|
||||
-include ../config/MCONFIG
|
||||
include ../MRULES
|
||||
|
||||
ifeq ($(LIBOBJS),)
|
||||
|
@ -25,5 +25,3 @@ libxtra.a: $(LIBOBJS)
|
|||
-rm -f libxtra.a
|
||||
$(AR) libxtra.a $(LIBOBJS)
|
||||
$(RANLIB) libxtra.a
|
||||
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
SRCROOT = ..
|
||||
VERSION = $(shell cat ../version)
|
||||
|
||||
-include ../MCONFIG
|
||||
-include ../config/MCONFIG
|
||||
include ../MRULES
|
||||
|
||||
OBJS = tftp.$(O) main.$(O)
|
||||
|
|
|
@ -31,10 +31,13 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RECVFILE_H
|
||||
#define RECVFILE_H
|
||||
#ifndef EXTERN_H
|
||||
#define EXTERN_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void tftp_recvfile(int, const char *, const char *);
|
||||
void tftp_sendfile(int, const char *, const char *);
|
||||
extern sigjmp_buf toplevel;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -188,7 +188,7 @@ char *xstrdup(const char *);
|
|||
|
||||
const char *program;
|
||||
|
||||
static inline void usage(int errcode)
|
||||
static void usage(int errcode)
|
||||
{
|
||||
fprintf(stderr,
|
||||
#ifdef HAVE_IPV6
|
||||
|
@ -305,7 +305,7 @@ int main(int argc, char *argv[])
|
|||
sp->s_proto = (char *)"udp";
|
||||
}
|
||||
|
||||
bsd_signal(SIGINT, intr);
|
||||
tftp_signal(SIGINT, intr, 0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,7 @@ extern int maxtimeout;
|
|||
#define PKTSIZE SEGSIZE+4
|
||||
char ackbuf[PKTSIZE];
|
||||
int timeout;
|
||||
sigjmp_buf toplevel;
|
||||
sigjmp_buf timeoutbuf;
|
||||
static sigjmp_buf timeoutbuf;
|
||||
|
||||
static void nak(int, const char *);
|
||||
static int makerequest(int, const char *, struct tftphdr *, const char *);
|
||||
|
@ -85,7 +84,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode)
|
|||
is_request = 1; /* First packet is the actual WRQ */
|
||||
amount = 0;
|
||||
|
||||
bsd_signal(SIGALRM, timer);
|
||||
tftp_signal(SIGALRM, timer, 0);
|
||||
do {
|
||||
if (is_request) {
|
||||
size = makerequest(WRQ, name, dp, mode) - 4;
|
||||
|
@ -191,7 +190,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode)
|
|||
firsttrip = 1;
|
||||
amount = 0;
|
||||
|
||||
bsd_signal(SIGALRM, timer);
|
||||
tftp_signal(SIGALRM, timer, 0);
|
||||
do {
|
||||
if (firsttrip) {
|
||||
size = makerequest(RRQ, name, ap, mode);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
SRCROOT = ..
|
||||
VERSION = $(shell cat ../version)
|
||||
|
||||
-include ../MCONFIG
|
||||
-include ../config/MCONFIG
|
||||
include ../MRULES
|
||||
|
||||
OBJS = tftpd.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)
|
||||
|
|
14
tftpd/misc.c
14
tftpd/misc.c
|
@ -19,19 +19,11 @@
|
|||
#include "tftpd.h"
|
||||
|
||||
/*
|
||||
* Set the signal handler and flags. Basically a user-friendly
|
||||
* wrapper around sigaction().
|
||||
* Set the signal handler and flags, and error out on failure.
|
||||
*/
|
||||
void set_signal(int signum, void (*handler) (int), int flags)
|
||||
void set_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;
|
||||
|
||||
if (sigaction(signum, &sa, NULL)) {
|
||||
if (tftp_signal(signum, handler, flags)) {
|
||||
syslog(LOG_ERR, "sigaction: %m");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
|
|
|
@ -26,10 +26,12 @@
|
|||
|
||||
#if defined(HAVE_RECVMSG) && defined(HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#include <sys/uio.h>
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
# include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef IP_PKTINFO
|
||||
# ifndef HAVE_STRUCT_IN_PKTINFO
|
||||
# ifndef HAVE_STRUCT_IN_PKTINFO_IPI_ADDR
|
||||
# ifdef __linux__
|
||||
/* Assume this version of glibc simply lacks the definition */
|
||||
struct in_pktinfo {
|
||||
|
@ -113,10 +115,31 @@ 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,
|
||||
struct sockaddr *from, socklen_t * fromlen,
|
||||
union sock_addr *myaddr)
|
||||
union sock_addr *from, union sock_addr *myaddr)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
|
@ -149,16 +172,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
|||
|
||||
/* Try to enable getting the return address */
|
||||
#ifdef IP_RECVDSTADDR
|
||||
if (from->sa_family == AF_INET)
|
||||
if (from->sa.sa_family == AF_INET)
|
||||
setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
|
||||
#endif
|
||||
#ifdef IP_PKTINFO
|
||||
if (from->sa_family == AF_INET)
|
||||
if (from->sa.sa_family == AF_INET)
|
||||
setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
|
||||
#endif
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (from->sa_family == AF_INET6)
|
||||
if (from->sa.sa_family == AF_INET6)
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
|
||||
#endif
|
||||
#endif
|
||||
|
@ -167,8 +190,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;
|
||||
msg.msg_namelen = *fromlen;
|
||||
msg.msg_name = &from->sa;
|
||||
msg.msg_namelen = sizeof(*from);
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
msg.msg_iov = &iov;
|
||||
|
@ -177,11 +200,9 @@ 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_family;
|
||||
myaddr->sa.sa_family = from->sa.sa_family;
|
||||
|
||||
if (msg.msg_controllen < sizeof(struct cmsghdr) ||
|
||||
(msg.msg_flags & MSG_CTRUNC))
|
||||
|
@ -190,7 +211,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_family == AF_INET) {
|
||||
if (from->sa.sa_family == AF_INET) {
|
||||
myaddr->sa.sa_family = AF_INET;
|
||||
#ifdef IP_RECVDSTADDR
|
||||
if (cmptr->cmsg_level == IPPROTO_IP &&
|
||||
|
@ -211,7 +232,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
|||
#endif
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (from->sa_family == AF_INET6) {
|
||||
else if (from->sa.sa_family == AF_INET6) {
|
||||
myaddr->sa.sa_family = AF_INET6;
|
||||
#ifdef IP6_RECVDSTADDR
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
|
||||
|
@ -222,17 +243,23 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
|||
|
||||
#ifdef HAVE_STRUCT_IN6_PKTINFO
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
|
||||
(cmptr->cmsg_type == IPV6_RECVPKTINFO ||
|
||||
(
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
cmptr->cmsg_type == IPV6_RECVPKTINFO ||
|
||||
#endif
|
||||
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...
|
||||
*/
|
||||
|
@ -245,6 +272,9 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
normalize_ip6_compat(from);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -252,16 +282,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
|||
|
||||
int
|
||||
myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t * fromlen,
|
||||
union sock_addr *myaddr)
|
||||
union sock_addr *from, 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_family;
|
||||
myaddr->sa.sa_family = from->sa.sa_family;
|
||||
sa_set_port(myaddr, htons(IPPORT_TFTP));
|
||||
|
||||
return recvfrom(s, buf, len, flags, from, fromlen);
|
||||
return recvfrom(s, buf, len, flags, &from->sa, &fromlen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,5 +19,4 @@
|
|||
|
||||
int
|
||||
myrecvfrom(int s, void *buf, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen,
|
||||
union sock_addr *myaddr);
|
||||
union sock_addr *from, union sock_addr *myaddr);
|
||||
|
|
304
tftpd/remap.c
304
tftpd/remap.c
|
@ -1,6 +1,6 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
|
||||
* Copyright 2001-2024 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 1024 /* Timeout after this many steps */
|
||||
#define DEADMAN_MAX_STEPS 4096 /* 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,12 +31,20 @@
|
|||
#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;
|
||||
int rule_flags;
|
||||
char rule_mode;
|
||||
unsigned int rule_flags;
|
||||
regex_t rx;
|
||||
const char *pattern;
|
||||
};
|
||||
|
@ -56,22 +64,30 @@ static int xform_tolower(int c)
|
|||
return tolower(c);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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 = pmatch[0].rm_so + endbytes;
|
||||
len = start + pmatch[0].rm_so;
|
||||
if (string) {
|
||||
memcpy(string, input, pmatch[0].rm_so);
|
||||
string += pmatch[0].rm_so;
|
||||
/* Copy the prefix before "start" as well! */
|
||||
memcpy(string, ibuf, start + pmatch[0].rm_so);
|
||||
string += start + pmatch[0].rm_so;
|
||||
}
|
||||
|
||||
/* Transform matched section */
|
||||
|
@ -97,7 +113,7 @@ static int genmatchstring(char *string, const char *pattern,
|
|||
mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
|
||||
len += mlen;
|
||||
if (string) {
|
||||
const char *p = input + pmatch[n].rm_so;
|
||||
const char *p = input + start + pmatch[n].rm_so;
|
||||
while (mlen--)
|
||||
*string++ = xform(*p++);
|
||||
}
|
||||
|
@ -140,7 +156,12 @@ static int 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';
|
||||
|
@ -149,6 +170,26 @@ static int 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,
|
||||
|
@ -206,11 +247,17 @@ static int parseline(char *line, struct rule *r, int lineno)
|
|||
r->rule_flags |= RULE_REWRITE;
|
||||
break;
|
||||
case 'g':
|
||||
r->rule_flags |= RULE_GLOBAL;
|
||||
if (r->rule_flags & RULE_GLOBAL)
|
||||
r->rule_flags |= RULE_SEDG;
|
||||
else
|
||||
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;
|
||||
|
@ -223,9 +270,17 @@ static int parseline(char *line, struct rule *r, int lineno)
|
|||
case '~':
|
||||
r->rule_flags |= RULE_INVERSE;
|
||||
break;
|
||||
case 'G':
|
||||
case 'P':
|
||||
r->rule_mode = *p;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR,
|
||||
|
@ -236,15 +291,21 @@ static int parseline(char *line, struct rule *r, int lineno)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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);
|
||||
}
|
||||
|
||||
/* Read and compile the regex */
|
||||
|
@ -325,17 +386,24 @@ void freerules(struct rule *r)
|
|||
}
|
||||
|
||||
/* Execute a rule set on a string; returns a malloc'd new string. */
|
||||
char *rewrite_string(const char *input, const struct rule *rules,
|
||||
char mode, match_pattern_callback macrosub,
|
||||
char *rewrite_string(const struct formats *pf,
|
||||
const char *input, const struct rule *rules,
|
||||
int mode, int af, match_pattern_callback macrosub,
|
||||
const char **errmsg)
|
||||
{
|
||||
char *current = tfstrdup(input);
|
||||
char *newstr;
|
||||
char *newstr, *newerstr;
|
||||
const char *accerr;
|
||||
const struct rule *ruleptr = rules;
|
||||
regmatch_t pmatch[10];
|
||||
int i;
|
||||
int len;
|
||||
int was_match = 0;
|
||||
int deadman = DEADMAN_MAX_STEPS;
|
||||
int deadman = deadman_max_steps;
|
||||
int matchsense;
|
||||
int pmatches;
|
||||
unsigned int bad_flags;
|
||||
int ggoffset;
|
||||
|
||||
/* Default error */
|
||||
*errmsg = "Remap table failure";
|
||||
|
@ -344,86 +412,121 @@ char *rewrite_string(const char *input, const struct rule *rules,
|
|||
syslog(LOG_INFO, "remap: input: %s", current);
|
||||
}
|
||||
|
||||
for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
|
||||
if (ruleptr->rule_mode && ruleptr->rule_mode != mode)
|
||||
continue; /* Rule not applicable, try next */
|
||||
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;
|
||||
|
||||
if (!deadman--) {
|
||||
syslog(LOG_WARNING,
|
||||
"remap: Breaking loop, input = %s, last = %s", input,
|
||||
current);
|
||||
free(current);
|
||||
return NULL; /* Did not terminate! */
|
||||
}
|
||||
for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
|
||||
if (ruleptr->rule_flags & bad_flags)
|
||||
continue; /* This rule is excluded by flags */
|
||||
|
||||
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;
|
||||
|
||||
do {
|
||||
if (regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
|
||||
(ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) {
|
||||
/* Match on this rule */
|
||||
was_match = 1;
|
||||
if (!deadman--)
|
||||
goto dead;
|
||||
|
||||
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 (regexec(&ruleptr->rx, current, pmatches, pmatch, 0)
|
||||
!= matchsense)
|
||||
break; /* No match, break out of do loop */
|
||||
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
/* Match on this rule */
|
||||
was_match = 1;
|
||||
|
||||
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: rewrite: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
if (ruleptr->rule_flags & RULE_ABORT) {
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: abort: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
} else {
|
||||
break; /* No match, terminate unconditionally */
|
||||
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 the rule is global, keep going until no match */
|
||||
} while (ruleptr->rule_flags & RULE_GLOBAL);
|
||||
|
||||
if (was_match) {
|
||||
was_match = 0;
|
||||
if (ruleptr->rule_flags & RULE_REWRITE) {
|
||||
len = genmatchstring(&newstr, ruleptr->pattern, current,
|
||||
pmatch, macrosub, 0, &ggoffset);
|
||||
|
||||
if (ruleptr->rule_flags & RULE_EXIT) {
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: exit",
|
||||
ruleptr->nrule);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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_HASFILE) &&
|
||||
pf->f_validate(newstr, mode, pf, &accerr)) {
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: ignored rewrite (%s): %s",
|
||||
ruleptr->nrule, accerr, newstr);
|
||||
}
|
||||
free(newstr);
|
||||
was_match = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
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 (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: not exiting (%s)\n",
|
||||
ruleptr->nrule, accerr);
|
||||
}
|
||||
was_match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If the rule is (old-style) global, keep going until no match */
|
||||
} while ((ruleptr->rule_flags & (RULE_GLOBAL|RULE_SEDG)) == RULE_GLOBAL);
|
||||
|
||||
if (!was_match)
|
||||
continue; /* Next rule */
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,4 +535,11 @@ char *rewrite_string(const char *input, const struct rule *rules,
|
|||
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! */
|
||||
}
|
||||
|
|
|
@ -35,8 +35,13 @@ struct rule *parserulefile(FILE *);
|
|||
void freerules(struct rule *);
|
||||
|
||||
/* Execute a rule set on a string; returns a malloc'd new string. */
|
||||
char *rewrite_string(const char *, const struct rule *, char,
|
||||
struct formats;
|
||||
char *rewrite_string(const struct formats *, const char *,
|
||||
const struct rule *, int, int,
|
||||
match_pattern_callback, const char **);
|
||||
|
||||
/* Remapping deadman counter */
|
||||
extern int deadman_max_steps;
|
||||
|
||||
#endif /* WITH_REGEX */
|
||||
#endif /* TFTPD_REMAP_H */
|
||||
|
|
|
@ -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 "14 September 2009" "tftp-hpa @@VERSION@@" "System Manager's Manual"
|
||||
.TH TFTPD 8 "7 June 2014" "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\-\-mapfile\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP
|
||||
\fB\-\-map-file\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,6 +163,10 @@ 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 .
|
||||
|
@ -238,7 +242,7 @@ option, but crash with an error if they actually get the option
|
|||
accepted by the server.
|
||||
.SH "FILENAME REMAPPING"
|
||||
The
|
||||
.B \-\-mapfile
|
||||
.B \-\-map-file
|
||||
option specifies a file which contains filename remapping rules. Each
|
||||
non-comment line (comments begin with hash marks,
|
||||
.BR # )
|
||||
|
@ -270,7 +274,18 @@ 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
|
||||
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
|
||||
.BR r .
|
||||
.TP
|
||||
.B i
|
||||
|
@ -281,6 +296,17 @@ 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.
|
||||
|
@ -295,16 +321,22 @@ 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 the
|
||||
The following escape sequences are recognized as part of a
|
||||
.IR "replacement pattern" :
|
||||
.TP
|
||||
\fB\\0\fP
|
||||
|
@ -318,12 +350,14 @@ subexpressions, \\( ... \\), of the
|
|||
pattern.
|
||||
.TP
|
||||
\fB\\i\fP
|
||||
The IP address of the requesting host, in dotted-quad notation
|
||||
(e.g. 192.0.2.169).
|
||||
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).
|
||||
.TP
|
||||
\fB\\x\fP
|
||||
The IP address of the requesting host, in hexadecimal notation
|
||||
(e.g. C00002A9).
|
||||
The IP address of the requesting host, in expanded hexadecimal
|
||||
notation (e.g. C00002A9 for IPv4, or 20010DB8000000000000000000000001
|
||||
for IPv6).
|
||||
.TP
|
||||
\fB\\\\\fP
|
||||
Literal backslash.
|
||||
|
@ -383,14 +417,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 whole names are prefixed by one of the given directories. If
|
||||
files whose 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 ( \-\-mapfile
|
||||
.RB ( \-\-map-file
|
||||
flag) support can be used to provide a limited amount of additional
|
||||
access control.
|
||||
.SH "CONFORMING TO"
|
||||
|
|
151
tftpd/tftpd.c
151
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 Intel Corporation; author: H. Peter Anvin
|
||||
* Copyright (c) 2011-2014 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 *__progname;
|
||||
const char *tftpd_progname;
|
||||
static int peer;
|
||||
static unsigned long timeout = TIMEOUT; /* Current timeout value */
|
||||
static unsigned long rexmtval = TIMEOUT; /* Basic timeout value */
|
||||
|
@ -93,7 +93,6 @@ 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;
|
||||
|
||||
|
@ -107,11 +106,12 @@ 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 */
|
||||
void timer(int sig)
|
||||
static void timer(int sig)
|
||||
{
|
||||
(void)sig; /* Suppress unused warning */
|
||||
timeout <<= 1;
|
||||
|
@ -163,14 +163,14 @@ void timer(int sig)
|
|||
}
|
||||
|
||||
#ifdef WITH_REGEX
|
||||
static struct rule *read_remap_rules(const char *file)
|
||||
static struct rule *read_remap_rules(const char *rulefile)
|
||||
{
|
||||
FILE *f;
|
||||
struct rule *rulep;
|
||||
|
||||
f = fopen(file, "rt");
|
||||
f = fopen(rulefile, "rt");
|
||||
if (!f) {
|
||||
syslog(LOG_ERR, "Cannot open map file: %s: %m", file);
|
||||
syslog(LOG_ERR, "Cannot open map file: %s: %m", rulefile);
|
||||
exit(EX_NOINPUT);
|
||||
}
|
||||
rulep = parserulefile(f);
|
||||
|
@ -185,7 +185,8 @@ static struct rule *read_remap_rules(const char *file)
|
|||
*/
|
||||
static int lock_file(int fd, int lock_write)
|
||||
{
|
||||
#if defined(HAVE_FCNTL) && defined(HAVE_F_SETLK_DEFINITION)
|
||||
(void)lock_write;
|
||||
#if defined(HAVE_FCNTL) && HAVE_DECL_F_SETLK
|
||||
struct flock fl;
|
||||
|
||||
fl.l_type = lock_write ? F_WRLCK : F_RDLCK;
|
||||
|
@ -193,7 +194,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_LOCK_SH_DEFINITION)
|
||||
#elif defined(HAVE_FLOCK) && HAVE_DECL_LOCK_SH && HAVE_DECL_LOCK_EX
|
||||
return flock(fd, lock_write ? LOCK_EX|LOCK_NB : LOCK_SH|LOCK_NB);
|
||||
#else
|
||||
return 0; /* Hope & pray... */
|
||||
|
@ -324,8 +325,9 @@ 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' },
|
||||
|
@ -346,6 +348,7 @@ 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 }
|
||||
};
|
||||
|
@ -375,6 +378,7 @@ 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;
|
||||
|
@ -387,9 +391,9 @@ int main(int argc, char **argv)
|
|||
/* basename() is way too much of a pain from a portability standpoint */
|
||||
|
||||
p = strrchr(argv[0], '/');
|
||||
__progname = (p && p[1]) ? p + 1 : argv[0];
|
||||
tftpd_progname = (p && p[1]) ? p + 1 : argv[0];
|
||||
|
||||
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
openlog(tftpd_progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
|
||||
srand(time(NULL) ^ getpid());
|
||||
|
||||
|
@ -493,6 +497,17 @@ 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++;
|
||||
|
@ -874,9 +889,7 @@ int main(int argc, char **argv)
|
|||
set_socket_nonblock(fd, 0);
|
||||
#endif
|
||||
|
||||
fromlen = sizeof(from);
|
||||
n = myrecvfrom(fd, buf, sizeof(buf), 0,
|
||||
(struct sockaddr *)&from, &fromlen, &myaddr);
|
||||
n = myrecvfrom(fd, buf, sizeof(buf), 0, &from, &myaddr);
|
||||
|
||||
if (n < 0) {
|
||||
if (E_WOULD_BLOCK(errno) || errno == EINTR) {
|
||||
|
@ -938,14 +951,14 @@ int main(int argc, char **argv)
|
|||
syslog daemon gets restarted by the time we get here. */
|
||||
if (secure && standalone) {
|
||||
closelog();
|
||||
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
openlog(tftpd_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, __progname,
|
||||
RQ_DAEMON, tftpd_progname,
|
||||
RQ_FILE, fd,
|
||||
RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0);
|
||||
sock_methods(&wrap_request);
|
||||
|
@ -977,21 +990,29 @@ 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 */
|
||||
/* 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
|
||||
#ifdef HAVE_INITGROUPS
|
||||
setrv = initgroups(user, pw->pw_gid);
|
||||
if (setrv) {
|
||||
if (!setrv) {
|
||||
die = 0;
|
||||
} else if (errno != EPERM) {
|
||||
syslog(LOG_ERR, "cannot set groups for user %s", user);
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_SETGROUPS
|
||||
if (setgroups(0, NULL)) {
|
||||
syslog(LOG_ERR, "cannot clear group list");
|
||||
die = EX_OSERR;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (die)
|
||||
exit(die);
|
||||
|
||||
/* Chroot and drop privileges */
|
||||
if (secure) {
|
||||
|
@ -1003,19 +1024,30 @@ int main(int argc, char **argv)
|
|||
chdir("/"); /* Cygwin chroot() bug workaround */
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_SETREGID
|
||||
|
||||
#ifdef HAVE_SETRESGID
|
||||
setrv = setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid);
|
||||
#elif defined(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_SETREUID
|
||||
#ifdef HAVE_SETRESUID
|
||||
setrv = setrv || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
|
||||
#elif defined(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");
|
||||
|
@ -1039,23 +1071,16 @@ 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(char *, int, const char **);
|
||||
static char *rewrite_access(const struct formats *,
|
||||
char *, int, 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,
|
||||
|
@ -1112,9 +1137,9 @@ int tftp(struct tftphdr *tp, int size)
|
|||
nak(EBADOP, "Unknown mode");
|
||||
exit(0);
|
||||
}
|
||||
if (!(filename =
|
||||
(*pf->f_rewrite) (origfilename, tp_opcode,
|
||||
&errmsgptr))) {
|
||||
file = NULL;
|
||||
if (!(filename = (*pf->f_rewrite)
|
||||
(pf, origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) {
|
||||
nak(EACCESS, errmsgptr); /* File denied by mapping rule */
|
||||
exit(0);
|
||||
}
|
||||
|
@ -1137,12 +1162,18 @@ int tftp(struct tftphdr *tp, int size)
|
|||
tmp_p, origfilename,
|
||||
filename);
|
||||
}
|
||||
ecode =
|
||||
(*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
|
||||
if (ecode) {
|
||||
nak(ecode, errmsgptr);
|
||||
exit(0);
|
||||
}
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
opt = ++cp;
|
||||
} else if (argn & 1) {
|
||||
val = ++cp;
|
||||
|
@ -1229,7 +1260,7 @@ static int set_blksize2(uintmax_t *vp)
|
|||
static int set_rollover(uintmax_t *vp)
|
||||
{
|
||||
uintmax_t ro = *vp;
|
||||
|
||||
|
||||
if (ro > 65535)
|
||||
return 0;
|
||||
|
||||
|
@ -1328,7 +1359,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);
|
||||
|
@ -1398,12 +1429,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(char *filename, int mode, const char **msg)
|
||||
static char *rewrite_access(const struct formats *pf, char *filename,
|
||||
int mode, int af, const char **msg)
|
||||
{
|
||||
if (rewrite_rules) {
|
||||
char *newname =
|
||||
rewrite_string(filename, rewrite_rules,
|
||||
mode != RRQ ? 'P' : 'G',
|
||||
rewrite_string(pf, filename, rewrite_rules, mode, af,
|
||||
rewrite_macros, msg);
|
||||
filename = newname;
|
||||
}
|
||||
|
@ -1411,15 +1442,17 @@ static char *rewrite_access(char *filename, int mode, const char **msg)
|
|||
}
|
||||
|
||||
#else
|
||||
static char *rewrite_access(char *filename, int mode, const char **msg)
|
||||
static char *rewrite_access(const struct formats *pf, char *filename,
|
||||
int mode, int af, 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
|
||||
|
@ -1644,17 +1677,21 @@ 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 *oap, int oacklen)
|
||||
static void tftp_recvfile(const struct formats *pf,
|
||||
struct tftphdr *oack, 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;
|
||||
|
|
|
@ -23,4 +23,13 @@ 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
|
||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
|||
5.2
|
||||
5.3
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue