ftp.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:35k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1985, 1989 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 "ftp_var.h"
- #define DONT_NEED_SIGBLOCK
- #define DONT_NEED_SIGPAUSE
- #define DONT_NEED_SIGUNBLOCK
- #define DONT_NEED_SIGPENDING
- #include "sigfix.h"
- #ifdef HAVE_SYS_IOCTL_H
- #include <sys/ioctl.h>
- #endif
- #include <netinet/ip.h>
- #include <arpa/ftp.h>
- #include <arpa/telnet.h>
- #ifdef HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #include <varargs.h>
- #ifdef FASCIST
- #include <syslog.h>
- #endif
- #ifdef HAVE_BSTRING_H
- #include <bstring.h>
- #endif
- #ifndef HAVE_BCOPY
- #define bcopy(b1,b2,len) memmove(b2, b1, (size_t)(len))
- #endif
- #ifndef HAVE_BZERO
- #define bzero(b,len) memset(b, 0, (size_t)(len))
- #endif
- #ifndef HAVE_BCMP
- #define bcmp(b1,b2,len) memcmp(b1, b2, (size_t)(len))
- #endif
- sig_t lostpeer();
- struct sockaddr_in hisctladdr;
- struct sockaddr_in data_addr;
- struct sockaddr_in myctladdr;
- int data = -1;
- int abrtflag = 0;
- int ptflag = 0;
- off_t restart_point = 0;
- unsigned long socks_bind_remoteAddr; /* Socks */
- extern int connected, errno;
- FILE *cin, *cout;
- FILE *dataconn();
- jmp_buf ptabort;
- int ptabflg;
- #ifndef HAVE_HERROR
- char *h_errlist[] = {
- "Error 0",
- "Unknown host", /* 1 HOST_NOT_FOUND */
- "Host name lookup failure", /* 2 TRY_AGAIN */
- "Unknown server error", /* 3 NO_RECOVERY */
- "No address associated with name", /* 4 NO_ADDRESS */
- };
- int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
- int h_errno;
- /* herror -- */
- /* print the error indicated by the h_errno value. */
- /* */
- void herror(const char *s) {
- if (s && *s) {
- fprintf(stderr, "%s: ", s);
- }
- if ((h_errno < 0) || (h_errno >= h_nerr)) {
- fprintf(stderr, "Unknown errorn");
- } else if (h_errno == 0) {
- #ifdef sun
- fprintf(stderr, "Host unknownn");
- #endif
- } else {
- fprintf(stderr, "%sn", h_errlist[h_errno]);
- }
- }
- #endif
- char *hookup(char *host, int port) {
- register struct hostent *hp = 0;
- static char hostnamebuf[80];
- int s, len, tos;
- bzero((char *)&hisctladdr, sizeof (hisctladdr));
- hisctladdr.sin_addr.s_addr = inet_addr(host);
- if (hisctladdr.sin_addr.s_addr != -1) {
- hisctladdr.sin_family = AF_INET;
- strncpy(hostnamebuf, host, sizeof(hostnamebuf));
- } else {
- if ((hp = gethostbyname(host)) == NULL) {
- fprintf(stderr, "ftp: %s: ", host);
- herror(NULL);
- code = -1;
- return NULL;
- }
- hisctladdr.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0], (caddr_t)&hisctladdr.sin_addr, hp->h_length);
- strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
- }
- hostname = hostnamebuf;
- if ((s = socket(hisctladdr.sin_family, SOCK_STREAM, 0)) < 0) {
- perror("ftp: socket");
- code = -1;
- return NULL;
- }
- hisctladdr.sin_port = port;
- while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
- if (hp && hp->h_addr_list[1]) {
- int oerrno = errno;
- fprintf(stderr, "ftp: connect to address %s: ", inet_ntoa(hisctladdr.sin_addr));
- errno = oerrno;
- perror(NULL);
- hp->h_addr_list++;
- bcopy(hp->h_addr_list[0], (caddr_t)&hisctladdr.sin_addr, hp->h_length);
- fprintf(stdout, "Trying %s...n", inet_ntoa(hisctladdr.sin_addr));
- close(s);
- if ((s = socket(hisctladdr.sin_family, SOCK_STREAM, 0)) < 0) {
- perror("ftp: socket");
- code = -1;
- return NULL;
- }
- continue;
- }
- perror("ftp: connect");
- code = -1;
- goto bad;
- }
- socks_bind_remoteAddr = hisctladdr.sin_addr.s_addr; /* Socks */
- len = sizeof (myctladdr);
- if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
- perror("ftp: getsockname");
- code = -1;
- goto bad;
- }
- #if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
- tos = IPTOS_LOWDELAY;
- if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
- perror("ftp: setsockopt TOS (ignored)");
- #endif
- cin = fdopen(s, "r");
- cout = fdopen(dup(s), "w"); /* when (if ever) do we need the dup ? */
- if (cin == NULL || cout == NULL) {
- fprintf(stderr, "ftp: fdopen failed.n");
- if (cin) fclose(cin);
- if (cout) 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) fclose(cin);
- if (cout) 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) {
- perror("ftp: setsockopt");
- }
- }
- #endif
- return (hostname);
- bad:
- close(s);
- return NULL;
- }
- void cmdabort() {
- extern jmp_buf ptabort;
- printf("n");
- fflush(stdout);
- abrtflag++;
- if (!ptflag) return;
- longjmp(ptabort,1);
- }
- /*VARARGS*/
- int command(va_alist) va_dcl {
- va_list ap;
- char *fmt;
- int r;
- sig_t oldintr;
- abrtflag = 0;
- if (debug) {
- printf("---> ");
- va_start(ap);
- fmt = va_arg(ap, char *);
- if (strncmp("PASS ", fmt, 5) == 0)
- printf("PASS XXXX");
- else
- vfprintf(stdout, fmt, ap);
- va_end(ap);
- printf("n");
- fflush(stdout);
- }
- if (cout == NULL) {
- perror ("No control connection for command");
- code = -1;
- return (0);
- }
- oldintr = (sig_t)Signal(SIGINT, cmdabort);
- va_start(ap);
- fmt = va_arg(ap, char *);
- vfprintf(cout, fmt, ap);
- va_end(ap);
- fprintf(cout, "rn");
- fflush(cout);
- cpend = 1;
- r = getreply(!strcmp(fmt, "QUIT"));
- if (abrtflag && oldintr != SIG_IGN) (*oldintr)(SIGINT);
- Signal(SIGINT, oldintr);
- return(r);
- }
- int login(char *host) {
- char tmp[80];
- char *user, *pass, *acct, *getlogin(), *getpass();
- int n, aflag = 0;
- user = pass = acct = 0;
- if (ruserpass(host, &user, &pass, &acct) < 0) {
- code = -1;
- return(0);
- }
- while (user == NULL) {
- char *myname = getlogin();
- if (myname == NULL) {
- struct passwd *pp = getpwuid(getuid());
- if (pp != NULL)
- myname = pp->pw_name;
- }
- if (myname)
- printf("Name (%s:%s): ", host, myname);
- else
- printf("Name (%s): ", host);
- fgets(tmp, sizeof(tmp) - 1, stdin);
- tmp[strlen(tmp) - 1] = ' ';
- if (*tmp == ' ')
- user = myname;
- else
- user = tmp;
- }
- n = command("USER %s", user);
- if (n == CONTINUE) {
- if (pass == NULL) {
- if (!strcmp(user, "anonymous") || !strcmp(user, "ftp")) {
- printf("Password: "); fflush(stdout);
- fgets(tmp, sizeof(tmp) - 1, stdin);
- tmp[strlen(tmp) - 1] = ' ';
- pass = tmp;
- } else
- pass = getpass("Password:");
- }
- n = command("PASS %s", pass);
- }
- if (n == CONTINUE) {
- aflag++;
- acct = getpass("Account:");
- n = command("ACCT %s", acct);
- }
- if (n != COMPLETE) {
- fprintf(stderr, "Login failed.n");
- return (0);
- }
- if (!aflag && acct != NULL)
- command("ACCT %s", acct);
- if (proxy)
- return(1);
- for (n = 0; n < macnum; ++n) {
- if (!strcmp("init", macros[n].mac_name)) {
- strcpy(line, "$init");
- makeargv();
- domacro(margc, margv);
- break;
- }
- }
- return (1);
- }
- char reply_string[BUFSIZ]; /* last line of previous reply */
- #include <ctype.h>
- int getreply(int expecteof) {
- register int c, n;
- register int dig;
- register char *cp;
- int originalcode = 0, continuation = 0;
- sig_t oldintr;
- int pflag = 0;
- char *pt = pasv;
- void cmdabort();
- oldintr = (sig_t)Signal(SIGINT, cmdabort);
- for (;;) {
- dig = n = code = 0;
- cp = reply_string;
- 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);
- fflush(cout);
- break;
- case DO:
- case DONT:
- c = getc(cin);
- fprintf(cout, "%c%c%c", IAC, WONT, c);
- fflush(cout);
- break;
- default:
- break;
- }
- continue;
- }
- dig++;
- if (c == EOF) {
- if (expecteof) {
- Signal(SIGINT,oldintr);
- code = 221;
- return (0);
- }
- lostpeer();
- if (verbose) {
- printf("421 Service not available, remote server has closed connectionn");
- 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);
- putchar(c);
- }
- if (dig < 4 && isdigit(c))
- code = code * 10 + (c - '0');
- if (!pflag && code == 227)
- pflag = 1;
- if (dig > 4 && pflag == 1 && isdigit(c))
- pflag = 2;
- if (pflag == 2) {
- if (c != 'r' && c != ')')
- *pt++ = c;
- else {
- *pt = ' ';
- pflag = 3;
- }
- }
- if (dig == 4 && c == '-') {
- if (continuation) code = 0;
- continuation++;
- }
- if (n == 0)
- n = c;
- if (cp < &reply_string[sizeof(reply_string) - 1])
- *cp++ = c;
- }
- if (verbose > 0 || (verbose > -1 && n == '5')) {
- putchar(c);
- fflush(stdout);
- }
- if (continuation && code != originalcode) {
- if (originalcode == 0) originalcode = code;
- continue;
- }
- *cp = ' ';
- if (n != '1')
- cpend = 0;
- Signal(SIGINT,oldintr);
- if (code == 421 || originalcode == 421)
- lostpeer();
- if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
- (*oldintr)(SIGINT);
- return (n - '0');
- }
- }
- int empty(fd_set *mask, int sec) {
- struct timeval t;
- t.tv_sec = (long) sec;
- t.tv_usec = 0;
- return(select(32, mask, NULL, NULL, &t));
- }
- jmp_buf sendabort;
- void abortsend() {
- mflag = 0;
- abrtflag = 0;
- printf("nsend abortednwaiting for remote to finish abortn");
- fflush(stdout);
- longjmp(sendabort, 1);
- }
- #define HASHBYTES 1024
- void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0) {
- tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
- tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
- if (tdiff->tv_usec < 0) tdiff->tv_sec--, tdiff->tv_usec += 1000000;
- }
- void ptransfer(char *direction, long bytes, struct timeval *t0, struct timeval *t1) {
- struct timeval td;
- float s, bs;
- if (verbose) {
- tvsub(&td, t1, t0);
- s = td.tv_sec + (td.tv_usec / 1000000.);
- #define nz(x) ((x) ? (x) : 1)
- bs = bytes / nz(s);
- printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)n",
- bytes, direction, s, bs / 1024.);
- }
- }
- void abort_remote(FILE *din) {
- char buf[BUFSIZ];
- int nfnd;
- fd_set mask;
- /*
- * 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)
- perror("abort");
- fprintf(cout,"%cABORrn", DM);
- 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) {
- perror("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 */
- getreply(0);
- }
- getreply(0);
- }
- void proxtrans(char *cmd, char *local, char *remote) {
- sig_t oldintr;
- int secndflag = 0, prox_type, nfnd;
- extern jmp_buf ptabort;
- char *cmd2;
- fd_set mask;
- void abortpt();
- 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 (command("PASV") != COMPLETE) {
- printf("proxy server does not support third party transfers.n");
- return;
- }
- pswitch(0);
- if (!connected) {
- printf("No primary connectionn");
- 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 = (sig_t)Signal(SIGINT, abortpt);
- if (command("%s %s", cmd, remote) != PRELIM) {
- Signal(SIGINT, oldintr);
- pswitch(1);
- return;
- }
- sleep(2);
- pswitch(1);
- secndflag++;
- if (command("%s %s", cmd2, local) != PRELIM)
- goto abort;
- ptflag++;
- getreply(0);
- pswitch(0);
- getreply(0);
- Signal(SIGINT, oldintr);
- pswitch(1);
- ptflag = 0;
- printf("local: %s remote: %sn", local, remote);
- return;
- abort:
- 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;
- 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;
- 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) perror("abort");
- if (ptabflg) code = -1;
- lostpeer();
- }
- getreply(0);
- getreply(0);
- }
- if (proxy) pswitch(0);
- pswitch(1);
- if (ptabflg) code = -1;
- Signal(SIGINT, oldintr);
- }
- /*
- * Need to start a listen on the data channel before we send the command,
- * otherwise the server's connect may fail.
- */
- int initconn() {
- register char *p, *a;
- int result, len, tmpno = 0;
- int on = 1;
- noport:
- data_addr = myctladdr;
- if (sendport)
- data_addr.sin_port = 0; /* let system pick one */
- if (data != -1)
- close(data);
- data = socket(AF_INET, SOCK_STREAM, 0);
- if (data < 0) {
- perror("ftp: socket");
- if (tmpno)
- sendport = 1;
- return (1);
- }
- if (!sendport)
- if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
- perror("ftp: setsockopt (reuse address)");
- goto bad;
- }
- if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) {
- perror("ftp: bind");
- goto bad;
- }
- if (options & SO_DEBUG &&
- setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
- perror("ftp: setsockopt (ignored)");
- len = sizeof (data_addr);
- if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
- perror("ftp: getsockname");
- goto bad;
- }
- if (listen(data, 1) < 0)
- perror("ftp: listen");
- if (sendport) {
- a = (char *)&data_addr.sin_addr;
- p = (char *)&data_addr.sin_port;
- #define UC(b) (((int)b)&0xff)
- 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]));
- if (result == ERROR && sendport == -1) {
- sendport = 0;
- tmpno = 1;
- goto noport;
- }
- return (result != COMPLETE);
- }
- if (tmpno)
- sendport = 1;
- #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
- on = IPTOS_THROUGHPUT;
- if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
- perror("ftp: setsockopt TOS (ignored)");
- #endif
- return (0);
- bad:
- close(data), data = -1;
- if (tmpno)
- sendport = 1;
- return (1);
- }
- void sendrequest(char *cmd, char *local, char *remote, int printnames) {
- struct stat st;
- struct timeval start, stop;
- register int c, d;
- FILE *fin, *dout = 0, *popen();
- int (*closefunc)(), pclose(), fclose();
- sig_t oldintr, oldintp;
- long bytes = 0, hashbytes = HASHBYTES;
- char *lmode, buf[BUFSIZ], *bufp;
- void abortsend();
- if (verbose && printnames) {
- if (local && *local != '-')
- printf("local: %s ", local);
- if (remote)
- printf("remote: %sn", remote);
- }
- if (proxy) {
- proxtrans(cmd, local, remote);
- return;
- }
- if (curtype != type)
- changetype(type, 0);
- closefunc = NULL;
- oldintr = NULL;
- oldintp = NULL;
- lmode = "w";
- if (setjmp(sendabort)) {
- while (cpend) {
- getreply(0);
- }
- if (data >= 0) {
- close(data);
- data = -1;
- }
- if (oldintr)
- Signal(SIGINT,oldintr);
- if (oldintp)
- Signal(SIGPIPE,oldintp);
- code = -1;
- return;
- }
- oldintr = (sig_t)Signal(SIGINT, abortsend);
- if (strcmp(local, "-") == 0)
- fin = stdin;
- else if (*local == '|') {
- oldintp = (sig_t)Signal(SIGPIPE,SIG_IGN);
- fin = popen(local + 1, "r");
- if (fin == NULL) {
- perror(local + 1);
- Signal(SIGINT, oldintr);
- Signal(SIGPIPE, oldintp);
- code = -1;
- return;
- }
- closefunc = pclose;
- } else {
- fin = fopen(local, "r");
- if (fin == NULL) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- closefunc = fclose;
- if (fstat(fileno(fin), &st) < 0 ||
- (st.st_mode&S_IFMT) != S_IFREG) {
- fprintf(stdout, "%s: not a plain file.n", local);
- Signal(SIGINT, oldintr);
- fclose(fin);
- code = -1;
- return;
- }
- }
- if (initconn()) {
- Signal(SIGINT, oldintr);
- if (oldintp)
- Signal(SIGPIPE, oldintp);
- code = -1;
- if (closefunc != NULL)
- (*closefunc)(fin);
- return;
- }
- if (setjmp(sendabort))
- goto abort;
- if (restart_point &&
- (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
- if (fseek(fin, (long) restart_point, 0) < 0) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- restart_point = 0;
- if (closefunc != NULL)
- (*closefunc)(fin);
- return;
- }
- if (command("REST %ld", (long) restart_point)
- != CONTINUE) {
- restart_point = 0;
- if (closefunc != NULL)
- (*closefunc)(fin);
- return;
- }
- restart_point = 0;
- lmode = "r+w";
- }
- if (remote) {
- if (command("%s %s", cmd, remote) != PRELIM) {
- Signal(SIGINT, oldintr);
- if (oldintp)
- Signal(SIGPIPE, oldintp);
- if (closefunc != NULL)
- (*closefunc)(fin);
- return;
- }
- } else
- if (command("%s", cmd) != PRELIM) {
- Signal(SIGINT, oldintr);
- if (oldintp)
- Signal(SIGPIPE, oldintp);
- if (closefunc != NULL)
- (*closefunc)(fin);
- return;
- }
- dout = dataconn(lmode);
- if (dout == NULL)
- goto abort;
- gettimeofday(&start, (struct timezone *)0);
- oldintp = (sig_t)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) {
- while (bytes >= hashbytes) {
- putchar('#');
- hashbytes += HASHBYTES;
- }
- fflush(stdout);
- }
- }
- if (hash && bytes > 0) {
- if (bytes < HASHBYTES)
- putchar('#');
- putchar('n');
- fflush(stdout);
- }
- if (c < 0)
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- if (d < 0) {
- if (errno != EPIPE)
- perror("netout");
- bytes = -1;
- }
- break;
- case TYPE_A:
- while ((c = getc(fin)) != EOF) {
- if (c == 'n') {
- while (hash && (bytes >= hashbytes)) {
- putchar('#');
- fflush(stdout);
- hashbytes += HASHBYTES;
- }
- if (ferror(dout))
- break;
- putc('r', dout);
- bytes++;
- }
- putc(c, dout);
- bytes++;
- /* if (c == 'r') { */
- /* (void) putc(' ', dout); /* this violates rfc */
- /* bytes++; */
- /* } */
- }
- if (hash) {
- if (bytes < hashbytes)
- putchar('#');
- putchar('n');
- fflush(stdout);
- }
- if (ferror(fin))
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- if (ferror(dout)) {
- if (errno != EPIPE)
- perror("netout");
- bytes = -1;
- }
- break;
- }
- gettimeofday(&stop, (struct timezone *)0);
- if (closefunc != NULL)
- (*closefunc)(fin);
- fclose(dout);
- getreply(0);
- Signal(SIGINT, oldintr);
- if (oldintp)
- Signal(SIGPIPE, oldintp);
- if (bytes > 0) {
- #ifdef FASCIST
- syslog(LOG_NOTICE, "Sent local file %s as %s -- %d bytes", local, remote, bytes);
- #endif
- ptransfer("sent", bytes, &start, &stop);
- }
- return;
- abort:
- gettimeofday(&stop, (struct timezone *)0);
- Signal(SIGINT, oldintr);
- if (oldintp)
- Signal(SIGPIPE, oldintp);
- if (!cpend) {
- code = -1;
- return;
- }
- if (data >= 0) {
- close(data);
- data = -1;
- }
- if (dout)
- fclose(dout);
- getreply(0);
- code = -1;
- if (closefunc != NULL && fin != NULL)
- (*closefunc)(fin);
- if (bytes > 0) {
- #ifdef FASCIST
- syslog(LOG_NOTICE, "Sent local file %s as %s -- %d bytes", local, remote, bytes);
- #endif
- ptransfer("sent", bytes, &start, &stop);
- }
- }
- jmp_buf recvabort;
- void
- abortrecv()
- {
- mflag = 0;
- abrtflag = 0;
- printf("nreceive abortednwaiting for remote to finish abortn");
- fflush(stdout);
- longjmp(recvabort, 1);
- }
- void recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) {
- FILE *fout, *din = 0, *popen();
- int (*closefunc)(), pclose(), fclose();
- sig_t oldintr, oldintp;
- int is_retr, tcrflag, bare_lfs = 0;
- char *gunique();
- static int bufsize;
- static char *buf;
- long bytes = 0, hashbytes = HASHBYTES;
- register int c, d;
- struct timeval start, stop;
- struct stat st;
- off_t lseek();
- void abortrecv();
- is_retr = strcmp(cmd, "RETR") == 0;
- if (is_retr && verbose && printnames) {
- if (local && *local != '-')
- printf("local: %s ", local);
- if (remote)
- printf("remote: %sn", 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) {
- getreply(0);
- }
- if (data >= 0) {
- close(data);
- data = -1;
- }
- if (oldintr)
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- oldintr = (sig_t)Signal(SIGINT, abortrecv);
- if (strcmp(local, "-") && *local != '|') {
- if (access(local, 2) < 0) {
- char *dir = rindex(local, '/');
- if (errno != ENOENT && errno != EACCES) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- if (dir != NULL)
- *dir = 0;
- d = access(dir ? local : ".", 2);
- if (dir != NULL)
- *dir = '/';
- if (d < 0) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- if (!runique && errno == EACCES &&
- chmod(local, 0600) < 0) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- Signal(SIGINT, oldintr);
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- if (runique && errno == EACCES &&
- (local = gunique(local)) == NULL) {
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- }
- else if (runique && (local = gunique(local)) == NULL) {
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- }
- if (!is_retr) {
- if (curtype != TYPE_A)
- changetype(TYPE_A, 0);
- } else if (curtype != type)
- changetype(type, 0);
- if (initconn()) {
- Signal(SIGINT, oldintr);
- code = -1;
- return;
- }
- if (setjmp(recvabort))
- goto abort;
- if (is_retr && restart_point &&
- command("REST %ld", (long) restart_point) != CONTINUE)
- return;
- if (remote) {
- if (command("%s %s", cmd, remote) != PRELIM) {
- Signal(SIGINT, oldintr);
- return;
- }
- } else {
- if (command("%s", cmd) != PRELIM) {
- Signal(SIGINT, oldintr);
- return;
- }
- }
- din = dataconn("r");
- if (din == NULL)
- goto abort;
- if (strcmp(local, "-") == 0)
- fout = stdout;
- else if (*local == '|') {
- oldintp = (sig_t)Signal(SIGPIPE, SIG_IGN);
- fout = popen(local + 1, "w");
- if (fout == NULL) {
- perror(local+1);
- goto abort;
- }
- closefunc = pclose;
- } else {
- fout = fopen(local, lmode);
- if (fout == NULL) {
- fprintf(stderr, "local: %s: %sn", local,
- strerror(errno));
- goto abort;
- }
- closefunc = fclose;
- }
- #ifndef SVR3
- if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
- #endif
- st.st_blksize = BUFSIZ;
- if (st.st_blksize > bufsize) {
- if (buf) free(buf);
- buf = malloc((unsigned)st.st_blksize);
- if (buf == NULL) {
- perror("malloc");
- bufsize = 0;
- goto abort;
- }
- bufsize = st.st_blksize;
- }
- gettimeofday(&start, (struct timezone *)0);
- switch (curtype) {
- case TYPE_I:
- case TYPE_L:
- #ifdef SEEK_SET
- #define FTP_SEEK_SET SEEK_SET
- #else
- #define FTP_SEEK_SET L_SET
- #endif
- #ifdef SEEK_CUR
- #define FTP_SEEK_CUR SEEK_CUR
- #else
- #define FTP_SEEK_CUR L_CUR
- #endif
- if (restart_point && lseek(fileno(fout), (long) restart_point, FTP_SEEK_SET) < 0) {
- fprintf(stderr, "local: %s: %sn", local, strerror(errno));
- 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) {
- while (bytes >= hashbytes) {
- putchar('#');
- hashbytes += HASHBYTES;
- }
- fflush(stdout);
- }
- }
- if (hash && bytes > 0) {
- if (bytes < HASHBYTES) putchar('#');
- putchar('n');
- fflush(stdout);
- }
- if (c < 0) {
- if (errno != EPIPE) perror("netin");
- bytes = -1;
- }
- if (d < c) {
- if (d < 0) fprintf(stderr, "local: %s: %sn", local, strerror(errno));
- else fprintf(stderr, "%s: short writen", local);
- }
- break;
- case TYPE_A:
- if (restart_point) {
- register int i, n, ch;
- if (fseek(fout, 0L, FTP_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 (fseek(fout, 0L, FTP_SEEK_CUR) < 0) {
- done:
- fprintf(stderr, "local: %s: %sn", local, strerror(errno));
- if (closefunc != NULL) (*closefunc)(fout);
- return;
- }
- }
- while ((c = getc(din)) != EOF) {
- if (c == 'n') bare_lfs++;
- while (c == 'r') {
- while (hash && (bytes >= hashbytes)) {
- putchar('#');
- fflush(stdout);
- hashbytes += HASHBYTES;
- }
- bytes++;
- if ((c = getc(din)) != 'n' || tcrflag) {
- if (ferror(fout)) goto break2;
- putc('r', fout);
- if (c == ' ') {
- bytes++;
- goto contin2;
- }
- if (c == EOF) goto contin2;
- }
- }
- putc(c, fout);
- bytes++;
- contin2: ;
- }
- break2:
- if (bare_lfs) {
- printf("WARNING! %d bare linefeeds received in ASCII moden", bare_lfs);
- printf("File may not have transferred correctly.n");
- }
- if (hash) {
- if (bytes < hashbytes) putchar('#');
- putchar('n');
- fflush(stdout);
- }
- if (ferror(din)) {
- if (errno != EPIPE) perror("netin");
- bytes = -1;
- }
- if (ferror(fout)) fprintf(stderr, "local: %s: %sn", local, strerror(errno));
- break;
- }
- if (closefunc != NULL) (*closefunc)(fout);
- Signal(SIGINT, oldintr);
- if (oldintp) Signal(SIGPIPE, oldintp);
- gettimeofday(&stop, (struct timezone *)0);
- fclose(din);
- getreply(0);
- if (bytes > 0 && is_retr) {
- #ifdef FASCIST
- syslog(LOG_NOTICE, "Received remote file %s as %s -- %d bytes", remote, local, bytes);
- #endif
- ptransfer("received", bytes, &start, &stop);
- }
- return;
- abort:
- /* abort using RFC959 recommended IP,SYNC sequence */
- gettimeofday(&stop, (struct timezone *)0);
- if (oldintp) Signal(SIGPIPE, oldintr);
- Signal(SIGINT, SIG_IGN);
- if (!cpend) {
- code = -1;
- Signal(SIGINT, oldintr);
- return;
- }
- abort_remote(din);
- code = -1;
- if (data >= 0) {
- close(data);
- data = -1;
- }
- if (closefunc != NULL && fout != NULL) (*closefunc)(fout);
- if (din) fclose(din);
- if (bytes > 0) {
- #ifdef FASCIST
- syslog(LOG_NOTICE, "Received remote file %s as %s -- %d bytes", remote, local, bytes);
- #endif
- ptransfer("received", bytes, &start, &stop);
- }
- Signal(SIGINT, oldintr);
- }
- FILE *
- dataconn(lmode)
- char *lmode;
- {
- struct sockaddr_in from;
- int s, fromlen = sizeof (from), tos;
- if ((s = accept(data, (struct sockaddr *) &from, &fromlen)) < 0) {
- perror("ftp: accept");
- close(data), data = -1;
- return (NULL);
- }
- close(data);
- data = s;
- #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
- tos = IPTOS_THROUGHPUT;
- if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
- perror("ftp: setsockopt TOS (ignored)");
- #endif
- return (fdopen(data, lmode));
- }
- void psabort() {
- extern int abrtflag;
- abrtflag++;
- }
- void pswitch(int flag) {
- extern int proxy, abrtflag;
- sig_t oldintr;
- static struct comvars {
- int connect;
- char name[MAXHOSTNAMELEN];
- struct sockaddr_in mctl;
- struct sockaddr_in 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 = (sig_t)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) {
- strncpy(ip->name, hostname, sizeof(ip->name) - 1);
- ip->name[strlen(ip->name)] = ' ';
- } else {
- ip->name[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;
- strncpy(ip->nti, ntin, 16);
- (ip->nti)[strlen(ip->nti)] = ' ';
- strcpy(ntin, op->nti);
- strncpy(ip->nto, ntout, 16);
- (ip->nto)[strlen(ip->nto)] = ' ';
- strcpy(ntout, op->nto);
- ip->mapflg = mapflag;
- mapflag = op->mapflg;
- strncpy(ip->mi, mapin, MAXPATHLEN - 1);
- (ip->mi)[strlen(ip->mi)] = ' ';
- strcpy(mapin, op->mi);
- strncpy(ip->mo, mapout, MAXPATHLEN - 1);
- (ip->mo)[strlen(ip->mo)] = ' ';
- strcpy(mapout, op->mo);
- Signal(SIGINT, oldintr);
- if (abrtflag) {
- abrtflag = 0;
- (*oldintr)(SIGINT);
- }
- }
- void abortpt() {
- printf("n");
- fflush(stdout);
- ptabflg++;
- mflag = 0;
- abrtflag = 0;
- longjmp(ptabort, 1);
- }
- void reset() {
- fd_set mask;
- int nfnd = 1;
- FD_ZERO(&mask);
- while (nfnd > 0) {
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,0)) < 0) {
- perror("reset");
- code = -1;
- lostpeer();
- } else if (nfnd) {
- getreply(0);
- }
- }
- }
- char *gunique(char *local) {
- static char new[MAXPATHLEN];
- char *cp = rindex(local, '/');
- int d, count=0;
- char ext = '1';
- if (cp) *cp = ' ';
- d = access(cp ? local : ".", 2);
- if (cp) *cp = '/';
- if (d < 0) {
- fprintf(stderr, "local: %s: %sn", local, strerror(errno));
- return((char *) 0);
- }
- strcpy(new, local);
- cp = new + strlen(new);
- *cp++ = '.';
- while (!d) {
- if (++count == 100) {
- printf("runique: can't find unique file name.n");
- return((char *) 0);
- }
- *cp++ = ext;
- *cp = ' ';
- if (ext == '9') ext = '0';
- else ext++;
- if ((d = access(new, 0)) < 0) break;
- if (ext != '0') cp--;
- else if (*(cp - 2) == '.') *(cp - 1) = '1';
- else {
- *(cp - 2) = *(cp - 2) + 1;
- cp--;
- }
- }
- return(new);
- }