📄 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. */#ifndef lintstatic char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91";#endif /* not lint */#if defined(SOCKS)#define connect Rconnect#define getsockname Rgetsockname#define listen Rlisten#define accept Raccept#define rcmd Rrcmd# if defined(SHORTENED_RBIND)#define bind Rbind# else /* SHORTENED_RBIND not defined *//* * Be sure to put in socks_bind_remoteAddr (32-bit integer) the IP * address (in network byte order) of the host it is aiming for, * which is typically the destination host of the previous connect(). */#define bind(a,b,c) Rbind(a,b,c,socks_bind_remoteAddr)# endif /* # if defined(SHORTENED_RBIND) */#endif /* #if defined(SOCKS) */#include <sys/param.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/file.h>#include <netinet/in.h>#ifndef LINUX#include <netinet/in_systm.h>#endif#include <netinet/ip.h>#include <arpa/ftp.h>#include <arpa/telnet.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <netdb.h>#include <fcntl.h>#include <pwd.h>#include <varargs.h>#ifdef FASCIST#include <syslog.h>#endif#include "ftp_var.h"#if defined(AIX) || defined(DGUX)#undef IP_TOS#endif#ifdef SOLARIS/* for bcopy(), bzero() and bcmp() */#include <string.h>#define bcopy(b1,b2,len) memmove(b2, b1, (size_t)(len))#define bzero(b,len) memset(b, 0, (size_t)(len))#define bcmp(b1,b2,len) memcmp(b1, b2, (size_t)(len))#endifstruct sockaddr_in hisctladdr;struct sockaddr_in data_addr;int data = -1;int abrtflag = 0;int ptflag = 0;struct sockaddr_in myctladdr;uid_t getuid();sig_t lostpeer();off_t restart_point = 0;unsigned long socks_bind_remoteAddr; /* Socks */extern char *strerror();extern int connected, errno;FILE *cin, *cout;FILE *dataconn();#if !defined(SVR3) && !defined(BIND_RESOLVER) && !defined(LINUX)/* >>> YDL */#if !defined(BSD) || (BSD - 43 <= 0)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; /* In some version of SunOS this is necessary *//* * herror -- * print the error indicated by the h_errno value. */#if defined(AIX_PS2)void herror(s) const char *s;#else /* #if AIX_PS2 not defined */herror(s) char *s;#endif /* #if defined(AIX_PS2) */{ 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) {#if defined(sun) fprintf(stderr, "Host unknown\n");#endif /* defined(sun) */ } else { fprintf(stderr, "%s\n", h_errlist[h_errno]); }}#endif /* !define(BSD) || (BSD - 43 <= 0) *//* <<< YDL */#endif /* !defined(SVR3) && !defined(BIND_RESOLVER) && !defined(LINUX) */char *hookup(host, port) char *host; int port;{ register struct hostent *hp = 0; int s, len, tos; static char hostnamebuf[80]; 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; (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); } else { hp = gethostbyname(host); if (hp == NULL) { fprintf(stderr, "ftp: %s: ", host); herror((char *)NULL); code = -1; return((char *) 0); } hisctladdr.sin_family = hp->h_addrtype; bcopy(hp->h_addr_list[0], (caddr_t)&hisctladdr.sin_addr, hp->h_length); (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); } hostname = hostnamebuf; s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { perror("ftp: socket"); code = -1; return (0); } hisctladdr.sin_port = port; while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { if (hp && hp->h_addr_list[1]) { int oerrno = errno; extern char *inet_ntoa(); fprintf(stderr, "ftp: connect to address %s: ", inet_ntoa(hisctladdr.sin_addr)); errno = oerrno; perror((char *) 0); 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)); (void) close(s); s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { perror("ftp: socket"); code = -1; return (0); } 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");#if defined(ISC) || defined(__alpha) || defined(SCO) cout = fdopen(dup(s), "w");#else cout = fdopen(s, "w");#endif if (cin == NULL || cout == NULL) { fprintf(stderr, "ftp: fdopen failed.\n"); 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) { perror("ftp: setsockopt"); } }#endif /* SO_OOBINLINE */ return (hostname);bad: (void) close(s); return ((char *)0);}login(host) 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); (void) fgets(tmp, sizeof(tmp) - 1, stdin); tmp[strlen(tmp) - 1] = '\0'; if (*tmp == '\0') user = myname; else user = tmp; } n = command("USER %s", user); if (n == CONTINUE) { if (pass == NULL) { if (strcmp(user, "anonymous") == 0) { printf("Password: "); (void) fflush(stdout); (void) fgets(tmp, sizeof(tmp) - 1, stdin); tmp[strlen(tmp) - 1] = '\0'; 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) (void) command("ACCT %s", acct); if (proxy) return(1); for (n = 0; n < macnum; ++n) { if (!strcmp("init", macros[n].mac_name)) { (void) strcpy(line, "$init"); makeargv(); domacro(margc, margv); break; } } return (1);}voidcmdabort(){ extern jmp_buf ptabort; printf("\n"); (void) fflush(stdout); abrtflag++; if (ptflag) longjmp(ptabort,1);}/*VARARGS*/command(va_alist)va_dcl{ va_list ap; char *fmt; int r; sig_t oldintr; void cmdabort(); 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"); (void) 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); fprintf(cout, "\r\n"); (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]; /* last line of previous reply */#include <ctype.h>getreply(expecteof) 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); (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) { printf("421 Service not available, remote server has closed connection\n"); (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(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 = '\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') { (void) putchar(c); (void) fflush (stdout); } 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'); }}empty(mask, sec) struct fd_set *mask; int sec;{ struct timeval t; t.tv_sec = (long) sec; t.tv_usec = 0; return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));}jmp_buf sendabort;voidabortsend(){ mflag = 0; abrtflag = 0; printf("\nsend aborted\nwaiting for remote to finish abort\n"); (void) fflush(stdout); longjmp(sendabort, 1);}#define HASHBYTES 1024sendrequest(cmd, local, remote, printnames) char *cmd, *local, *remote;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -