home *** CD-ROM | disk | FTP | other *** search
- /* ftp.c */
-
- /* $RCSfile: ftp.c,v $
- * $Revision: 14020.12 $
- * $Date: 93/07/09 11:30:28 $
- */
-
- #include "sys.h"
-
- #include <setjmp.h>
- #include <sys/stat.h>
- #include <sys/file.h>
-
- #ifndef AIX /* AIX-2.2.1 declares utimbuf in unistd.h */
- #ifdef NO_UTIMEH
- struct utimbuf {time_t actime; time_t modtime;};
- #else
- # include <utime.h>
- #endif
- #endif /*AIX*/
-
- #ifdef SYSLOG
- # include <syslog.h>
- #endif
-
- /* You may need this for declarations of fd_set, etc. */
- #ifdef SYSSELECTH
- # include <sys/select.h>
- #else
- #ifdef STRICT_PROTOS
- #ifndef Select
- extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
- #endif
- #endif
- #endif
-
- #include <netinet/in.h>
- #include <arpa/ftp.h>
- #include <arpa/inet.h>
- #include <arpa/telnet.h>
- #include <signal.h>
- #include <errno.h>
- #ifdef NET_ERRNO_H
- # include <net/errno.h>
- #endif
- #include <netdb.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include <ctype.h>
- #include "util.h"
- #include "ftp.h"
- #include "cmds.h"
- #include "main.h"
- #include "ftprc.h"
- #include "getpass.h"
- #include "defaults.h"
- #include "copyright.h"
-
- /* ftp.c globals */
- struct sockaddr_in hisctladdr;
- struct sockaddr_in data_addr;
- int data = -1;
- int abrtflag = 0;
- struct sockaddr_in myctladdr;
- FILE *cin = NULL, *cout = NULL;
- char *reply_string = NULL;
- jmp_buf sendabort, recvabort;
- int progress_meter = dPROGRESS;
- int cur_progress_meter;
- int sendport = -1; /* use PORT cmd for each data connection */
- int code; /* return/reply code for ftp command */
- string indataline;
- int cpend; /* flag: if != 0, then pending server reply */
- char *xferbuf; /* buffer for local and remote I/O */
- size_t xferbufsize; /* size in bytes, of the transfer buffer. */
- long next_report;
- long bytes;
- long now_sec;
- long file_size;
- struct timeval start, stop;
- int buffer_only = 0; /* True if reading into redir line
- * buffer only (not echoing to
- * stdout).
- */
-
- /* ftp.c externs */
- extern FILE *logf;
- extern string anon_password;
- extern longstring cwd, lcwd;
- extern Hostname hostname;
- extern int verbose, debug, macnum, margc;
- extern int curtype, creating, toatty;
- extern int options, activemcmd, paging;
- extern int ansi_escapes, logged_in, macnum;
- extern char *line, *margv[];
- extern char *tcap_normal, *tcap_boldface;
- extern char *tcap_underline, *tcap_reverse;
- extern struct userinfo uinfo;
- extern struct macel macros[];
- extern struct lslist *lshead, *lstail;
- extern int is_ls;
- #ifdef PASSIVEMODE
- extern int passivemode;
- #endif
-
- #ifdef GATEWAY
- extern string gateway;
- extern string gate_login;
- #endif
-
- #ifdef TERM_FTP
- #include <client.h>
- extern int lcompression, rcompression;
- int compress_toggle = 0;
- extern int compress_toggle;
- #endif
-
- #if defined(TERM_FTP) && (defined(BSD) || defined(_POSIX_SOURCE))
- FILE *safeopen(int s, char *lmode){
- FILE *file;
-
- setreuid(geteuid(),getuid());
- setregid(getegid(),getgid());
- file=fdopen(s, lmode);
- setreuid(geteuid(),getuid());
- setregid(getegid(),getgid());
- return(file);
- }
- #else
- #define safeopen fdopen
- #endif
-
-
- #ifdef TERM_FTP
-
- int hookup(char *host, unsigned int port)
- {
- int s;
- int result = -1;
-
- lcompression = rcompression = compress_toggle;
-
- if ((s = connect_server(0)) < 0) {
- perror("ftp: connect to term server");
- goto ret;
- }
- send_command(s, C_PORT, 0, "%s:%d", host, ntohs(port));
- send_command(s, C_DUMB, 1, 0);
- cin = fdopen(s, "r");
- cout = fdopen(dup(s), "w");
- if (cin == NULL || cout == NULL) {
- fprintf(stderr, "ftp: safeopen failed.\n");
- goto bad;
- }
- Strncpy(hostname, host);
- if (verbose)
- printf("Connected to %s.\n", hostname);
- if (getreply(0) > 2) { /* read startup message from server */
- goto bad;
- }
- result = 0;
- goto ret;
-
- bad:
- (void) close(s);
- if (cin != NULL)
- (void) fclose(cin);
- if (cout != NULL)
- (void) fclose(cout);
- cin = cout = NULL;
-
- ret:
- return (result);
- } /* hookup_term */
- #else /* Not TERM_FTP, i.e. most of us. */
-
- int hookup(char *host, unsigned int port)
- {
- register struct hostent *hp = 0;
- int s, len, hErr = -1;
- string errstr;
- char **curaddr = NULL;
-
- bzero((char *)&hisctladdr, sizeof (hisctladdr));
- #ifdef BAD_INETADDR
- hisctladdr.sin_addr = inet_addr(host);
- #else
- hisctladdr.sin_addr.s_addr = inet_addr(host);
- #endif
- if (hisctladdr.sin_addr.s_addr != -1) {
- hisctladdr.sin_family = AF_INET;
- (void) Strncpy(hostname, host);
- } else {
- hp = gethostbyname(host);
- if (hp == NULL) {
- #ifdef HERROR
- extern int h_errno;
- if (h_errno == HOST_NOT_FOUND)
- (void) printf("%s: unknown host\n", host);
- else (void) fprintf(stderr, "%s: gethostbyname herror (%d): ",
- host, h_errno);
- herror(NULL);
- #else
- (void) printf("%s: unknown host\n", host);
- #endif
- goto done;
- }
- hisctladdr.sin_family = hp->h_addrtype;
- curaddr = hp->h_addr_list;
- bcopy(*curaddr, (caddr_t)&hisctladdr.sin_addr, hp->h_length);
- (void) Strncpy(hostname, hp->h_name);
- }
- s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
- if (s < 0) {
- PERROR("hookup", "socket");
- goto done;
- }
- hisctladdr.sin_port = port;
- #ifdef SOCKS
- while (Rconnect(s, (struct sockaddr *) &hisctladdr, (int) sizeof (hisctladdr)) < 0) {
- #else
- while (Connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
- #endif
- if (curaddr != NULL) {
- curaddr++;
- if (*curaddr != (char *)0) {
- (void) sprintf(errstr, "connect error to address %s",
- inet_ntoa(hisctladdr.sin_addr));
- PERROR("hookup", errstr);
- bcopy(*curaddr, (caddr_t)&hisctladdr.sin_addr, hp->h_length);
- dbprintf("Trying %s...\n", inet_ntoa(hisctladdr.sin_addr));
- (void) close(s);
- s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
- if (s < 0) {
- PERROR("hookup", "socket");
- goto done;
- }
- continue;
- }
- }
- PERROR("hookup", "connect");
- switch (errno) {
- case ENETDOWN:
- case ENETUNREACH:
- case ECONNABORTED:
- case ETIMEDOUT:
- case ECONNREFUSED:
- case EHOSTDOWN:
- hErr = -2; /* we can re-try later. */
- }
- goto bad;
- }
- len = sizeof (myctladdr);
- if (Getsockname(s, (char *)&myctladdr, &len) < 0) {
- PERROR("hookup", "getsockname");
- goto bad;
- }
- cin = safeopen(s, "r");
- cout = safeopen(dup(s), "w");
- if (cin == NULL || cout == NULL) {
- (void) fprintf(stderr, "ftp: safeopen failed.\n");
- close_streams(0);
- goto bad;
- }
- if (IS_VVERBOSE)
- (void) printf("Connected to %s.\n", hostname);
- #ifdef IPTOS_LOWDELAY /* control is interactive */
- #ifdef IP_TOS
- {
- int nType = IPTOS_LOWDELAY;
- if (setsockopt(s, IPPROTO_IP, IP_TOS,
- (char *) &nType, sizeof(nType)) < 0) {
- PERROR("hookup", "setsockopt(IP_TOS)");
- }
- }
- #endif
- #endif
- if (getreply(0) > 2) { /* read startup message from server */
- close_streams(0);
- if (code == 421)
- hErr = -2; /* We can try again later. */
- goto bad;
- }
- #ifdef SO_OOBINLINE
- {
- int on = 1;
-
- if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof(on))
- < 0 && debug) {
- PERROR("hookup", "setsockopt(SO_OOBINLINE)");
- }
- }
- #endif /* SO_OOBINLINE */
-
- hErr = 0;
- goto done;
-
- bad:
- (void) close(s);
- if (cin != NULL)
- (void) fclose(cin);
- if (cout != NULL)
- (void) fclose(cout);
- cin = cout = NULL;
- done:
- return (hErr);
- } /* hookup */
- #endif /* TERM_FTP */
-
-
- /* This registers the user's username, password, and account with the remote
- * host which validates it. If we get on, we also do some other things, like
- * enter a log entry and execute the startup macro.
- */
- int Login(char *userNamePtr, char *passWordPtr, char *accountPtr, int doInit)
- {
- string userName;
- string str;
- int n;
- int sentAcct = 0;
- int userWasPrompted = 0;
- int result = CMDERR;
- time_t now;
-
- if (userNamePtr == NULL) {
- /* Prompt for a username. */
- (void) sprintf(str, "Login Name (%s): ", uinfo.username);
- ++userWasPrompted;
- if (Gets(str, userName, sizeof(userName)) == NULL)
- goto done;
- else if (userName[0]) {
- /* User didn't just hit return. */
- userNamePtr = userName;
- } else {
- /*
- * User can hit return if he wants to enter his username
- * automatically.
- */
- if (*uinfo.username != '\0')
- userNamePtr = uinfo.username;
- else
- goto done;
- }
- }
-
- #ifdef GATEWAY
- if (*gateway)
- (void) sprintf(str, "USER %s@%s",
- (*gate_login ? gate_login : dGATEWAY_LOGIN),
- hostname);
- else
- #endif
- (void) sprintf(str, "USER %s", userNamePtr);
-
- /* Send the user name. */
- n = command(str);
- if (n == CONTINUE) {
- if (passWordPtr == NULL) {
- if (((strcmp("anonymous", userName) == 0) ||
- (strcmp("ftp", userName) == 0)) && (*anon_password != '\0'))
- passWordPtr = anon_password;
- else {
- /* Prompt for a password. */
- ++userWasPrompted;
- passWordPtr = Getpass("Password:");
- }
- }
-
- /* The remote site is requesting us to send the password now. */
- (void) sprintf(str, "PASS %s", passWordPtr);
- n = command(str);
- if (n == CONTINUE) {
- /* The remote site is requesting us to send the account now. */
- if (accountPtr == NULL) {
- /* Prompt for a username. */
- (void) sprintf(str, "ACCT %s", Getpass("Account:"));
- ++userWasPrompted;
- } else {
- (void) sprintf(str, "ACCT %s", accountPtr);
- }
- ++sentAcct; /* Keep track that we've sent the account already. */
- n = command(str);
- }
- }
-
- if (n != COMPLETE) {
- (void) printf("Login failed.\n");
- goto done;
- }
-
- /* If you specified an account, and the remote-host didn't request it
- * (maybe it's optional), we will send the account information.
- */
- if (!sentAcct && accountPtr != NULL) {
- (void) sprintf(str, "ACCT %s", accountPtr);
- (void) command(str);
- }
-
- /* See if remote host dropped connection. Some sites will let you log
- * in anonymously, only to tell you that they already have too many
- * anon users, then drop you. We do a no-op here to see if they've
- * ditched us.
- */
- n = quiet_command("NOOP");
- if (n == TRANSIENT)
- goto done;
-
- #ifdef SYSLOG
- syslog(LOG_INFO, "%s connected to %s as %s.",
- uinfo.username, hostname, userNamePtr);
- #endif
-
- /* Save which sites we opened to the user's logfile. */
- if (logf != NULL) {
- (void) time(&now);
- (void) fprintf(logf, "%s opened at %s",
- hostname,
- ctime(&now));
- }
-
- /* Let the user know we are logged in, unless he was prompted for some
- * information already.
- */
- if (!userWasPrompted)
- if (NOT_VQUIET)
- (void) printf("Logged into %s.\n", hostname);
-
- if ((doInit) && (macnum > 0)) {
- /* Run the startup macro, if any. */
- /* If macnum is non-zero, the init macro was defined from
- * ruserpass. It would be the only macro defined at this
- * point.
- */
- (void) strcpy(line, "$init");
- makeargv();
- (void) domacro(margc, margv);
- }
-
- _cd(NULL); /* Init cwd variable. */
-
- result = NOERR;
- logged_in = 1;
-
- done:
- return (result);
- } /* Login */
-
-
-
- /*ARGSUSED*/
- void cmdabort SIG_PARAMS
- {
- (void) printf("\n");
- (void) fflush(stdout);
- abrtflag++;
- } /* cmdabort */
-
-
-
-
- int CommandWithFlags(char *cmd, int flags)
- {
- int r;
- Sig_t oldintr;
- string str;
-
- if (cmd == NULL) {
- /* Should never happen; bug if it does. */
- PERROR("command", "NULL command");
- return (-1);
- }
- abrtflag = 0;
- if (debug) {
- if (strncmp(cmd, "PASS", (size_t)4) == 0)
- dbprintf("cmd: \"PASS ********\"\n");
- else
- dbprintf("cmd: \"%s\" (length %d)\n", cmd, (int) strlen(cmd));
- }
- if (cout == NULL) {
- (void) sprintf(str, "%s: No control connection for command", cmd);
- PERROR("command", str);
- return (0);
- }
- oldintr = Signal(SIGINT, /* cmdabort */ SIG_IGN);
-
- /* Used to have BROKEN_MEMCPY tested here. */
- if (cout != NULL)
- (void) fprintf(cout, "%s\r\n", cmd);
-
- (void) fflush(cout);
- cpend = 1;
- r = (flags == WAIT_FOR_REPLY) ?
- (getreply(strcmp(cmd, "QUIT") == 0)) : PRELIM;
- if (abrtflag && oldintr != SIG_IGN && oldintr != NULL)
- (*oldintr)(0);
- (void) Signal(SIGINT, oldintr);
- return(r);
- } /* CommandWithFlags */
-
-
-
- /* This stub runs 'CommandWithFlags' above, telling it to wait for
- * reply after the command is sent.
- */
- int command(char *cmd)
- {
- return (CommandWithFlags(cmd, WAIT_FOR_REPLY));
- } /* command */
-
- /* This stub runs 'CommandWithFlags' above, telling it to NOT wait for
- * reply after the command is sent.
- */
- int command_noreply(char *cmd)
- {
- return(CommandWithFlags(cmd, DONT_WAIT_FOR_REPLY));
- } /* command */
-
-
-
- int quiet_command(char *cmd)
- {
- register int oldverbose, result;
-
- oldverbose = verbose;
- verbose = debug ? V_VERBOSE : V_QUIET;
- result = command(cmd);
- verbose = oldverbose;
- return (result);
- } /* quiet_command */
-
-
-
-
- int verbose_command(char *cmd)
- {
- register int oldverbose, result;
-
- oldverbose = verbose;
- verbose = V_VERBOSE;
- result = command(cmd);
- verbose = oldverbose;
- return (result);
- } /* quiet_command */
-
-
-
-
- int getreply(int expecteof)
- {
- register int c, n = 0;
- int dig;
- char *cp, *end, *dp;
- int thiscode, originalcode = 0, continuation = 0;
- Sig_t oldintr;
-
- if (cin == NULL)
- return (-1);
- /* oldintr = Signal(SIGINT, SIG_IGN); */
- oldintr = Signal(SIGINT, cmdabort);
- end = reply_string + RECEIVEDLINELEN - 2;
- for (;abrtflag==0;) {
- dig = n = thiscode = code = 0;
- cp = reply_string;
- for (;abrtflag==0;) {
- c = fgetc(cin);
- if (c == IAC) { /* handle telnet commands */
- switch (c = fgetc(cin)) {
- case WILL:
- case WONT:
- c = fgetc(cin);
- (void) fprintf(cout, "%c%c%c",IAC,DONT,c);
- (void) fflush(cout);
- break;
- case DO:
- case DONT:
- c = fgetc(cin);
- (void) 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(0);
- if (NOT_VQUIET) {
- (void) printf("421 Service not available, remote server has closed connection\n");
- (void) fflush(stdout);
- }
- code = 421;
- return(4);
- }
- if (cp < end && c != '\r')
- *cp++ = c;
-
- if (c == '\n')
- break;
- if (dig < 4 && isdigit(c))
- code = thiscode = code * 10 + (c - '0');
- else if (dig == 4 && c == '-') {
- if (continuation)
- code = 0;
- continuation++;
- }
- if (n == 0)
- n = c;
- } /* end for(;;) #2 */
-
- *cp = '\0';
- switch (verbose) {
- case V_QUIET:
- /* Don't print anything. */
- break;
- case V_ERRS:
- if (n == '5') {
- dp = reply_string;
- goto stripCode;
- }
- break;
- case V_IMPLICITCD:
- case V_TERSE:
- dp = NULL;
- if (n == '5' && verbose == V_TERSE)
- dp = reply_string;
- else {
- switch (thiscode) {
- case 230:
- case 214:
- case 331:
- case 332:
- case 421: /* For ftp.apple.com, etc. */
- dp = reply_string;
- break;
- case 220:
- /*
- * Skip the foo FTP server ready line.
- */
- if (strstr(reply_string, "ready.") == NULL)
- dp = reply_string;
- break;
- case 250:
- /*
- * Print 250 lines if they aren't
- * "250 CWD command successful."
- */
- if (strncmp(reply_string + 4, "CWD ", (size_t) 4))
- dp = reply_string;
- }
- }
- if (dp == NULL) break;
- stripCode:
- /* Try to strip out the code numbers, etc. */
- if (isdigit(*dp++) && isdigit(*dp++) && isdigit(*dp++)) {
- if (*dp == ' ' || *dp == '-') {
- dp++;
- if (*dp == ' ') dp++;
- } else dp = reply_string;
- } else {
- int spaces;
- dp = reply_string;
- for (spaces = 0; spaces < 4; ++spaces)
- if (dp[spaces] != ' ')
- break;
- if (spaces == 4)
- dp += spaces;
- }
- goto printLine;
- case V_VERBOSE:
- dp = reply_string;
- printLine: (void) fputs(dp, stdout);
- } /* end switch */
-
- if (continuation && code != originalcode) {
- if (originalcode == 0)
- originalcode = code;
- continue;
- }
- if (n != '1')
- cpend = 0;
- (void) Signal(SIGINT,oldintr);
- if (code == 421 || originalcode == 421)
- lostpeer(0);
- if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN && oldintr)
- (*oldintr)(0);
- break;
- } /* end for(;;) #1 */
- return (n - '0');
- } /* getreply */
-
-
-
-
- static int empty(struct fd_set *mask, int sec)
- {
- struct timeval t;
-
- t.tv_sec = (long) sec;
- t.tv_usec = 0;
-
- return(Select(32, mask, NULL, NULL, &t));
- } /* empty */
-
-
-
-
- static 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;
- } /* tvsub */
-
-
- /* Variables private to progress_report code. */
- static int barlen;
- static long last_dot;
- static int dots;
-
- int start_progress(int sending, char *local)
- {
- long s;
- char spec[64];
-
- cur_progress_meter = toatty ? progress_meter : 0;
- if ((cur_progress_meter > pr_last) || (cur_progress_meter < 0))
- cur_progress_meter = dPROGRESS;
- if ((file_size <= 0) && ((cur_progress_meter == pr_percent) || (cur_progress_meter == pr_philbar) || (cur_progress_meter == pr_last)))
- cur_progress_meter = pr_kbytes;
- if (!ansi_escapes && (cur_progress_meter == pr_philbar))
- cur_progress_meter = pr_dots;
-
- (void) Gettimeofday(&start);
- now_sec = start.tv_sec;
-
- switch (cur_progress_meter) {
- case pr_none:
- break;
- case pr_percent:
- (void) printf("%s: ", local);
- goto zz;
- case pr_kbytes:
- (void) printf("%s: ", local);
- goto zz;
- case pr_philbar:
- (void) printf("%s%s file: %s %s\n",
- tcap_boldface,
- sending ? "Sending" : "Receiving",
- local,
- tcap_normal
- );
- barlen = 52;
- for (s = file_size; s > 0; s /= 10L) barlen--;
- (void) sprintf(spec, " 0 %%%ds %%ld bytes. ETA: --:--\r",
- barlen);
- (void) printf(spec, " ", file_size);
- goto zz;
- case pr_dots:
- last_dot = (file_size / 10) + 1;
- dots = 0;
- (void) printf("%s: ", local);
- zz:
- (void) fflush(stdout);
- Echo(stdin, 0);
- } /* end switch */
- return (cur_progress_meter);
- } /* start_progress */
-
-
-
-
- int progress_report(int finish_up)
- {
- int size;
- int perc;
- float frac;
- char spec[64];
- float secsElap;
- int secsLeft, minLeft;
- struct timeval td;
-
- next_report += xferbufsize;
- (void) Gettimeofday(&stop);
- if ((stop.tv_sec > now_sec) || (finish_up && file_size)) {
- switch (cur_progress_meter) {
- case pr_none:
- break;
- case pr_percent:
- perc = (int) (100.0 * (float)bytes / (float)file_size);
- if (perc > 100) perc = 100;
- else if (perc < 0) perc = 0;
- (void) printf("\b\b\b\b%3d%%", perc);
- (void) fflush(stdout);
- break;
- case pr_philbar:
- frac = (float)bytes / (float)file_size;
- if (frac > 1.0)
- frac = 1.0;
- else if (frac < 0.0)
- frac = 0.0;
- size = (int) ((float)barlen * frac);
- (void) sprintf(spec,
- "%%3d%%%% 0 %%s%%%ds%%s%%%ds %%ld bytes. ETA:%%3d:%%02d\r",
- size, barlen - size);
- perc = (long) (100.0 * frac);
- tvsub(&td, &stop, &start);
- secsElap = td.tv_sec + (td.tv_usec / 1000000.0);
- secsLeft = (int) ((float)file_size / ((float)bytes/secsElap) -
- secsElap + 0.5);
- minLeft = secsLeft / 60;
- secsLeft = secsLeft - (minLeft * 60);
- (void) printf(
- spec,
- perc,
- tcap_reverse,
- "",
- tcap_normal,
- "",
- file_size,
- minLeft,
- secsLeft
- );
- (void) fflush(stdout);
- break;
- case pr_kbytes:
- if ((bytes / 1024) > 0) {
- (void) printf("\b\b\b\b\b\b%5ldK", bytes / 1024);
- (void) fflush(stdout);
- }
- break;
- case pr_dots:
- if (bytes > last_dot) {
- (void) fputc('.', stdout);
- (void) fflush(stdout);
- last_dot += (file_size / 10) + 1;
- dots++;
- }
- } /* end switch */
- now_sec = stop.tv_sec;
- } /* end if we updated */
- return (UserLoggedIn());
- } /* progress_report */
-
-
-
-
-
- void end_progress(char *direction, char *local, char *remote)
- {
- struct timeval td;
- float s, bs = 0.0;
- str32 bsstr;
- int doLastReport;
- int receiving;
- longstring fullRemote, fullLocal;
-
- doLastReport = ((UserLoggedIn()) && (cur_progress_meter != pr_none) &&
- (NOT_VQUIET) && (bytes > 0));
-
- receiving = (direction[0] == 'r');
-
- switch(FileType(local)) {
- case IS_FILE:
- (void) Strncpy(fullLocal, lcwd);
- (void) Strncat(fullLocal, "/");
- (void) Strncat(fullLocal, local);
- break;
- case IS_PIPE:
- doLastReport = 0;
- local = Strncpy(fullLocal, local);
- break;
- case IS_STREAM:
- default:
- doLastReport = 0;
- local = Strncpy(fullLocal, receiving ? "stdout" : "stdin");
- }
-
- if (doLastReport)
- (void) progress_report(1); /* tell progress proc to cleanup. */
-
- tvsub(&td, &stop, &start);
- s = td.tv_sec + (td.tv_usec / 1000000.0);
-
- bsstr[0] = '\0';
- if (s != 0.0) {
- bs = (float)bytes / s;
- if (bs > 1024.0)
- sprintf(bsstr, "%.2f K/s", bs / 1024.0);
- else
- sprintf(bsstr, "%.2f Bytes/sec", bs);
- }
-
- if (doLastReport) switch(cur_progress_meter) {
- case pr_none:
- zz:
- (void) printf("%s: %ld bytes %s in %.2f seconds, %s.\n",
- local, bytes, direction, s, bsstr);
- break;
- case pr_kbytes:
- case pr_percent:
- (void) printf("%s%ld bytes %s in %.2f seconds, %s.\n",
- cur_progress_meter == pr_kbytes ? "\b\b\b\b\b\b" : "\b\b\b\b",
- bytes, direction, s, bsstr);
- Echo(stdin, 1);
- break;
- case pr_philbar:
- (void) printf("\n");
- Echo(stdin, 1);
- goto zz;
- case pr_dots:
- for (; dots < 10; dots++)
- (void) fputc('.', stdout);
- (void) fputc('\n', stdout);
- Echo(stdin, 1);
- goto zz;
- }
-
- /* Save transfers to the logfile. */
- /* if a simple path is given, try to log the full path */
- if (*remote != '/') {
- (void) Strncpy(fullRemote, cwd);
- (void) Strncat(fullRemote, "/");
- (void) Strncat(fullRemote, remote);
- } else
- (void) Strncpy(fullRemote, remote);
-
- if (logf != NULL) {
- (void) fprintf(logf, "\t-> \"%s\" %s, %s\n",
- fullRemote, direction, bsstr);
- }
- #ifdef SYSLOG
- {
- longstring infoPart1;
-
- /* Some syslog()'s can't take an unlimited number of arguments,
- * so shorten our call to syslog to 5 arguments total.
- */
- Strncpy(infoPart1, uinfo.username);
- if (receiving) {
- Strncat(infoPart1, " received ");
- Strncat(infoPart1, fullRemote);
- Strncat(infoPart1, " as ");
- Strncat(infoPart1, fullLocal);
- Strncat(infoPart1, " from ");
- } else {
- Strncat(infoPart1, " sent ");
- Strncat(infoPart1, fullLocal);
- Strncat(infoPart1, " as ");
- Strncat(infoPart1, fullRemote);
- Strncat(infoPart1, " to ");
- }
- Strncat(infoPart1, hostname);
- syslog (LOG_INFO, "%s (%ld bytes, %s).", infoPart1, bytes, bsstr);
- }
- #endif /* SYSLOG */
- } /* end_progress */
-
-
-
-
- void close_file(FILE **fin, int filetype)
- {
- if (*fin != NULL) {
- if (filetype == IS_FILE) {
- (void) fclose(*fin);
- *fin = NULL;
- } else if (filetype == IS_PIPE) {
- (void) pclose(*fin);
- *fin = NULL;
- }
- }
- } /* close_file */
-
-
-
-
- /*ARGSUSED*/
- void abortsend SIG_PARAMS
- {
- activemcmd = 0;
- abrtflag = 0;
- (void) fprintf(stderr, "\nSend aborted.\n");
- Echo(stdin, 1);
- longjmp(sendabort, 1);
- } /* abortsend */
-
-
-
- int sendrequest(char *cmd, char *local, char *remote)
- {
- FILE *fin, *dout = NULL;
- Sig_t oldintr, oldintp;
- string str;
- register int c, d;
- struct stat st;
- int filetype, result = NOERR;
- int do_reports = 0;
- char *mode;
- register char *bufp;
-
- dbprintf("cmd: %s; rmt: %s; loc: %s.\n",
- cmd,
- remote == NULL ? "(null)" : remote,
- local == NULL ? "(null)" : local
- );
-
- oldintr = NULL;
- oldintp = NULL;
- mode = "w";
- bytes = file_size = 0L;
- 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);
- result = -1;
- goto xx;
- }
- oldintr = Signal(SIGINT, abortsend);
- file_size = -1;
- if (strcmp(local, "-") == 0) {
- fin = stdin;
- filetype = IS_STREAM;
- } else if (*local == '|') {
- filetype = IS_PIPE;
- oldintp = Signal(SIGPIPE,SIG_IGN);
- fin = popen(local + 1, "r");
- if (fin == NULL) {
- PERROR("sendrequest", local + 1);
- (void) Signal(SIGINT, oldintr);
- (void) Signal(SIGPIPE, oldintp);
- result = -1;
- goto xx;
- }
- } else {
- filetype = IS_FILE;
- fin = fopen(local, "r");
- if (fin == NULL) {
- PERROR("sendrequest", local);
- (void) Signal(SIGINT, oldintr);
- result = -1;
- goto xx;
- }
- if (fstat(fileno(fin), &st) < 0 ||
- (st.st_mode&S_IFMT) != S_IFREG) {
- (void) fprintf(stdout, "%s: not a plain file.\n", local);
- (void) Signal(SIGINT, oldintr);
- (void) fclose(fin);
- result = -1;
- goto xx;
- }
- file_size = st.st_size;
- }
- if (initconn()) {
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- result = -1;
- close_file(&fin, filetype);
- goto xx;
- }
- if (setjmp(sendabort))
- goto Abort;
-
- #ifdef TRY_NOREPLY
- if (remote) {
- (void) sprintf(str, "%s %s", cmd, remote);
- (void) command_noreply(str);
- } else {
- (void) command_noreply(cmd);
- }
-
- dout = dataconn(mode);
- if (dout == NULL)
- goto Abort;
-
- if(getreply(0) != PRELIM) {
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- close_file(&fin, filetype);
- return -1;
- }
- #else
- if (remote) {
- (void) sprintf(str, "%s %s", cmd, remote);
- if (command(str) != PRELIM) {
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- close_file(&fin, filetype);
- goto xx;
- }
- } else {
- if (command(cmd) != PRELIM) {
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- close_file(&fin, filetype);
- goto xx;
- }
- }
-
- dout = dataconn(mode);
- if (dout == NULL)
- goto Abort;
- #endif
-
- (void) Gettimeofday(&start);
- oldintp = Signal(SIGPIPE, SIG_IGN);
- if ((do_reports = (filetype == IS_FILE && NOT_VQUIET)) != 0)
- do_reports = start_progress(1, local);
-
- switch (curtype) {
-
- case TYPE_I:
- case TYPE_L:
- errno = d = 0;
- while ((c = read(fileno(fin), xferbuf, (int)xferbufsize)) > 0) {
- bytes += c;
- for (bufp = xferbuf; c > 0; c -= d, bufp += d)
- if ((d = write(fileno(dout), bufp, c)) <= 0)
- break;
- /* Print progress indicator. */
- if (do_reports)
- do_reports = progress_report(0);
- }
- if (c < 0)
- PERROR("sendrequest", local);
- if (d <= 0) {
- if (d == 0 && !creating)
- (void) fprintf(stderr, "netout: write returned 0?\n");
- else if (errno != EPIPE)
- PERROR("sendrequest", "netout");
- bytes = -1;
- }
- break;
-
- case TYPE_A:
- next_report = xferbufsize;
- while ((c = getc(fin)) != EOF) {
- if (c == '\n') {
- if (ferror(dout))
- break;
- (void) putc('\r', dout);
- bytes++;
- }
- (void) putc(c, dout);
- bytes++;
-
- /* Print progress indicator. */
- if (do_reports && bytes > next_report)
- do_reports = progress_report(0);
- }
- if (ferror(fin))
- PERROR("sendrequest", local);
- if (ferror(dout)) {
- if (errno != EPIPE)
- PERROR("sendrequest", "netout");
- bytes = -1;
- }
- break;
- }
- Done:
- close_file(&fin, filetype);
- if (dout)
- (void) fclose(dout);
- (void) getreply(0);
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- end_progress("sent", local, remote);
- xx:
- return (result);
- Abort:
- result = -1;
- if (!cpend)
- goto xx;
- if (data >= 0) {
- (void) close(data);
- data = -1;
- }
- goto Done;
- } /* sendrequest */
-
-
-
-
- /*ARGSUSED*/
- void abortrecv SIG_PARAMS
- {
- activemcmd = 0;
- abrtflag = 0;
- (void) fprintf(stderr,
- #ifdef TRY_ABOR
- "(abort)\n");
- #else
- "\nAborting, please wait...");
- #endif
- (void) fflush(stderr);
- Echo(stdin, 1);
- longjmp(recvabort, 1);
- } /* abortrecv */
-
-
-
-
- void GetLSRemoteDir(char *remote, char *remote_dir)
- {
- char *cp;
-
- /*
- * The ls() function can specify a directory to list along with ls flags,
- * if it sends the flags first followed by the directory name.
- *
- * So far, we don't care about the remote directory being listed. I put
- * it now so I won't forget in case I need to do something with it later.
- */
- remote_dir[0] = 0;
- if (remote != NULL) {
- cp = index(remote, LS_FLAGS_AND_FILE);
- if (cp == NULL)
- (void) Strncpy(remote_dir, remote);
- else {
- *cp++ = ' ';
- (void) Strncpy(remote_dir, cp);
- }
- }
- } /* GetLSRemoteDir */
-
-
-
-
- int AdjustLocalFileName(char *local)
- {
- char *dir;
-
- /* See if the file exists, and if we can overwrite it. */
- if ((access(local, 0) == 0) && (access(local, 2) < 0))
- goto noaccess;
-
- /*
- * Make sure we are writing to a valid local path.
- * First check the local directory, and see if we can write to it.
- */
- if (access(local, 2) < 0) {
- dir = rindex(local, '/');
-
- if (errno != ENOENT && errno != EACCES) {
- /* Report an error if it's one we can't handle. */
- PERROR("AdjustLocalFileName", local);
- return -1;
- }
- /* See if we have write permission on this directory. */
- if (dir != NULL) {
- /* Special case: /filename. */
- if (dir != local)
- *dir = 0;
- if (access(dir == local ? "/" : local, 2) < 0) {
- /*
- * We have a big long pathname, like /a/b/c/d,
- * but see if we can write into the current
- * directory and call the file ./d.
- */
- if (access(".", 2) < 0) {
- (void) strcpy(local, " and .");
- goto noaccess;
- }
- (void) strcpy(local, dir + 1); /* use simple filename. */
- } else
- *dir = '/';
- } else {
- /* We have a simple path name (file name only). */
- if (access(".", 2) < 0) {
- noaccess: PERROR("AdjustLocalFileName", local);
- return -1;
- }
- }
- }
- return (NOERR);
- } /* AdjustLocalFileName */
-
-
-
- int SetToAsciiForLS(int is_retr, int currenttype)
- {
- int oldt = -1, oldv;
-
- if (!is_retr) {
- if (currenttype != TYPE_A) {
- oldt = currenttype;
- oldv = verbose;
- if (!debug)
- verbose = V_QUIET;
- (void) setascii(0, NULL);
- verbose = oldv;
- }
- }
- return oldt;
- } /* SetToAsciiForLS */
-
-
-
- int IssueCommand(char *ftpcmd, char *remote)
- {
- string str;
- int result = NOERR;
-
- if (remote)
- (void) sprintf(str, "%s %s", ftpcmd, remote);
- else
- (void) Strncpy(str, ftpcmd);
-
- #ifdef TRY_NOREPLY
- if (command_noreply(str) != PRELIM)
- #else
- if (command(str) != PRELIM)
- #endif
- result = -1;
- return (result);
- } /* IssueCommand */
-
-
-
- FILE *OpenOutputFile(int filetype, char *local, char *mode, Sig_t *oldintp)
- {
- FILE *fout;
-
- if (filetype == IS_STREAM) {
- fout = stdout;
- } else if (filetype == IS_PIPE) {
- /* If it is a pipe, the pipecmd will have a | as the first char. */
- ++local;
- fout = popen(local, "w");
- *oldintp = Signal(SIGPIPE, abortrecv);
- } else {
- fout = fopen(local, mode);
- }
- if (fout == NULL)
- PERROR("OpenOutputFile", local);
- return (fout);
- } /* OpenOutputFile */
-
-
-
- void ReceiveBinary(FILE *din, FILE *fout, int *do_reports, char *localfn)
- {
- int c, d, do2;
-
- errno = 0; /* Clear any old error left around. */
- do2 = *do_reports; /* A slight optimization :-) */
- bytes = 0; /* Init the byte-transfer counter. */
-
- for (;;) {
- /* Read a block from the input stream. */
- c = read(fileno(din), xferbuf, (int)xferbufsize);
-
- /* If c is zero, then we've read the whole file. */
- if (c == 0)
- break;
-
- /* Check for errors that may have occurred while reading. */
- if (c < 0) {
- /* Error occurred while reading. */
- if (errno != EPIPE)
- PERROR("ReceiveBinary", "netin");
- bytes = -1;
- break;
- }
-
- /* Write out the same block we just read in. */
- d = write(fileno(fout), xferbuf, c);
-
- /* Check for write errors. */
- if ((d < 0) || (ferror(fout))) {
- /* Error occurred while writing. */
- PERROR("ReceiveBinary", "outfile");
- break;
- }
- if (d < c) {
- (void) fprintf(stderr, "%s: short write\n", localfn);
- break;
- }
-
- /* Update the byte counter. */
- bytes += (long) c;
-
- /* Print progress indicator. */
- if (do2 != 0)
- do2 = progress_report(0);
- }
-
- *do_reports = do2; /* Update the real do_reports variable. */
- } /* ReceiveBinary */
-
-
-
- void AddRedirLine(char *str2)
- {
- register struct lslist *new;
-
- (void) Strncpy(indataline, str2);
- new = (struct lslist *) malloc((size_t) sizeof(struct lslist));
- if (new != NULL) {
- if ((new->string = NewString(str2)) != NULL) {
- new->next = NULL;
- if (lshead == NULL)
- lshead = lstail = new;
- else {
- lstail->next = new;
- lstail = new;
- }
- }
- }
- } /* AddRedirLine */
-
-
-
- void ReceiveAscii(FILE *din, FILE *fout, int *do_reports, char *localfn, int
- lineMode)
- {
- string str2;
- int nchars = 0, c;
- char *linePtr;
- int do2 = *do_reports, stripped;
-
- next_report = xferbufsize;
- bytes = errno = 0;
- if (lineMode) {
- while ((linePtr = FGets(str2, din)) != NULL) {
- bytes += (long) RemoveTrailingNewline(linePtr, &stripped);
- if (is_ls || debug > 0)
- AddRedirLine(linePtr);
-
- /* Shutup while getting remote size and mod time. */
- if (!buffer_only) {
- c = fputs(linePtr, fout);
-
- if (c != EOF) {
- if (stripped > 0)
- c = fputc('\n', fout);
- }
- if ((c == EOF) || (ferror(fout))) {
- PERROR("ReceiveAscii", "outfile");
- break;
- }
- }
-
- /* Print progress indicator. */
- if (do2 && bytes > next_report)
- do2 = progress_report(0);
- }
- } else while ((c = getc(din)) != EOF) {
- linePtr = str2;
- while (c == '\r') {
- bytes++;
- if ((c = getc(din)) != '\n') {
- if (ferror(fout))
- goto break2;
- /* Shutup while getting remote size and mod time. */
- if (!buffer_only)
- (void) putc('\r', fout);
- if (c == '\0') {
- bytes++;
- goto contin2;
- }
- if (c == EOF)
- goto contin2;
- }
- }
- /* Shutup while getting remote size and mod time. */
- if (!buffer_only)
- (void) putc(c, fout);
- bytes++;
-
- /* Print progress indicator. */
- if (do2 && bytes > next_report)
- do2 = progress_report(0);
-
- /* No seg violations, please */
- if (nchars < sizeof(str2) - 1) {
- *linePtr++ = c; /* build redir string */
- nchars++;
- }
-
- contin2:
- /* Save the input line in the buffer for recall later. */
- if (c == '\n' && is_ls) {
- *--linePtr = 0;
- AddRedirLine(str2);
- nchars = 0;
- }
-
- } /* while ((c = getc(din)) != EOF) */
- break2:
- if (ferror(din)) {
- if (errno != EPIPE)
- PERROR("ReceiveAscii", "netin");
- bytes = -1;
- }
- if (ferror(fout)) {
- if (errno != EPIPE)
- PERROR("ReceiveAscii", localfn);
- }
- *do_reports = do2;
- } /* ReceiveAscii */
-
-
-
- void CloseOutputFile(FILE *f, int filetype, char *name, time_t mt)
- {
- struct utimbuf ut;
-
- if (f != NULL) {
- (void) fflush(f);
- if (filetype == IS_FILE) {
- (void) fclose(f);
- #ifndef DONT_TIMESTAMP
- if (mt != (time_t)0) {
- ut.actime = ut.modtime = mt;
- (void) utime(name, &ut);
- }
- #endif /* DONT_TIMESTAMP */
- } else if (filetype == IS_PIPE) {
- (void)pclose(f);
- }
- }
- } /* close_file */
-
-
-
- void ResetOldType(int oldtype)
- {
- int oldv;
-
- if (oldtype >= 0) {
- oldv = verbose;
- if (!debug)
- verbose = V_QUIET;
- (void) SetTypeByNumber(oldtype);
- verbose = oldv;
- }
- } /* ResetOldType */
-
-
-
- int FileType(char *fname)
- {
- int ft = IS_FILE;
-
- if (strcmp(fname, "-") == 0)
- ft = IS_STREAM;
- else if (*fname == '|')
- ft = IS_PIPE;
- return (ft);
- } /* FileType */
-
-
-
-
- void CloseData(void) {
- if (data >= 0) {
- (void) close(data);
- data = -1;
- }
- } /* CloseData */
-
-
-
-
- int recvrequest(char *cmd, char *local, char *remote, char *mode)
- {
- FILE *fout = NULL, *din = NULL;
- Sig_t oldintr = NULL, oldintp = NULL;
- int oldtype = -1, is_retr;
- int nfnd;
- char msg;
- struct fd_set mask;
- int filetype, do_reports = 0;
- string remote_dir;
- time_t remfTime = 0;
- int result = -1;
-
- dbprintf("---> cmd: %s; rmt: %s; loc: %s; mode: %s.\n",
- cmd,
- remote == NULL ? "(null)" : remote,
- local == NULL ? "(null)" : local,
- mode
- );
-
- is_retr = strcmp(cmd, "RETR") == 0;
-
- GetLSRemoteDir(remote, remote_dir);
- if ((filetype = FileType(local)) == IS_FILE) {
- if (AdjustLocalFileName(local))
- goto xx;
- }
-
- file_size = -1;
- if (filetype == IS_FILE)
- file_size = GetDateAndSize(remote, (unsigned long *) &remfTime);
-
- if (initconn())
- goto xx;
-
- oldtype = SetToAsciiForLS(is_retr, curtype);
-
- /* Issue the NLST command but don't wait for the reply. Some FTP
- * servers make the data connection before issuing the
- * "150 Opening ASCII mode data connection for /bin/ls" reply.
- */
- if (IssueCommand(cmd, remote))
- goto xx;
-
- if ((fout = OpenOutputFile(filetype, local, mode, &oldintp)) == NULL)
- goto xx;
-
- if ((din = dataconn("r")) == NULL)
- goto Abort;
-
- #ifdef TRY_NOREPLY
- /* Now get the reply we skipped above. */
- (void) getreply(0);
- #endif
-
- do_reports = NOT_VQUIET && is_retr && filetype == IS_FILE;
- if (do_reports)
- do_reports = start_progress(0, local);
-
- if (setjmp(recvabort)) {
- #ifdef TRY_ABOR
- goto Abort;
- #else
- /* Just read the rest of the stream without doing anything with
- * the results.
- */
- (void) Signal(SIGINT, SIG_IGN);
- (void) Signal(SIGPIPE, SIG_IGN); /* Don't bug us while aborting. */
- while (read(fileno(din), xferbuf, (int)xferbufsize) > 0)
- ;
- (void) fprintf(stderr, "\rAborted. \n");
- #endif
- } else {
- oldintr = Signal(SIGINT, abortrecv);
-
- if (curtype == TYPE_A)
- ReceiveAscii(din, fout, &do_reports, local, 1);
- else
- ReceiveBinary(din, fout, &do_reports, local);
- result = NOERR;
- /* Don't interrupt us now, since we finished successfully. */
- (void) Signal(SIGPIPE, SIG_IGN);
- (void) Signal(SIGINT, SIG_IGN);
- }
- CloseData();
- (void) getreply(0);
-
- goto xx;
-
- Abort:
-
- /* Abort using RFC959 recommended IP,SYNC sequence */
-
- (void) Signal(SIGPIPE, SIG_IGN); /* Don't bug us while aborting. */
- (void) Signal(SIGINT, SIG_IGN);
- if (!cpend || !cout) goto xx;
- (void) fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- msg = IAC;
- /* send IAC in urgent mode instead of DM because UNIX places oob mark */
- /* after urgent byte rather than before as now is protocol */
- if (send(fileno(cout),&msg,1,MSG_OOB) != 1)
- PERROR("recvrequest", "abort");
- (void) 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)
- PERROR("recvrequest", "abort");
- lostpeer(0);
- }
- if (din && FD_ISSET(fileno(din), &mask)) {
- while ((read(fileno(din), xferbuf, xferbufsize)) > 0)
- ;
- }
- if ((getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
- CloseData();
- (void) getreply(0);
- }
- (void) getreply(0);
- result = -1;
- CloseData();
-
- xx:
- CloseOutputFile(fout, filetype, local, remfTime);
- dbprintf("outfile closed.\n");
- if (din)
- (void) fclose(din);
- if (is_retr)
- end_progress("received", local, remote);
- if (oldintr)
- (void) Signal(SIGINT, oldintr);
- if (oldintp)
- (void) Signal(SIGPIPE, oldintp);
- dbprintf("recvrequest result = %d.\n", result);
- if (oldtype >= 0)
- ResetOldType(oldtype);
- bytes = 0L;
- return (result);
- } /* recvrequest */
-
-
-
-
- /*
- * Need to start a listen on the data channel
- * before we send the command, otherwise the
- * server's connect may fail.
- */
-
- #ifdef TERM_FTP
-
-
- /*
- * Need to request that the server go into passive mode and then get the
- * address and port for the term server to connect to.
- */
- int initconn(void)
- {
- int result;
- int n[6];
- int s;
-
- if (data != -1)
- (void) close(data);
- result = command("PASV");
- if (result == COMPLETE) {
- if (sscanf(reply_string, "%*[^(](%d,%d,%d,%d,%d,%d)",
- &n[0], &n[1], &n[2], &n[3], &n[4], &n[5]) != 6) {
- printf("Cannot parse PASV response: %s\n",
- reply_string);
- return 1;
- }
- close(data);
- lcompression = rcompression = compress_toggle;
- if ((s = connect_server(0)) < 0) {
- perror("ftp: connect to term server");
- data = -1;
- return 1;
- }
- data = s;
- send_command(s, C_PORT, 0, "%d.%d.%d.%d:%d",
- n[0], n[1], n[2], n[3], 256 * n[4] + n[5]);
- send_command(s, C_COMPRESS, 1, "n");
- send_command(s, C_DUMB, 1, 0);
- return 0;
- }
- return 1;
- } /* initconn_term */
-
-
-
-
- FILE *dataconn(char *lmode)
- {
- return (safeopen(data, lmode));
- } /* dataconn_term */
- #else /* not TERM_FTP */
-
-
- int initconn(void)
- {
- register char *p, *a;
- int result, len, tmpno = 0;
- int on = 1, rval;
- string str;
- Sig_t oldintr;
- #ifdef PASSIVEMODE
- int a1, a2, a3, a4, p1, p2;
- unsigned char n[6];
- #endif
-
- oldintr = Signal(SIGINT, SIG_IGN);
-
- #ifdef PASSIVEMODE
- if (passivemode) {
- data = socket(AF_INET, SOCK_STREAM, 0);
- if (data < 0) {
- PERROR("initconn", "socket");
- rval = 1;
- goto Return;
- }
- if (options & SO_DEBUG &&
- setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)) < 0 ) {
- PERROR("initconn", "setscokopt (ignored)");
- }
- result = command("PASV");
- if (result != COMPLETE) {
- printf("Passive mode refused.\n");
- rval = 1;
- goto Return;
- }
- /*
- * What we've got here is a string of comma separated one-byte
- * unsigned integer values. The first four are the IP address,
- * the fifth is the MSB of the port address, and the sixth is the
- * LSB of the port address. Extract this data and prepare a
- * 'data_addr' (struct sockaddr_in).
- */
- if (sscanf(reply_string+27, "%d,%d,%d,%d,%d,%d",
- &a1, &a2, &a3, &a4, &p1, &p2) != 6) {
- printf("Cannot parse PASV response: %s\n", reply_string);
- rval = 1;
- goto Return;
- }
- n[0] = (unsigned char) a1;
- n[1] = (unsigned char) a2;
- n[2] = (unsigned char) a3;
- n[3] = (unsigned char) a4;
- n[4] = (unsigned char) p1;
- n[5] = (unsigned char) p2;
-
- data_addr.sin_family = AF_INET;
- bcopy( (void *)&n[0], (void *)&data_addr.sin_addr, 4 );
- bcopy( (void *)&n[4], (void *)&data_addr.sin_port, 2 );
-
- if (Connect( data, &data_addr, sizeof(data_addr) ) < 0 ) {
- PERROR("initconn", "connect");
- rval = 1;
- goto Return;
- }
- rval = 0;
- goto Return;
- }
- #endif
-
- noport:
- data_addr = myctladdr;
- if (sendport)
- data_addr.sin_port = 0; /* let system pick one */
- if (data != -1)
- (void) close (data);
- data = socket(AF_INET, SOCK_STREAM, 0);
- if (data < 0) {
- PERROR("initconn", "socket");
- if (tmpno)
- sendport = 1;
- rval = 1; goto Return;
- }
- if (!sendport)
- if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
- PERROR("initconn", "setsockopt (reuse address)");
- goto bad;
- }
- #ifdef SOCKS
- if (Rbind(data, (struct sockaddr *)&data_addr, sizeof (data_addr), hisctladdr.sin_addr.s_addr) < 0) {
- #else
- if (Bind(data, &data_addr, sizeof (data_addr)) < 0) {
- #endif
- PERROR("initconn", "bind");
- goto bad;
- }
- #ifdef LINGER /* If puts don't complete, you could try this. */
- {
- struct linger li;
- li.l_onoff = 1;
- li.l_linger = 900;
-
- if (setsockopt(data, SOL_SOCKET, SO_LINGER,
- (char *)&li, sizeof(struct linger)) < 0)
- {
- PERROR("initconn", "setsockopt(SO_LINGER)");
- }
- }
- #endif /* LINGER */
-
- #ifdef IPTOS_THROUGHPUT /* transfers are background */
- #ifdef IP_TOS
- {
- int nType = IPTOS_THROUGHPUT;
- if (setsockopt(data, IPPROTO_IP, IP_TOS,
- (char *) &nType, sizeof(nType)) < 0) {
- PERROR("initconn", "setsockopt(IP_TOS)");
- }
- }
- #endif
- #endif
-
- if (options & SO_DEBUG &&
- setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
- PERROR("initconn", "setsockopt (ignored)");
- len = sizeof (data_addr);
- if (Getsockname(data, (char *)&data_addr, &len) < 0) {
- PERROR("initconn", "getsockname");
- goto bad;
- }
-
- #ifdef SOCKS
- if (Rlisten(data, 1) < 0)
- #else
- if (listen(data, 1) < 0)
- #endif
- PERROR("initconn", "listen");
- if (sendport) {
- a = (char *)&data_addr.sin_addr;
- p = (char *)&data_addr.sin_port;
- #define UC(x) (int) (((int) x) & 0xff)
- (void) sprintf(str, "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]));
- result = command(str);
- if (result == ERROR && sendport == -1) {
- sendport = 0;
- tmpno = 1;
- goto noport;
- }
- rval = (result != COMPLETE); goto Return;
- }
- if (tmpno)
- sendport = 1;
- rval = 0; goto Return;
- bad:
- (void) close(data), data = -1;
- if (tmpno)
- sendport = 1;
- rval = 1;
- Return:
- (void) Signal(SIGINT, oldintr);
- return (rval);
- } /* initconn */
-
-
-
-
- FILE *
- dataconn(char *mode)
- {
- struct sockaddr_in from;
- FILE *fp;
- int s, fromlen = sizeof (from);
-
- #ifdef SOCKS
- s = Raccept(data, (struct sockaddr *) &from, &fromlen);
- #else
- #ifdef PASSIVEMODE
- if (passivemode)
- return( fdopen( data, mode ));
- #endif
- s = Accept(data, &from, &fromlen);
- #endif
- if (s < 0) {
- PERROR("dataconn", "accept");
- (void) close(data), data = -1;
- fp = NULL;
- } else {
- (void) close(data);
- data = s;
- fp = safeopen(data, mode);
- }
- return (fp);
- } /* dataconn */
- #endif
-
- /* eof ftp.c */
-