diff options
Diffstat (limited to 'usr.bin/ftp/ftp.c')
-rw-r--r-- | usr.bin/ftp/ftp.c | 1965 |
1 files changed, 0 insertions, 1965 deletions
diff --git a/usr.bin/ftp/ftp.c b/usr.bin/ftp/ftp.c deleted file mode 100644 index fc4f0b2..0000000 --- a/usr.bin/ftp/ftp.c +++ /dev/null @@ -1,1965 +0,0 @@ -/* $NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $ */ - -/* - * Copyright (c) 1985, 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; -#else -__RCSID("$FreeBSD$"); -__RCSID_SOURCE("$NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $"); -#endif -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <arpa/inet.h> -#include <arpa/ftp.h> -#include <arpa/telnet.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <netdb.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#include "ftp_var.h" - -/* wrapper for KAME-special getnameinfo() */ -#ifndef NI_WITHSCOPEID -#define NI_WITHSCOPEID 0 -#endif - -int data = -1; -int abrtflag = 0; -jmp_buf ptabort; -int ptabflg; -int ptflag = 0; - -FILE *cin, *cout; - -union sockunion { - struct sockinet { - u_char si_len; - u_char si_family; - u_short si_port; - } su_si; - struct sockaddr_in su_sin; - struct sockaddr_in6 su_sin6; -}; -#define su_len su_si.si_len -#define su_family su_si.si_family -#define su_port su_si.si_port - -union sockunion myctladdr, hisctladdr, data_addr; - -char * -hookup(host0, port) - const char *host0; - char *port; -{ - int s, len, tos, error; - struct addrinfo hints, *res, *res0; - static char hostnamebuf[MAXHOSTNAMELEN]; - char *host; - - if (*host0 == '[' && strrchr(host0, ']') != NULL) { /*IPv6 addr in []*/ - strncpy(hostnamebuf, host0 + 1, strlen(host0) - 2); - hostnamebuf[strlen(host0) - 2] = '\0'; - } else { - strncpy(hostnamebuf, host0, strlen(host0)); - hostnamebuf[strlen(host0)] = '\0'; - } - host = hostnamebuf; - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - error = getaddrinfo(host, port, &hints, &res0); - if (error) { - warnx("%s: %s", host, gai_strerror(error)); - if (error == EAI_SYSTEM) - warnx("%s: %s", host, strerror(errno)); - code = -1; - return (0); - } - - res = res0; - if (res->ai_canonname) - (void) strncpy(hostnamebuf, res->ai_canonname, - sizeof(hostnamebuf)); - hostname = hostnamebuf; - while (1) { - /* - * make sure that ai_addr is NOT an IPv4 mapped address. - * IPv4 mapped address complicates too many things in FTP - * protocol handling, as FTP protocol is defined differently - * between IPv4 and IPv6. - */ - ai_unmapped(res); - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s < 0) { - res = res->ai_next; - if (res) - continue; - warn("socket"); - code = -1; - return (0); - } - if (dobind) { - struct addrinfo *bindres; - int binderr = -1; - - for (bindres = bindres0; - bindres != NULL; - bindres = bindres->ai_next) - if (bindres->ai_family == res->ai_family) - break; - if (bindres == NULL) - bindres = bindres0; - binderr = bind(s, bindres->ai_addr, - bindres->ai_addrlen); - if (binderr == -1) - { - res = res->ai_next; - if (res) { - (void)close(s); - continue; - } - warn("bind"); - code = -1; - goto bad; - } - } - if (connect(s, res->ai_addr, res->ai_addrlen) == 0) - break; - if (res->ai_next) { - char hname[INET6_ADDRSTRLEN]; - getnameinfo(res->ai_addr, res->ai_addrlen, - hname, sizeof(hname) - 1, NULL, 0, - NI_NUMERICHOST|NI_WITHSCOPEID); - warn("connect to address %s", hname); - res = res->ai_next; - getnameinfo(res->ai_addr, res->ai_addrlen, - hname, sizeof(hname) - 1, NULL, 0, - NI_NUMERICHOST|NI_WITHSCOPEID); - printf("Trying %s...\n", hname); - (void)close(s); - continue; - } - warn("connect"); - code = -1; - goto bad; - } - memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res0); - len = sizeof(myctladdr); - if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { - warn("getsockname"); - code = -1; - goto bad; - } -#ifdef IP_TOS - if (myctladdr.su_family == AF_INET) - { - tos = IPTOS_LOWDELAY; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); - } -#endif - cin = fdopen(s, "r"); - cout = fdopen(s, "w"); - if (cin == NULL || cout == NULL) { - warnx("fdopen failed."); - if (cin) - (void)fclose(cin); - if (cout) - (void)fclose(cout); - code = -1; - goto bad; - } - if (verbose) - printf("Connected to %s.\n", hostname); - if (getreply(0) > 2) { /* read startup message from server */ - if (cin) - (void)fclose(cin); - if (cout) - (void)fclose(cout); - code = -1; - goto bad; - } -#ifdef SO_OOBINLINE - { - int on = 1; - - if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) - < 0 && debug) { - warn("setsockopt"); - } - } -#endif /* SO_OOBINLINE */ - - return (hostname); -bad: - (void)close(s); - return ((char *)0); -} - -void -cmdabort(notused) - int notused; -{ - - alarmtimer(0); - putchar('\n'); - (void)fflush(stdout); - abrtflag++; - if (ptflag) - longjmp(ptabort, 1); -} - -/*VARARGS*/ -int -#ifdef __STDC__ -command(const char *fmt, ...) -#else -command(va_alist) - va_dcl -#endif -{ - va_list ap; - int r; - sig_t oldintr; -#ifndef __STDC__ - const char *fmt; -#endif - - abrtflag = 0; - if (debug) { - fputs("---> ", stdout); -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); - fmt = va_arg(ap, const char *); -#endif - if (strncmp("PASS ", fmt, 5) == 0) - fputs("PASS XXXX", stdout); - else if (strncmp("ACCT ", fmt, 5) == 0) - fputs("ACCT XXXX", stdout); - else - vprintf(fmt, ap); - va_end(ap); - putchar('\n'); - (void)fflush(stdout); - } - if (cout == NULL) { - warnx("No control connection for command."); - code = -1; - return (0); - } - oldintr = signal(SIGINT, cmdabort); -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); - fmt = va_arg(ap, char *); -#endif - vfprintf(cout, fmt, ap); - va_end(ap); - fputs("\r\n", cout); - (void)fflush(cout); - cpend = 1; - r = getreply(!strcmp(fmt, "QUIT")); - if (abrtflag && oldintr != SIG_IGN) - (*oldintr)(SIGINT); - (void)signal(SIGINT, oldintr); - return (r); -} - -char reply_string[BUFSIZ]; /* first line of previous reply */ - -int -getreply(expecteof) - int expecteof; -{ - char current_line[BUFSIZ]; /* last line of previous reply */ - int c, n, line; - int dig; - int originalcode = 0, continuation = 0; - sig_t oldintr; - int pflag = 0; - char *cp, *pt = pasv; - - oldintr = signal(SIGINT, cmdabort); - for (line = 0 ;; line++) { - dig = n = code = 0; - cp = current_line; - while ((c = getc(cin)) != '\n') { - if (c == IAC) { /* handle telnet commands */ - switch (c = getc(cin)) { - case WILL: - case WONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, DONT, c); - (void)fflush(cout); - break; - case DO: - case DONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, WONT, c); - (void)fflush(cout); - break; - default: - break; - } - continue; - } - dig++; - if (c == EOF) { - if (expecteof) { - (void)signal(SIGINT, oldintr); - code = 221; - return (0); - } - lostpeer(); - if (verbose) { - puts( -"421 Service not available, remote server has closed connection."); - (void)fflush(stdout); - } - code = 421; - return (4); - } - if (c != '\r' && (verbose > 0 || - (verbose > -1 && n == '5' && dig > 4))) { - if (proxflag && - (dig == 1 || (dig == 5 && verbose == 0))) - printf("%s:", hostname); - (void)putchar(c); - } - if (dig < 4 && isdigit((unsigned char)c)) - code = code * 10 + (c - '0'); - switch (pflag) { - case 0: - if (code == 227 || code == 228) { - /* result for PASV/LPSV */ - pflag = 1; - /* fall through */ - } else if (code == 229) { - /* result for EPSV */ - pflag = 100; - break; - } else - break; - case 1: - if (!(dig > 4 && isdigit((unsigned char)c))) - break; - pflag = 2; - /* fall through */ - case 2: - if (c != '\r' && c != ')' && - pt < &pasv[sizeof(pasv)-1]) - *pt++ = c; - else { - *pt = '\0'; - pflag = 3; - } - break; - case 100: - if (dig > 4 && c == '(') - pflag = 2; - break; - } - if (dig == 4 && c == '-') { - if (continuation) - code = 0; - continuation++; - } - if (n == 0) - n = c; - if (cp < ¤t_line[sizeof(current_line) - 1]) - *cp++ = c; - } - if (verbose > 0 || (verbose > -1 && n == '5')) { - (void)putchar(c); - (void)fflush (stdout); - } - if (line == 0) { - size_t len = cp - current_line; - - if (len > sizeof(reply_string)) - len = sizeof(reply_string); - - (void)strncpy(reply_string, current_line, len); - reply_string[len] = '\0'; - } - if (continuation && code != originalcode) { - if (originalcode == 0) - originalcode = code; - continue; - } - *cp = '\0'; - if (n != '1') - cpend = 0; - (void)signal(SIGINT, oldintr); - if (code == 421 || originalcode == 421) - lostpeer(); - if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) - (*oldintr)(SIGINT); - return (n - '0'); - } -} - -int -empty(mask, sec) - fd_set *mask; - int sec; -{ - struct timeval t; - - t.tv_sec = (long) sec; - t.tv_usec = 0; - return (select(32, mask, (fd_set *) 0, (fd_set *) 0, &t)); -} - -jmp_buf sendabort; - -void -abortsend(notused) - int notused; -{ - - alarmtimer(0); - mflag = 0; - abrtflag = 0; - puts("\nsend aborted\nwaiting for remote to finish abort."); - (void)fflush(stdout); - longjmp(sendabort, 1); -} - -void -sendrequest(cmd, local, remote, printnames) - const char *cmd, *local, *remote; - int printnames; -{ - struct stat st; - int c, d; - FILE *fin, *dout; - int (*closefunc) __P((FILE *)); - sig_t oldinti, oldintr, oldintp; - volatile off_t hashbytes; - char *lmode, buf[BUFSIZ], *bufp; - int oprogress; - -#ifdef __GNUC__ /* XXX: to shut up gcc warnings */ - (void)&fin; - (void)&dout; - (void)&closefunc; - (void)&oldinti; - (void)&oldintr; - (void)&oldintp; - (void)&lmode; -#endif - - hashbytes = mark; - direction = "sent"; - dout = NULL; - bytes = 0; - filesize = -1; - oprogress = progress; - if (verbose && printnames) { - if (local && *local != '-') - printf("local: %s ", local); - if (remote) - printf("remote: %s\n", remote); - } - if (proxy) { - proxtrans(cmd, local, remote); - return; - } - if (curtype != type) - changetype(type, 0); - closefunc = NULL; - oldintr = NULL; - oldintp = NULL; - oldinti = NULL; - lmode = "w"; - if (setjmp(sendabort)) { - while (cpend) { - (void)getreply(0); - } - if (data >= 0) { - (void)close(data); - data = -1; - } - if (oldintr) - (void)signal(SIGINT, oldintr); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - if (oldinti) - (void)signal(SIGINFO, oldinti); - code = -1; - goto cleanupsend; - } - oldintr = signal(SIGINT, abortsend); - oldinti = signal(SIGINFO, psummary); - if (strcmp(local, "-") == 0) { - fin = stdin; - progress = 0; - } else if (*local == '|') { - oldintp = signal(SIGPIPE, SIG_IGN); - fin = popen(local + 1, "r"); - if (fin == NULL) { - warn("%s", local + 1); - (void)signal(SIGINT, oldintr); - (void)signal(SIGPIPE, oldintp); - (void)signal(SIGINFO, oldinti); - code = -1; - goto cleanupsend; - } - progress = 0; - closefunc = pclose; - } else { - fin = fopen(local, "r"); - if (fin == NULL) { - warn("local: %s", local); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - goto cleanupsend; - } - closefunc = fclose; - if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) { - printf("%s: not a plain file.\n", local); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - fclose(fin); - code = -1; - goto cleanupsend; - } - filesize = st.st_size; - } - if (initconn()) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - code = -1; - if (closefunc != NULL) - (*closefunc)(fin); - goto cleanupsend; - } - if (setjmp(sendabort)) - goto abort; - - if (restart_point && - (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { - int rc; - - rc = -1; - switch (curtype) { - case TYPE_A: - rc = fseeko(fin, restart_point, SEEK_SET); - break; - case TYPE_I: - case TYPE_L: - rc = lseek(fileno(fin), restart_point, SEEK_SET); - break; - } - if (rc < 0) { - warn("local: %s", local); - if (closefunc != NULL) - (*closefunc)(fin); - goto cleanupsend; - } - if (command("REST %qd", (long long) restart_point) != - CONTINUE) { - if (closefunc != NULL) - (*closefunc)(fin); - goto cleanupsend; - } - lmode = "r+w"; - } - if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - if (closefunc != NULL) - (*closefunc)(fin); - goto cleanupsend; - } - } else - if (command("%s", cmd) != PRELIM) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - if (closefunc != NULL) - (*closefunc)(fin); - goto cleanupsend; - } - dout = dataconn(lmode); - if (dout == NULL) - goto abort; - progressmeter(-1); - oldintp = signal(SIGPIPE, SIG_IGN); - switch (curtype) { - - case TYPE_I: - case TYPE_L: - errno = d = 0; - while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) { - bytes += c; - for (bufp = buf; c > 0; c -= d, bufp += d) - if ((d = write(fileno(dout), bufp, c)) <= 0) - break; - if (hash && (!progress || filesize < 0) ) { - while (bytes >= hashbytes) { - (void)putchar('#'); - hashbytes += mark; - } - (void)fflush(stdout); - } - } - if (hash && (!progress || filesize < 0) && bytes > 0) { - if (bytes < mark) - (void)putchar('#'); - (void)putchar('\n'); - (void)fflush(stdout); - } - if (c < 0) - warn("local: %s", local); - if (d < 0) { - if (errno != EPIPE) - warn("netout"); - bytes = -1; - } - break; - - case TYPE_A: - while ((c = getc(fin)) != EOF) { - if (c == '\n') { - while (hash && (!progress || filesize < 0) && - (bytes >= hashbytes)) { - (void)putchar('#'); - (void)fflush(stdout); - hashbytes += mark; - } - if (ferror(dout)) - break; - (void)putc('\r', dout); - bytes++; - } - (void)putc(c, dout); - bytes++; -#if 0 /* this violates RFC */ - if (c == '\r') { - (void)putc('\0', dout); - bytes++; - } -#endif - } - if (hash && (!progress || filesize < 0)) { - if (bytes < hashbytes) - (void)putchar('#'); - (void)putchar('\n'); - (void)fflush(stdout); - } - if (ferror(fin)) - warn("local: %s", local); - if (ferror(dout)) { - if (errno != EPIPE) - warn("netout"); - bytes = -1; - } - break; - } - progressmeter(1); - if (closefunc != NULL) - (*closefunc)(fin); - (void)fclose(dout); - (void)getreply(0); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - if (bytes > 0) - ptransfer(0); - goto cleanupsend; -abort: - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - if (!cpend) { - code = -1; - return; - } - if (data >= 0) { - (void)close(data); - data = -1; - } - if (dout) - (void)fclose(dout); - (void)getreply(0); - code = -1; - if (closefunc != NULL && fin != NULL) - (*closefunc)(fin); - if (bytes > 0) - ptransfer(0); -cleanupsend: - progress = oprogress; - restart_point = 0; -} - -jmp_buf recvabort; - -void -abortrecv(notused) - int notused; -{ - - alarmtimer(0); - mflag = 0; - abrtflag = 0; - puts("\nreceive aborted\nwaiting for remote to finish abort."); - (void)fflush(stdout); - longjmp(recvabort, 1); -} - -void -recvrequest(cmd, local, remote, lmode, printnames, ignorespecial) - const char *cmd, *local, *remote, *lmode; - int printnames, ignorespecial; -{ - FILE *fout, *din; - int (*closefunc) __P((FILE *)); - sig_t oldinti, oldintr, oldintp; - int c, d; - volatile int is_retr, tcrflag, bare_lfs; - static size_t bufsize; - static char *buf; - volatile off_t hashbytes; - struct stat st; - time_t mtime; - struct timeval tval[2]; - int oprogress; - int opreserve; - -#ifdef __GNUC__ /* XXX: to shut up gcc warnings */ - (void)&local; - (void)&fout; - (void)&din; - (void)&closefunc; - (void)&oldinti; - (void)&oldintr; - (void)&oldintp; -#endif - - fout = NULL; - din = NULL; - oldinti = NULL; - hashbytes = mark; - direction = "received"; - bytes = 0; - bare_lfs = 0; - filesize = -1; - oprogress = progress; - opreserve = preserve; - is_retr = (strcmp(cmd, "RETR") == 0); - if (is_retr && verbose && printnames) { - if (local && (ignorespecial || *local != '-')) - printf("local: %s ", local); - if (remote) - printf("remote: %s\n", remote); - } - if (proxy && is_retr) { - proxtrans(cmd, local, remote); - return; - } - closefunc = NULL; - oldintr = NULL; - oldintp = NULL; - tcrflag = !crflag && is_retr; - if (setjmp(recvabort)) { - while (cpend) { - (void)getreply(0); - } - if (data >= 0) { - (void)close(data); - data = -1; - } - if (oldintr) - (void)signal(SIGINT, oldintr); - if (oldinti) - (void)signal(SIGINFO, oldinti); - progress = oprogress; - preserve = opreserve; - code = -1; - return; - } - oldintr = signal(SIGINT, abortrecv); - oldinti = signal(SIGINFO, psummary); - if (ignorespecial || (strcmp(local, "-") && *local != '|')) { - if (access(local, W_OK) < 0) { - char *dir = strrchr(local, '/'); - - if (errno != ENOENT && errno != EACCES) { - warn("local: %s", local); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - if (dir != NULL) - *dir = 0; - d = access(dir == local ? "/" : dir ? local : ".", W_OK); - if (dir != NULL) - *dir = '/'; - if (d < 0) { - warn("local: %s", local); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - if (!runique && errno == EACCES && - chmod(local, 0600) < 0) { - warn("local: %s", local); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - if (runique && errno == EACCES && - (local = gunique(local)) == NULL) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - } - else if (runique && (local = gunique(local)) == NULL) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - } - if (!is_retr) { - if (curtype != TYPE_A) - changetype(TYPE_A, 0); - } else { - if (curtype != type) - changetype(type, 0); - filesize = remotesize(remote, 0); - } - if (initconn()) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - code = -1; - return; - } - if (setjmp(recvabort)) - goto abort; - if (is_retr && restart_point && - command("REST %qd", (long long) restart_point) != CONTINUE) - return; - if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - return; - } - } else { - if (command("%s", cmd) != PRELIM) { - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - return; - } - } - din = dataconn("r"); - if (din == NULL) - goto abort; - if (!ignorespecial && strcmp(local, "-") == 0) { - fout = stdout; - progress = 0; - preserve = 0; - } else if (!ignorespecial && *local == '|') { - oldintp = signal(SIGPIPE, SIG_IGN); - fout = popen(local + 1, "w"); - if (fout == NULL) { - warn("%s", local+1); - goto abort; - } - progress = 0; - preserve = 0; - closefunc = pclose; - } else { - fout = fopen(local, lmode); - if (fout == NULL) { - warn("local: %s", local); - goto abort; - } - closefunc = fclose; - } - if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) - st.st_blksize = BUFSIZ; - if (st.st_blksize > bufsize) { - if (buf) - (void)free(buf); - buf = malloc((unsigned)st.st_blksize); - if (buf == NULL) { - warn("malloc"); - bufsize = 0; - goto abort; - } - bufsize = st.st_blksize; - } - if (!S_ISREG(st.st_mode)) { - progress = 0; - preserve = 0; - } - progressmeter(-1); - switch (curtype) { - - case TYPE_I: - case TYPE_L: - if (is_retr && restart_point && - lseek(fileno(fout), restart_point, SEEK_SET) < 0) { - warn("local: %s", local); - progress = oprogress; - preserve = opreserve; - if (closefunc != NULL) - (*closefunc)(fout); - return; - } - errno = d = 0; - while ((c = read(fileno(din), buf, bufsize)) > 0) { - if ((d = write(fileno(fout), buf, c)) != c) - break; - bytes += c; - if (hash && (!progress || filesize < 0)) { - while (bytes >= hashbytes) { - (void)putchar('#'); - hashbytes += mark; - } - (void)fflush(stdout); - } - } - if (hash && (!progress || filesize < 0) && bytes > 0) { - if (bytes < mark) - (void)putchar('#'); - (void)putchar('\n'); - (void)fflush(stdout); - } - if (c < 0) { - if (errno != EPIPE) - warn("netin"); - bytes = -1; - } - if (d < c) { - if (d < 0) - warn("local: %s", local); - else - warnx("%s: short write", local); - } - break; - - case TYPE_A: - if (is_retr && restart_point) { - int ch; - off_t i, n; - - if (fseeko(fout, (off_t)0, SEEK_SET) < 0) - goto done; - n = restart_point; - for (i = 0; i++ < n;) { - if ((ch = getc(fout)) == EOF) - goto done; - if (ch == '\n') - i++; - } - if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { -done: - warn("local: %s", local); - progress = oprogress; - preserve = opreserve; - if (closefunc != NULL) - (*closefunc)(fout); - return; - } - } - while ((c = getc(din)) != EOF) { - if (c == '\n') - bare_lfs++; - while (c == '\r') { - while (hash && (!progress || filesize < 0) && - (bytes >= hashbytes)) { - (void)putchar('#'); - (void)fflush(stdout); - hashbytes += mark; - } - bytes++; - if ((c = getc(din)) != '\n' || tcrflag) { - if (ferror(fout)) - goto break2; - (void)putc('\r', fout); - if (c == '\0') { - bytes++; - goto contin2; - } - if (c == EOF) - goto contin2; - } - } - (void)putc(c, fout); - bytes++; - contin2: ; - } -break2: - if (bare_lfs) { - printf( -"WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs); - puts("File may not have transferred correctly."); - } - if (hash && (!progress || filesize < 0)) { - if (bytes < hashbytes) - (void)putchar('#'); - (void)putchar('\n'); - (void)fflush(stdout); - } - if (ferror(din)) { - if (errno != EPIPE) - warn("netin"); - bytes = -1; - } - if (ferror(fout)) - warn("local: %s", local); - break; - } - progressmeter(1); - progress = oprogress; - preserve = opreserve; - if (closefunc != NULL) - (*closefunc)(fout); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - if (oldintp) - (void)signal(SIGPIPE, oldintp); - (void)fclose(din); - (void)getreply(0); - if (bytes >= 0 && is_retr) { - if (bytes > 0) - ptransfer(0); - if (preserve && (closefunc == fclose)) { - mtime = remotemodtime(remote, 0); - if (mtime != -1) { - (void)gettimeofday(&tval[0], - (struct timezone *)0); - tval[1].tv_sec = mtime; - tval[1].tv_usec = 0; - if (utimes(local, tval) == -1) { - printf( - "Can't change modification time on %s to %s", - local, asctime(localtime(&mtime))); - } - } - } - } - return; - -abort: - -/* abort using RFC959 recommended IP,SYNC sequence */ - - progress = oprogress; - preserve = opreserve; - if (oldintp) - (void)signal(SIGPIPE, oldintp); - (void)signal(SIGINT, SIG_IGN); - if (!cpend) { - code = -1; - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); - return; - } - - abort_remote(din); - code = -1; - if (data >= 0) { - (void)close(data); - data = -1; - } - if (closefunc != NULL && fout != NULL) - (*closefunc)(fout); - if (din) - (void)fclose(din); - if (bytes > 0) - ptransfer(0); - (void)signal(SIGINT, oldintr); - (void)signal(SIGINFO, oldinti); -} - -/* - * Need to start a listen on the data channel before we send the command, - * otherwise the server's connect may fail. - */ -int -initconn() -{ - char *p, *a; - int result, len, tmpno = 0; - int on = 1; - int error, ports; - u_int af; - u_int hal, h[16]; - u_int pal, prt[2]; - char *pasvcmd; - -#ifdef INET6 - if (myctladdr.su_family == AF_INET6 - && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) - || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { - warnx("use of scoped address can be troublesome"); - } -#endif - - if (passivemode) { -#ifdef __GNUC__ /* XXX: to shut up gcc warnings */ - (void)&pasvcmd; -#endif - data_addr = myctladdr; - data = socket(data_addr.su_family, SOCK_STREAM, 0); - if (data < 0) { - warn("socket"); - return (1); - } - if (dobind) { - struct addrinfo *bindres; - int binderr = -1; - - for (bindres = bindres0; - bindres != NULL; - bindres = bindres->ai_next) - if (bindres->ai_family == data_addr.su_family) - break; - if (bindres == NULL) - bindres = bindres0; - binderr = bind(data, bindres->ai_addr, - bindres->ai_addrlen); - if (binderr == -1) - { - warn("bind"); - goto bad; - } - } - if ((options & SO_DEBUG) && - setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)) < 0) - warn("setsockopt (ignored)"); - switch (data_addr.su_family) { - case AF_INET: - if (try_epsv) { - int overbose; - - overbose = verbose; - if (debug == 0) - verbose = -1; - result = command(pasvcmd = "EPSV"); - verbose = overbose; - if (code / 10 == 22 && code != 229) { - puts("wrong server: EPSV return code must be 229"); - result = COMPLETE + 1; - } - } else - result = COMPLETE + 1; - if (result != COMPLETE) { - try_epsv = 0; - result = command(pasvcmd = "PASV"); - } - break; -#ifdef INET6 - case AF_INET6: - result = command(pasvcmd = "EPSV"); - if (code / 10 == 22 && code != 229) { - puts("wrong server: EPSV return code must be 229"); - result = COMPLETE + 1; - } - if (result != COMPLETE) - result = command(pasvcmd = "LPSV"); - break; -#endif - default: - result = COMPLETE + 1; - } - if (result != COMPLETE) { - puts("Passive mode refused."); - goto bad; - } - -#define pack2(var, offset) \ - (((var[(offset) + 0] & 0xff) << 8) | ((var[(offset) + 1] & 0xff) << 0)) -#define pack4(var, offset) \ - (((var[(offset) + 0] & 0xff) << 24) | ((var[(offset) + 1] & 0xff) << 16) \ - | ((var[(offset) + 2] & 0xff) << 8) | ((var[(offset) + 3] & 0xff) << 0)) - /* - * What we've got at this point is a string of comma - * separated one-byte unsigned integer values. - * In PASV case, - * The first four are the an IP address. The fifth is - * the MSB of the port number, the sixth is the LSB. - * From that we'll prepare a sockaddr_in. - * In other case, the format is more complicated. - */ - if (strcmp(pasvcmd, "PASV") == 0) { - if (code / 10 == 22 && code != 227) { - puts("wrong server: return code must be 227"); - error = 1; - goto bad; - } - error = sscanf(pasv, "%d,%d,%d,%d,%d,%d", - &h[0], &h[1], &h[2], &h[3], - &prt[0], &prt[1]); - if (error == 6) { - error = 0; - data_addr.su_sin.sin_addr.s_addr = - htonl(pack4(h, 0)); - } else - error = 1; - } else if (strcmp(pasvcmd, "LPSV") == 0) { - if (code / 10 == 22 && code != 228) { - puts("wrong server: return code must be 228"); - error = 1; - goto bad; - } - switch (data_addr.su_family) { - case AF_INET: - error = sscanf(pasv, -"%d,%d,%d,%d,%d,%d,%d,%d,%d", - &af, &hal, - &h[0], &h[1], &h[2], &h[3], - &pal, &prt[0], &prt[1]); - if (error == 9 && af == 4 && hal == 4 && pal == 2) { - error = 0; - data_addr.su_sin.sin_addr.s_addr = - htonl(pack4(h, 0)); - } else - error = 1; - break; -#ifdef INET6 - case AF_INET6: - error = sscanf(pasv, -"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - &af, &hal, - &h[0], &h[1], &h[2], &h[3], - &h[4], &h[5], &h[6], &h[7], - &h[8], &h[9], &h[10], &h[11], - &h[12], &h[13], &h[14], &h[15], - &pal, &prt[0], &prt[1]); - if (error != 21 || af != 6 || hal != 16 || pal != 2) { - error = 1; - break; - } - - error = 0; - { - u_int32_t *p32; - p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr; - p32[0] = htonl(pack4(h, 0)); - p32[1] = htonl(pack4(h, 4)); - p32[2] = htonl(pack4(h, 8)); - p32[3] = htonl(pack4(h, 12)); - } - break; -#endif - default: - error = 1; - } - } else if (strcmp(pasvcmd, "EPSV") == 0) { - char delim[4]; - - prt[0] = 0; - if (code / 10 == 22 && code != 229) { - puts("wrong server: return code must be 229"); - error = 1; - goto bad; - } - error = sscanf(pasv, "%c%c%c%d%c", - &delim[0], &delim[1], &delim[2], - &prt[1], &delim[3]); - if (error != 5) { - error = 1; - goto epsv_done; - } - if (delim[0] != delim[1] || delim[0] != delim[2] - || delim[0] != delim[3]) { - error = 1; - goto epsv_done; - } - - data_addr = hisctladdr; - /* quickhack */ - prt[0] = (prt[1] & 0xff00) >> 8; - prt[1] &= 0xff; - error = 0; -epsv_done: - } else - error = 1; - - if (error) { - puts( -"Passive mode address scan failure. Shouldn't happen!"); - goto bad; - }; - - data_addr.su_port = htons(pack2(prt, 0)); - - if (connect(data, (struct sockaddr *)&data_addr, - data_addr.su_len) < 0) { - warn("connect"); - goto bad; - } -#ifdef IP_TOS - if (data_addr.su_family == AF_INET) - { - on = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, - sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); - } -#endif - return (0); - } - -noport: - data_addr = myctladdr; - if (sendport) - data_addr.su_port = 0; /* let system pick one */ - if (data != -1) - (void)close(data); - data = socket(data_addr.su_family, SOCK_STREAM, 0); - if (data < 0) { - warn("socket"); - if (tmpno) - sendport = 1; - return (1); - } - if (!sendport) - if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, - sizeof(on)) < 0) { - warn("setsockopt (reuse address)"); - goto bad; - } -#ifdef IP_PORTRANGE - if (data_addr.su_family == AF_INET) - { - - ports = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; - if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, (char *)&ports, - sizeof(ports)) < 0) - warn("setsockopt PORTRANGE (ignored)"); - } -#endif -#ifdef INET6 -#ifdef IPV6_PORTRANGE - if (data_addr.su_family == AF_INET6) { - ports = restricted_data_ports ? IPV6_PORTRANGE_HIGH - : IPV6_PORTRANGE_DEFAULT; - if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE, - (char *)&ports, sizeof(ports)) < 0) - warn("setsockopt PORTRANGE (ignored)"); - } -#endif -#endif - if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) { - warn("bind"); - goto bad; - } - if (options & SO_DEBUG && - setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)) < 0) - warn("setsockopt (ignored)"); - len = sizeof(data_addr); - if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { - warn("getsockname"); - goto bad; - } - if (listen(data, 1) < 0) - warn("listen"); - if (sendport) { - char hname[INET6_ADDRSTRLEN]; - int af; - struct sockaddr_in data_addr4; - union sockunion *daddr; - -#ifdef INET6 - if (data_addr.su_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&data_addr.su_sin6.sin6_addr)) { - memset(&data_addr4, 0, sizeof(data_addr4)); - data_addr4.sin_len = sizeof(struct sockaddr_in); - data_addr4.sin_family = AF_INET; - data_addr4.sin_port = data_addr.su_port; - memcpy((caddr_t)&data_addr4.sin_addr, - (caddr_t)&data_addr.su_sin6.sin6_addr.s6_addr[12], - sizeof(struct in_addr)); - daddr = (union sockunion *)&data_addr4; - } else -#endif - daddr = &data_addr; - - - -#define UC(b) (((int)b)&0xff) - - switch (daddr->su_family) { -#ifdef INET6 - case AF_INET6: -#endif - af = (daddr->su_family == AF_INET) ? 1 : 2; - if (getnameinfo((struct sockaddr *)daddr, - daddr->su_len, hname, - sizeof(hname) - 1, NULL, 0, - NI_NUMERICHOST)) { - result = ERROR; - } else { - result = command("EPRT |%d|%s|%d|", - af, hname, ntohs(daddr->su_port)); - } - break; - default: - result = COMPLETE + 1; - break; - } - if (result == COMPLETE) - goto skip_port; - - p = (char *)&daddr->su_port; - switch (daddr->su_family) { - case AF_INET: - a = (char *)&daddr->su_sin.sin_addr; - result = command("PORT %d,%d,%d,%d,%d,%d", - UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), - UC(p[0]), UC(p[1])); - break; -#ifdef INET6 - case AF_INET6: - a = (char *)&daddr->su_sin6.sin6_addr; - result = command( -"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - 6, 16, - UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), - UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), - UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), - UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), - 2, UC(p[0]), UC(p[1])); - break; -#endif - default: - result = COMPLETE + 1; /* xxx */ - } - skip_port: - - if (result == ERROR && sendport == -1) { - sendport = 0; - tmpno = 1; - goto noport; - } - return (result != COMPLETE); - } - if (tmpno) - sendport = 1; -#ifdef IP_TOS - if (data_addr.su_family == AF_INET) - { - on = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); - } -#endif - return (0); -bad: - (void)close(data), data = -1; - if (tmpno) - sendport = 1; - return (1); -} - -FILE * -dataconn(lmode) - const char *lmode; -{ - union sockunion from; - int s, fromlen, tos; - - fromlen = myctladdr.su_len; - - if (passivemode) - return (fdopen(data, lmode)); - - s = accept(data, (struct sockaddr *) &from, &fromlen); - if (s < 0) { - warn("accept"); - (void)close(data), data = -1; - return (NULL); - } - (void)close(data); - data = s; -#ifdef IP_TOS - if (data_addr.su_family == AF_INET) - { - tos = IPTOS_THROUGHPUT; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); - } -#endif - return (fdopen(data, lmode)); -} - -void -psummary(notused) - int notused; -{ - - if (bytes > 0) - ptransfer(1); -} - -void -psabort(notused) - int notused; -{ - - alarmtimer(0); - abrtflag++; -} - -void -pswitch(flag) - int flag; -{ - sig_t oldintr; - static struct comvars { - int connect; - char name[MAXHOSTNAMELEN]; - union sockunion mctl; - union sockunion hctl; - FILE *in; - FILE *out; - int tpe; - int curtpe; - int cpnd; - int sunqe; - int runqe; - int mcse; - int ntflg; - char nti[17]; - char nto[17]; - int mapflg; - char mi[MAXPATHLEN]; - char mo[MAXPATHLEN]; - } proxstruct, tmpstruct; - struct comvars *ip, *op; - - abrtflag = 0; - oldintr = signal(SIGINT, psabort); - if (flag) { - if (proxy) - return; - ip = &tmpstruct; - op = &proxstruct; - proxy++; - } else { - if (!proxy) - return; - ip = &proxstruct; - op = &tmpstruct; - proxy = 0; - } - ip->connect = connected; - connected = op->connect; - if (hostname) { - (void)strncpy(ip->name, hostname, sizeof(ip->name) - 1); - ip->name[sizeof(ip->name) - 1] = '\0'; - } else - ip->name[0] = '\0'; - hostname = op->name; - ip->hctl = hisctladdr; - hisctladdr = op->hctl; - ip->mctl = myctladdr; - myctladdr = op->mctl; - ip->in = cin; - cin = op->in; - ip->out = cout; - cout = op->out; - ip->tpe = type; - type = op->tpe; - ip->curtpe = curtype; - curtype = op->curtpe; - ip->cpnd = cpend; - cpend = op->cpnd; - ip->sunqe = sunique; - sunique = op->sunqe; - ip->runqe = runique; - runique = op->runqe; - ip->mcse = mcase; - mcase = op->mcse; - ip->ntflg = ntflag; - ntflag = op->ntflg; - (void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1); - (ip->nti)[sizeof(ip->nti) - 1] = '\0'; - (void)strcpy(ntin, op->nti); - (void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1); - (ip->nto)[sizeof(ip->nto) - 1] = '\0'; - (void)strcpy(ntout, op->nto); - ip->mapflg = mapflag; - mapflag = op->mapflg; - (void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1); - (ip->mi)[sizeof(ip->mi) - 1] = '\0'; - (void)strcpy(mapin, op->mi); - (void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1); - (ip->mo)[sizeof(ip->mo) - 1] = '\0'; - (void)strcpy(mapout, op->mo); - (void)signal(SIGINT, oldintr); - if (abrtflag) { - abrtflag = 0; - (*oldintr)(SIGINT); - } -} - -void -abortpt(notused) - int notused; -{ - - alarmtimer(0); - putchar('\n'); - (void)fflush(stdout); - ptabflg++; - mflag = 0; - abrtflag = 0; - longjmp(ptabort, 1); -} - -void -proxtrans(cmd, local, remote) - const char *cmd, *local, *remote; -{ - sig_t oldintr; - int prox_type, nfnd; - volatile int secndflag; - char *cmd2; - fd_set mask; - -#ifdef __GNUC__ /* XXX: to shut up gcc warnings */ - (void)&oldintr; - (void)&cmd2; -#endif - - oldintr = NULL; - secndflag = 0; - if (strcmp(cmd, "RETR")) - cmd2 = "RETR"; - else - cmd2 = runique ? "STOU" : "STOR"; - if ((prox_type = type) == 0) { - if (unix_server && unix_proxy) - prox_type = TYPE_I; - else - prox_type = TYPE_A; - } - if (curtype != prox_type) - changetype(prox_type, 1); - if (try_epsv && command("EPSV") != COMPLETE) - try_epsv = 0; - if (!try_epsv && command("PASV") != COMPLETE) { - puts("proxy server does not support third party transfers."); - return; - } - pswitch(0); - if (!connected) { - puts("No primary connection."); - pswitch(1); - code = -1; - return; - } - if (curtype != prox_type) - changetype(prox_type, 1); - if (command("PORT %s", pasv) != COMPLETE) { - pswitch(1); - return; - } - if (setjmp(ptabort)) - goto abort; - oldintr = signal(SIGINT, abortpt); - if (command("%s %s", cmd, remote) != PRELIM) { - (void)signal(SIGINT, oldintr); - pswitch(1); - return; - } - sleep(2); - pswitch(1); - secndflag++; - if (command("%s %s", cmd2, local) != PRELIM) - goto abort; - ptflag++; - (void)getreply(0); - pswitch(0); - (void)getreply(0); - (void)signal(SIGINT, oldintr); - pswitch(1); - ptflag = 0; - printf("local: %s remote: %s\n", local, remote); - return; -abort: - (void)signal(SIGINT, SIG_IGN); - ptflag = 0; - if (strcmp(cmd, "RETR") && !proxy) - pswitch(1); - else if (!strcmp(cmd, "RETR") && proxy) - pswitch(0); - if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ - if (command("%s %s", cmd2, local) != PRELIM) { - pswitch(0); - if (cpend) - abort_remote((FILE *) NULL); - } - pswitch(1); - if (ptabflg) - code = -1; - (void)signal(SIGINT, oldintr); - return; - } - if (cpend) - abort_remote((FILE *) NULL); - pswitch(!proxy); - if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ - if (command("%s %s", cmd2, local) != PRELIM) { - pswitch(0); - if (cpend) - abort_remote((FILE *) NULL); - pswitch(1); - if (ptabflg) - code = -1; - (void)signal(SIGINT, oldintr); - return; - } - } - if (cpend) - abort_remote((FILE *) NULL); - pswitch(!proxy); - if (cpend) { - FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask, 10)) <= 0) { - if (nfnd < 0) { - warn("abort"); - } - if (ptabflg) - code = -1; - lostpeer(); - } - (void)getreply(0); - (void)getreply(0); - } - if (proxy) - pswitch(0); - pswitch(1); - if (ptabflg) - code = -1; - (void)signal(SIGINT, oldintr); -} - -void -reset(argc, argv) - int argc; - char *argv[]; -{ - fd_set mask; - int nfnd = 1; - - FD_ZERO(&mask); - while (nfnd > 0) { - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask, 0)) < 0) { - warn("reset"); - code = -1; - lostpeer(); - } - else if (nfnd) { - (void)getreply(0); - } - } -} - -char * -gunique(local) - const char *local; -{ - static char new[MAXPATHLEN]; - char *cp = strrchr(local, '/'); - int d, count=0; - char ext = '1'; - - if (cp) - *cp = '\0'; - d = access(cp == local ? "/" : cp ? local : ".", W_OK); - if (cp) - *cp = '/'; - if (d < 0) { - warn("local: %s", local); - return ((char *) 0); - } - (void)strcpy(new, local); - cp = new + strlen(new); - *cp++ = '.'; - while (!d) { - if (++count == 100) { - puts("runique: can't find unique file name."); - return ((char *) 0); - } - *cp++ = ext; - *cp = '\0'; - if (ext == '9') - ext = '0'; - else - ext++; - if ((d = access(new, F_OK)) < 0) - break; - if (ext != '0') - cp--; - else if (*(cp - 2) == '.') - *(cp - 1) = '1'; - else { - *(cp - 2) = *(cp - 2) + 1; - cp--; - } - } - return (new); -} - -void -abort_remote(din) - FILE *din; -{ - char buf[BUFSIZ]; - int nfnd; - fd_set mask; - - if (cout == NULL) { - warnx("Lost control connection for abort."); - if (ptabflg) - code = -1; - lostpeer(); - return; - } - /* - * send IAC in urgent mode instead of DM because 4.3BSD places oob mark - * after urgent byte rather than before as is protocol now - */ - sprintf(buf, "%c%c%c", IAC, IP, IAC); - if (send(fileno(cout), buf, 3, MSG_OOB) != 3) - warn("abort"); - fprintf(cout, "%cABOR\r\n", DM); - (void)fflush(cout); - FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - if (din) { - FD_SET(fileno(din), &mask); - } - if ((nfnd = empty(&mask, 10)) <= 0) { - if (nfnd < 0) { - warn("abort"); - } - if (ptabflg) - code = -1; - lostpeer(); - } - if (din && FD_ISSET(fileno(din), &mask)) { - while (read(fileno(din), buf, BUFSIZ) > 0) - /* LOOP */; - } - if (getreply(0) == ERROR && code == 552) { - /* 552 needed for nic style abort */ - (void)getreply(0); - } - (void)getreply(0); -} - -void -ai_unmapped(ai) - struct addrinfo *ai; -{ - struct sockaddr_in6 *sin6; - struct sockaddr_in sin; - - if (ai->ai_family != AF_INET6) - return; - if (ai->ai_addrlen != sizeof(struct sockaddr_in6) || - sizeof(sin) > ai->ai_addrlen) - return; - sin6 = (struct sockaddr_in6 *)ai->ai_addr; - if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - return; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(struct sockaddr_in); - memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], - sizeof(sin.sin_addr)); - sin.sin_port = sin6->sin6_port; - - ai->ai_family = AF_INET; - memcpy(ai->ai_addr, &sin, sin.sin_len); - ai->ai_addrlen = sin.sin_len; -} |