📄 ftp.c
字号:
/* 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))#endifsig_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_HERRORchar *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 error\n"); } else if (h_errno == 0) {#ifdef sun fprintf(stderr, "Host unknown\n");#endif } else { fprintf(stderr, "%s\n", h_errlist[h_errno]); }}#endifchar *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 = Signal(SIGINT, cmdabort); va_start(ap); fmt = va_arg(ap, char *); vfprintf(cout, fmt, ap); va_end(ap); fflush(cout); cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); Signal(SIGINT, oldintr); if (abrtflag) { kill(getpid(),SIGINT); } return(r);}int ftplogin(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] = '\0'; if (*tmp == '\0') user = myname; else user = tmp; } n = command("USER %s\r\n", 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] = '\0'; pass = tmp; } else pass = GETPASS("Password:"); } n = command("PASS %s\r\n", pass); } if (n == CONTINUE) { aflag++; acct = GETPASS("Account:"); n = command("ACCT %s\r\n", acct); } if (n != COMPLETE) { fprintf(stderr, "Login failed.\n"); return (0); } if (!aflag && acct != NULL) command("ACCT %s\r\n", 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 = 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 connection\n"); 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((unsigned char)c)) code = code * 10 + (c - '0'); if (!pflag && code == 227) pflag = 1; if (dig > 4 && pflag == 1 && isdigit((unsigned char)c)) pflag = 2; if (pflag == 2) { if (c != '\r' && c != ')') *pt++ = c; else { *pt = '\0'; 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 = '\0'; if (n != '1') cpend = 0; Signal(SIGINT,oldintr); if (code == 421 || originalcode == 421) lostpeer(); if (abrtflag && oldintr != cmdabort) { kill(getpid(),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 aborted\nwaiting for remote to finish abort\n"); fflush(stdout); longjmp(sendabort, 1);}#define HASHBYTES 1024void 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.); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -