diff --git a/aclocal.m4 b/aclocal.m4 index 15a4037..bf0e28f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -42,59 +42,38 @@ AH_TEMPLATE([HAVE_MSGHDR_MSG_CONTROL], [Define if struct msghdr has the msg_control field.]) AC_DEFUN(PA_MSGHDR_MSG_CONTROL, -[AC_MSG_CHECKING([for msg_control in struct msghdr]) - AC_TRY_COMPILE( -[ -#define _XPG4_2 /* Needed on Solaris */ + [AC_CHECK_MEMBER(struct msghdr.msg_control, + [AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL)], + [], + [ #include #include #include -], -[ - struct msghdr msg; - void *p = (void *) &msg.msg_control; -], -[ - AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL) - AC_MSG_RESULT([yes]) -], -[ - AC_MSG_RESULT([no]) -])]) + ])]) dnl ------------------------------------------------------------------------ dnl PA_STRUCT_IN_PKTINFO -dnl -dnl Look for definition of struct in_pktinfo. Some versions of glibc -dnl lack struct in_pktinfo; if so we need to include the definition -dnl ourselves -- but we only want to do that if absolutely necessary! +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_MSG_CHECKING([for definition of struct in_pktinfo]) - AC_TRY_COMPILE( -[ + [AC_CHECK_MEMBER(struct in_pktinfo.ipi_addr, + [AC_DEFINE(HAVE_STRUCT_IN_PKTINFO)], + [], + [ #include #include #include #include #include #include -], -[ - struct in_pktinfo pktinfo; - int foo = sizeof(struct in_pktinfo); - void *quux = (void *)(&pktinfo.ipi_addr); -], -[ - AC_DEFINE(HAVE_STRUCT_IN_PKTINFO) - AC_MSG_RESULT([yes]) -], -[ - AC_MSG_RESULT([no]) -])]) + ])]) dnl -------------------------------------------------------------------------- dnl PA_HAVE_TCPWRAPPERS @@ -179,6 +158,7 @@ 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> ], diff --git a/config.h b/config.h index c07b4b8..ef0d408 100644 --- a/config.h +++ b/config.h @@ -109,6 +109,15 @@ #define E_WOULD_BLOCK(x) ((x) == EWOULDBLOCK) #endif +/* Some broken systems care about text versus binary, but + real Unix systems don't... */ +#ifndef HAVE_O_TEXT_DEFINITION +#define O_TEXT 0 +#endif +#ifndef HAVE_O_BINARY_DEFINITION +#define O_BINARY 0 +#endif + /* If we don't have intmax_t, try creating it */ #ifndef HAVE_INTMAX_T diff --git a/configure.in b/configure.in index d55daed..eba4d25 100644 --- a/configure.in +++ b/configure.in @@ -110,6 +110,10 @@ AC_CHECK_FUNCS(strtoull) PA_MSGHDR_MSG_CONTROL PA_STRUCT_IN_PKTINFO +PA_HEADER_DEFINES(fcntl.h, int, O_NONBLOCK) +PA_HEADER_DEFINES(fcntl.h, int, O_BINARY) +PA_HEADER_DEFINES(fcntl.h, int, O_TEXT) + AH_TEMPLATE([HAVE_SIGSETJMP], [Define if we have sigsetjmp, siglongjmp and sigjmp_buf.]) PA_SIGSETJMP([AC_DEFINE(HAVE_SIGSETJMP)]) @@ -128,8 +132,6 @@ dnl common_libs="$LIBS" -AH_TEMPLATE([HAVE_IPPORT_TFTP_DEFINITION], -[Define if netinet/in.h defines IPPORT_TFTP.]) PA_HEADER_DEFINES(netinet/in.h, int, IPPORT_TFTP) PA_WITH_BOOL(tcpwrappers, 1, diff --git a/tftp/extern.h b/tftp/extern.h index 60ad0e9..401608e 100644 --- a/tftp/extern.h +++ b/tftp/extern.h @@ -41,7 +41,7 @@ #ifndef RECVFILE_H #define RECVFILE_H -void tftp_recvfile (int, char *, char *); -void tftp_sendfile (int, char *, char *); +void tftp_recvfile (int, const char *, const char *); +void tftp_sendfile (int, const char *, const char *); #endif diff --git a/tftp/main.c b/tftp/main.c index dfe9d22..7f383fa 100644 --- a/tftp/main.c +++ b/tftp/main.c @@ -66,13 +66,31 @@ static const char *rcsid UNUSED = #define TIMEOUT 5 /* secs between rexmt's */ #define LBUFLEN 200 /* size of input buffer */ +struct modes { + const char *m_name; + const char *m_mode; + int m_openflags; +}; + +static const struct modes modes[] = { + { "netascii", "netascii", O_TEXT }, + { "ascii", "netascii", O_TEXT }, + { "octet", "octet", O_BINARY }, + { "binary", "octet", O_BINARY }, + { "image", "octet", O_BINARY }, + { 0, 0, 0 } +}; +#define MODE_OCTET (&modes[2]) +#define MODE_NETASCII (&modes[0]) +#define MODE_DEFAULT MODE_NETASCII + struct sockaddr_in peeraddr; int f; u_short port; int trace; int verbose; int connected; -char mode[32]; +const struct modes *mode; #ifdef WITH_READLINE char *line = NULL; #else @@ -104,7 +122,7 @@ static void command (void); static void getusage (char *); static void makeargv (void); static void putusage (char *); -static void settftpmode (const char *); +static void settftpmode (const struct modes *); #define HELPINDENT (sizeof("connect")) @@ -213,7 +231,7 @@ main(int argc, char *argv[]) perror("tftp: bind"); exit(1); } - strcpy(mode, "netascii"); + mode = MODE_DEFAULT; bsd_signal(SIGINT, intr); if (pargc > 1) { if (sigsetjmp(toplevel,1) != 0) @@ -326,27 +344,14 @@ setpeer(int argc, char *argv[]) connected = 1; } -struct modes { - const char *m_name; - const char *m_mode; -} modes[] = { - { "ascii", "netascii" }, - { "netascii", "netascii" }, - { "binary", "octet" }, - { "image", "octet" }, - { "octet", "octet" }, -/* { "mail", "mail" }, */ - { 0, 0 } -}; - void modecmd(int argc, char *argv[]) { - struct modes *p; + const struct modes *p; const char *sep; if (argc < 2) { - printf("Using %s mode to transfer files.\n", mode); + printf("Using %s mode to transfer files.\n", mode->m_mode); return; } if (argc == 2) { @@ -354,7 +359,7 @@ modecmd(int argc, char *argv[]) if (strcmp(argv[1], p->m_name) == 0) break; if (p->m_name) { - settftpmode(p->m_mode); + settftpmode(p); return; } printf("%s: unknown mode\n", argv[1]); @@ -376,22 +381,22 @@ void setbinary(int argc, char *argv[]) { (void)argc; (void)argv; /* Quiet unused warning */ - settftpmode("octet"); + settftpmode(MODE_OCTET); } void setascii(int argc, char *argv[]) { (void)argc; (void)argv; /* Quiet unused warning */ - settftpmode("netascii"); + settftpmode(MODE_NETASCII); } static void -settftpmode(const char *newmode) +settftpmode(const struct modes *newmode) { - strcpy(mode, newmode); + mode = newmode; if (verbose) - printf("mode set to %s\n", mode); + printf("mode set to %s\n", mode->m_mode); } @@ -444,16 +449,16 @@ put(int argc, char *argv[]) } if (argc < 4) { cp = argc == 2 ? tail(targ) : argv[1]; - fd = open(cp, O_RDONLY); + fd = open(cp, O_RDONLY|mode->m_openflags); if (fd < 0) { fprintf(stderr, "tftp: "); perror(cp); return; } if (verbose) printf("putting %s to %s:%s [%s]\n", - cp, hostname, targ, mode); + cp, hostname, targ, mode->m_mode); peeraddr.sin_port = port; - tftp_sendfile(fd, targ, mode); + tftp_sendfile(fd, targ, mode->m_mode); return; } /* this assumes the target is a directory */ @@ -462,16 +467,16 @@ put(int argc, char *argv[]) *cp++ = '/'; for (n = 1; n < argc - 1; n++) { strcpy(cp, tail(argv[n])); - fd = open(argv[n], O_RDONLY); + fd = open(argv[n], O_RDONLY|mode->m_openflags); if (fd < 0) { fprintf(stderr, "tftp: "); perror(argv[n]); continue; } if (verbose) printf("putting %s to %s:%s [%s]\n", - argv[n], hostname, targ, mode); + argv[n], hostname, targ, mode->m_mode); peeraddr.sin_port = port; - tftp_sendfile(fd, targ, mode); + tftp_sendfile(fd, targ, mode->m_mode); } } @@ -532,29 +537,29 @@ get(int argc, char *argv[]) } if (argc < 4) { cp = argc == 3 ? argv[2] : tail(src); - fd = creat(cp, 0644); + fd = open(cp, O_WRONLY|O_CREAT|O_TRUNC|mode->m_openflags, 0666); if (fd < 0) { fprintf(stderr, "tftp: "); perror(cp); return; } if (verbose) printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); + hostname, src, cp, mode->m_mode); peeraddr.sin_port = port; - tftp_recvfile(fd, src, mode); + tftp_recvfile(fd, src, mode->m_mode); break; } cp = tail(src); /* new .. jdg */ - fd = creat(cp, 0644); + fd = open(cp, O_WRONLY|O_CREAT|O_TRUNC|mode->m_openflags, 0666); if (fd < 0) { fprintf(stderr, "tftp: "); perror(cp); continue; } if (verbose) printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); + hostname, src, cp, mode->m_mode); peeraddr.sin_port = port; - tftp_recvfile(fd, src, mode); + tftp_recvfile(fd, src, mode->m_mode); } } @@ -621,7 +626,7 @@ status(int argc, char *argv[]) printf("Connected to %s.\n", hostname); else printf("Not connected.\n"); - printf("Mode: %s Verbose: %s Tracing: %s\n", mode, + printf("Mode: %s Verbose: %s Tracing: %s\n", mode->m_mode, verbose ? "on" : "off", trace ? "on" : "off"); printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", rexmtval, maxtimeout); diff --git a/tftp/tftp.c b/tftp/tftp.c index c199f8e..b35473e 100644 --- a/tftp/tftp.c +++ b/tftp/tftp.c @@ -77,7 +77,7 @@ static void tpacket(const char *, struct tftphdr *, int); * Send the requested file. */ void -tftp_sendfile(int fd, char *name, char *mode) +tftp_sendfile(int fd, const char *name, const char *mode) { struct tftphdr *ap; /* data and ack packets */ struct tftphdr *dp; @@ -93,8 +93,8 @@ tftp_sendfile(int fd, char *name, char *mode) startclock(); /* start stat's clock */ dp = r_init(); /* reset fillbuf/read-ahead code */ ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "r"); convert = !strcmp(mode, "netascii"); + file = fdopen(fd, convert ? "rt" : "rb"); block = 0; is_request = 1; /* First packet is the actual WRQ */ amount = 0; @@ -185,7 +185,7 @@ abort: * Receive a file. */ void -tftp_recvfile(int fd, char *name, char *mode) +tftp_recvfile(int fd, const char *name, const char *mode) { struct tftphdr *ap; struct tftphdr *dp; @@ -201,8 +201,8 @@ tftp_recvfile(int fd, char *name, char *mode) startclock(); dp = w_init(); ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "w"); convert = !strcmp(mode, "netascii"); + file = fdopen(fd, convert ?"wt":"wb"); block = 1; firsttrip = 1; amount = 0; diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index 9d1f30f..99692fb 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -175,7 +175,7 @@ set_socket_nonblock(int fd, int flag) { int err; int flags; -#if defined(HAVE_FCNTL) && defined(O_NONBLOCK) +#if defined(HAVE_FCNTL) && defined(HAVE_O_NONBLOCK_DEFINITION) /* Posixly correct */ err = ((flags = fcntl(fd, F_GETFL, 0)) < 0) || (fcntl(fd, F_SETFL, flag ? flags|O_NONBLOCK : flags&~O_NONBLOCK) < 0); @@ -929,7 +929,7 @@ FILE *file; * Validate file access. Since we * have no uid or gid, for now require * file to exist and be publicly - * readable/writable. + * readable/writable, unless -p specified. * If we were invoked with arguments * from inetd then the file must also be * in one of the given directory prefixes. @@ -941,9 +941,10 @@ validate_access(char *filename, int mode, struct formats *pf) { struct stat stbuf; int i, len; - int fd, wmode; + int fd, wmode, rmode; char *cp; const char **dirp; + char stdio_mode[3]; tsize_ok = 0; @@ -974,9 +975,12 @@ validate_access(char *filename, int mode, struct formats *pf) */ wmode = O_WRONLY | (cancreate ? O_CREAT : 0) | - (unixperms ? O_TRUNC : 0); + (unixperms ? O_TRUNC : 0) | + (pf->f_convert ? O_TEXT : O_BINARY); + rmode = O_RDONLY | + (pf->f_convert ? O_TEXT : O_BINARY); - fd = open(filename, mode == RRQ ? O_RDONLY : wmode, 0666); + fd = open(filename, mode == RRQ ? rmode : wmode, 0666); if (fd < 0) { switch (errno) { case ENOENT: @@ -1015,7 +1019,11 @@ validate_access(char *filename, int mode, struct formats *pf) tsize_ok = 1; } - file = fdopen(fd, (mode == RRQ)? "r":"w"); + stdio_mode[0] = (mode == RRQ) ? 'r':'w'; + stdio_mode[1] = (pf->f_convert) ? 't':'b'; + stdio_mode[2] = '\0'; + + file = fdopen(fd, stdio_mode); if (file == NULL) exit(EX_OSERR); /* Internal error */