155682Smarkm/* 255682Smarkm * Copyright (c) 1985, 1989, 1993, 1994 355682Smarkm * The Regents of the University of California. All rights reserved. 455682Smarkm * 555682Smarkm * Redistribution and use in source and binary forms, with or without 655682Smarkm * modification, are permitted provided that the following conditions 755682Smarkm * are met: 855682Smarkm * 1. Redistributions of source code must retain the above copyright 955682Smarkm * notice, this list of conditions and the following disclaimer. 1055682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer in the 1255682Smarkm * documentation and/or other materials provided with the distribution. 1355682Smarkm * 3. All advertising materials mentioning features or use of this software 1455682Smarkm * must display the following acknowledgement: 1555682Smarkm * This product includes software developed by the University of 1655682Smarkm * California, Berkeley and its contributors. 1755682Smarkm * 4. Neither the name of the University nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "ftp_locl.h" 35233294SstasRCSID ("$Id$"); 3655682Smarkm 3755682Smarkmstruct sockaddr_storage hisctladdr_ss; 3855682Smarkmstruct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss; 3955682Smarkmstruct sockaddr_storage data_addr_ss; 4055682Smarkmstruct sockaddr *data_addr = (struct sockaddr *)&data_addr_ss; 4155682Smarkmstruct sockaddr_storage myctladdr_ss; 4255682Smarkmstruct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss; 4355682Smarkmint data = -1; 4455682Smarkmint abrtflag = 0; 4555682Smarkmjmp_buf ptabort; 4655682Smarkmint ptabflg; 4755682Smarkmint ptflag = 0; 4855682Smarkmoff_t restart_point = 0; 4955682Smarkm 5055682Smarkm 5155682SmarkmFILE *cin, *cout; 5255682Smarkm 5355682Smarkmtypedef void (*sighand) (int); 5455682Smarkm 5555682Smarkmchar * 5655682Smarkmhookup (const char *host, int port) 5755682Smarkm{ 5855682Smarkm static char hostnamebuf[MaxHostNameLen]; 5955682Smarkm struct addrinfo *ai, *a; 6055682Smarkm struct addrinfo hints; 6155682Smarkm int error; 6255682Smarkm char portstr[NI_MAXSERV]; 6372445Sassar socklen_t len; 6455682Smarkm int s; 6555682Smarkm 6655682Smarkm memset (&hints, 0, sizeof(hints)); 6755682Smarkm hints.ai_socktype = SOCK_STREAM; 6855682Smarkm hints.ai_protocol = IPPROTO_TCP; 6955682Smarkm hints.ai_flags = AI_CANONNAME; 7055682Smarkm 7155682Smarkm snprintf (portstr, sizeof(portstr), "%u", ntohs(port)); 7255682Smarkm 7355682Smarkm error = getaddrinfo (host, portstr, &hints, &ai); 7455682Smarkm if (error) { 7555682Smarkm warnx ("%s: %s", host, gai_strerror(error)); 7655682Smarkm code = -1; 7755682Smarkm return NULL; 7855682Smarkm } 7955682Smarkm strlcpy (hostnamebuf, host, sizeof(hostnamebuf)); 8055682Smarkm hostname = hostnamebuf; 8155682Smarkm 82178825Sdfr s = -1; 8355682Smarkm for (a = ai; a != NULL; a = a->ai_next) { 8455682Smarkm s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 8555682Smarkm if (s < 0) 8655682Smarkm continue; 8755682Smarkm 8855682Smarkm if (a->ai_canonname != NULL) 8955682Smarkm strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf)); 9055682Smarkm 9155682Smarkm memcpy (hisctladdr, a->ai_addr, a->ai_addrlen); 92233294Sstas 9355682Smarkm error = connect (s, a->ai_addr, a->ai_addrlen); 9455682Smarkm if (error < 0) { 9555682Smarkm char addrstr[256]; 9655682Smarkm 9755682Smarkm if (getnameinfo (a->ai_addr, a->ai_addrlen, 9855682Smarkm addrstr, sizeof(addrstr), 9955682Smarkm NULL, 0, NI_NUMERICHOST) != 0) 10055682Smarkm strlcpy (addrstr, "unknown address", sizeof(addrstr)); 101233294Sstas 10255682Smarkm warn ("connect %s", addrstr); 10355682Smarkm close (s); 104178825Sdfr s = -1; 10555682Smarkm continue; 10655682Smarkm } 10755682Smarkm break; 10855682Smarkm } 10955682Smarkm freeaddrinfo (ai); 110178825Sdfr if (s < 0) { 11155682Smarkm warnx ("failed to contact %s", host); 11255682Smarkm code = -1; 11355682Smarkm return NULL; 11455682Smarkm } 11555682Smarkm 11655682Smarkm len = sizeof(myctladdr_ss); 11755682Smarkm if (getsockname (s, myctladdr, &len) < 0) { 11855682Smarkm warn ("getsockname"); 11955682Smarkm code = -1; 12055682Smarkm close (s); 12155682Smarkm return NULL; 12255682Smarkm } 12355682Smarkm#ifdef IPTOS_LOWDELAY 12455682Smarkm socket_set_tos (s, IPTOS_LOWDELAY); 12555682Smarkm#endif 12655682Smarkm cin = fdopen (s, "r"); 12755682Smarkm cout = fdopen (s, "w"); 12855682Smarkm if (cin == NULL || cout == NULL) { 12955682Smarkm warnx ("fdopen failed."); 13055682Smarkm if (cin) 13155682Smarkm fclose (cin); 13255682Smarkm if (cout) 13355682Smarkm fclose (cout); 13455682Smarkm code = -1; 13555682Smarkm goto bad; 13655682Smarkm } 13755682Smarkm if (verbose) 13855682Smarkm printf ("Connected to %s.\n", hostname); 13955682Smarkm if (getreply (0) > 2) { /* read startup message from server */ 14055682Smarkm if (cin) 14155682Smarkm fclose (cin); 14255682Smarkm if (cout) 14355682Smarkm fclose (cout); 14455682Smarkm code = -1; 14555682Smarkm goto bad; 14655682Smarkm } 14755682Smarkm#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) 14855682Smarkm { 14955682Smarkm int on = 1; 15055682Smarkm 15155682Smarkm if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on)) 15255682Smarkm < 0 && debug) { 15355682Smarkm warn ("setsockopt"); 15455682Smarkm } 15555682Smarkm } 15655682Smarkm#endif /* SO_OOBINLINE */ 15755682Smarkm 15855682Smarkm return (hostname); 15955682Smarkmbad: 16055682Smarkm close (s); 16155682Smarkm return NULL; 16255682Smarkm} 16355682Smarkm 16455682Smarkmint 16555682Smarkmlogin (char *host) 16655682Smarkm{ 16755682Smarkm char tmp[80]; 16855682Smarkm char defaultpass[128]; 169178825Sdfr char *userstr, *pass, *acctstr; 170233294Sstas char *ruserstr, *rpass, *racctstr; 17155682Smarkm int n, aflag = 0; 17255682Smarkm 17355682Smarkm char *myname = NULL; 17455682Smarkm struct passwd *pw = k_getpwuid(getuid()); 17555682Smarkm 17655682Smarkm if (pw != NULL) 17755682Smarkm myname = pw->pw_name; 17855682Smarkm 179233294Sstas ruserstr = rpass = racctstr = NULL; 18055682Smarkm 18155682Smarkm if(sec_login(host)) 18255682Smarkm printf("\n*** Using plaintext user and password ***\n\n"); 18355682Smarkm else{ 18455682Smarkm printf("Authentication successful.\n\n"); 18555682Smarkm } 18655682Smarkm 187233294Sstas if (ruserpassword (host, &ruserstr, &rpass, &racctstr) < 0) { 18855682Smarkm code = -1; 18955682Smarkm return (0); 19055682Smarkm } 191233294Sstas userstr = ruserstr; 192233294Sstas pass = rpass; 193233294Sstas acctstr = racctstr; 194233294Sstas 195178825Sdfr while (userstr == NULL) { 19655682Smarkm if (myname) 19755682Smarkm printf ("Name (%s:%s): ", host, myname); 19855682Smarkm else 19955682Smarkm printf ("Name (%s): ", host); 20072445Sassar *tmp = '\0'; 20172445Sassar if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL) 20272445Sassar tmp[strlen (tmp) - 1] = '\0'; 20355682Smarkm if (*tmp == '\0') 204178825Sdfr userstr = myname; 20555682Smarkm else 206178825Sdfr userstr = tmp; 20755682Smarkm } 208178825Sdfr strlcpy(username, userstr, sizeof(username)); 209233294Sstas if (ruserstr) 210233294Sstas free(ruserstr); 211233294Sstas 212178825Sdfr n = command("USER %s", userstr); 213233294Sstas if (n == COMPLETE) 21472445Sassar n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */ 21572445Sassar else if(n == CONTINUE) { 21672445Sassar if (pass == NULL) { 21755682Smarkm char prompt[128]; 218233294Sstas if(myname && 219178825Sdfr (!strcmp(userstr, "ftp") || !strcmp(userstr, "anonymous"))) { 220233294Sstas snprintf(defaultpass, sizeof(defaultpass), 22155682Smarkm "%s@%s", myname, mydomain); 222233294Sstas snprintf(prompt, sizeof(prompt), 22355682Smarkm "Password (%s): ", defaultpass); 22472445Sassar } else if (sec_complete) { 22572445Sassar pass = myname; 22672445Sassar } else { 22755682Smarkm *defaultpass = '\0'; 22855682Smarkm snprintf(prompt, sizeof(prompt), "Password: "); 22955682Smarkm } 23072445Sassar if (pass == NULL) { 23172445Sassar pass = defaultpass; 232178825Sdfr UI_UTIL_read_pw_string (tmp, sizeof (tmp), prompt, 0); 23372445Sassar if (tmp[0]) 23472445Sassar pass = tmp; 23572445Sassar } 23655682Smarkm } 23755682Smarkm n = command ("PASS %s", pass); 238233294Sstas if (rpass) 239233294Sstas free(rpass); 24055682Smarkm } 24155682Smarkm if (n == CONTINUE) { 24255682Smarkm aflag++; 243233294Sstas UI_UTIL_read_pw_string (tmp, sizeof(tmp), "Account:", 0); 244178825Sdfr acctstr = tmp; 245178825Sdfr n = command ("ACCT %s", acctstr); 24655682Smarkm } 24755682Smarkm if (n != COMPLETE) { 248233294Sstas if (racctstr) 249233294Sstas free(racctstr); 25055682Smarkm warnx ("Login failed."); 25155682Smarkm return (0); 25255682Smarkm } 253178825Sdfr if (!aflag && acctstr != NULL) 254178825Sdfr command ("ACCT %s", acctstr); 255233294Sstas if (racctstr) 256233294Sstas free(racctstr); 25755682Smarkm if (proxy) 25855682Smarkm return (1); 25955682Smarkm for (n = 0; n < macnum; ++n) { 26055682Smarkm if (!strcmp("init", macros[n].mac_name)) { 26155682Smarkm strlcpy (line, "$init", sizeof (line)); 26255682Smarkm makeargv(); 26355682Smarkm domacro(margc, margv); 26455682Smarkm break; 26555682Smarkm } 26655682Smarkm } 26755682Smarkm sec_set_protection_level (); 26855682Smarkm return (1); 26955682Smarkm} 27055682Smarkm 27155682Smarkmvoid 27255682Smarkmcmdabort (int sig) 27355682Smarkm{ 27455682Smarkm 27555682Smarkm printf ("\n"); 27655682Smarkm fflush (stdout); 27755682Smarkm abrtflag++; 27855682Smarkm if (ptflag) 27955682Smarkm longjmp (ptabort, 1); 28055682Smarkm} 28155682Smarkm 28255682Smarkmint 28355682Smarkmcommand (char *fmt,...) 28455682Smarkm{ 28555682Smarkm va_list ap; 28655682Smarkm int r; 28755682Smarkm sighand oldintr; 28855682Smarkm 28955682Smarkm abrtflag = 0; 29055682Smarkm if (cout == NULL) { 29155682Smarkm warn ("No control connection for command"); 29255682Smarkm code = -1; 29355682Smarkm return (0); 29455682Smarkm } 29555682Smarkm oldintr = signal(SIGINT, cmdabort); 29655682Smarkm if(debug){ 29755682Smarkm printf("---> "); 29855682Smarkm if (strncmp("PASS ", fmt, 5) == 0) 29955682Smarkm printf("PASS XXXX"); 300102644Snectar else { 301102644Snectar va_start(ap, fmt); 30255682Smarkm vfprintf(stdout, fmt, ap); 303102644Snectar va_end(ap); 304102644Snectar } 30555682Smarkm } 306102644Snectar va_start(ap, fmt); 30755682Smarkm sec_vfprintf(cout, fmt, ap); 30855682Smarkm va_end(ap); 30955682Smarkm if(debug){ 31055682Smarkm printf("\n"); 31155682Smarkm fflush(stdout); 31255682Smarkm } 31355682Smarkm fprintf (cout, "\r\n"); 31455682Smarkm fflush (cout); 31555682Smarkm cpend = 1; 31655682Smarkm r = getreply (!strcmp (fmt, "QUIT")); 31755682Smarkm if (abrtflag && oldintr != SIG_IGN) 31855682Smarkm (*oldintr) (SIGINT); 31955682Smarkm signal (SIGINT, oldintr); 32055682Smarkm return (r); 32155682Smarkm} 32255682Smarkm 32355682Smarkmchar reply_string[BUFSIZ]; /* last line of previous reply */ 32455682Smarkm 32555682Smarkmint 32655682Smarkmgetreply (int expecteof) 32755682Smarkm{ 32855682Smarkm char *p; 32955682Smarkm char *lead_string; 33055682Smarkm int c; 33155682Smarkm struct sigaction sa, osa; 332102644Snectar char buf[8192]; 333102644Snectar int reply_code; 334102644Snectar int long_warn = 0; 33555682Smarkm 33655682Smarkm sigemptyset (&sa.sa_mask); 33755682Smarkm sa.sa_flags = 0; 33855682Smarkm sa.sa_handler = cmdabort; 33955682Smarkm sigaction (SIGINT, &sa, &osa); 34055682Smarkm 34155682Smarkm p = buf; 34255682Smarkm 343102644Snectar reply_code = 0; 34455682Smarkm while (1) { 34555682Smarkm c = getc (cin); 34655682Smarkm switch (c) { 34755682Smarkm case EOF: 34855682Smarkm if (expecteof) { 34955682Smarkm sigaction (SIGINT, &osa, NULL); 35055682Smarkm code = 221; 35155682Smarkm return 0; 35255682Smarkm } 35355682Smarkm lostpeer (0); 35455682Smarkm if (verbose) { 35555682Smarkm printf ("421 Service not available, " 35655682Smarkm "remote server has closed connection\n"); 35755682Smarkm fflush (stdout); 35855682Smarkm } 35955682Smarkm code = 421; 36055682Smarkm return (4); 36155682Smarkm case IAC: 36255682Smarkm c = getc (cin); 36355682Smarkm if (c == WILL || c == WONT) 36455682Smarkm fprintf (cout, "%c%c%c", IAC, DONT, getc (cin)); 36555682Smarkm if (c == DO || c == DONT) 36655682Smarkm fprintf (cout, "%c%c%c", IAC, WONT, getc (cin)); 36755682Smarkm continue; 36855682Smarkm case '\n': 36955682Smarkm *p++ = '\0'; 370178825Sdfr if(isdigit((unsigned char)buf[0])){ 37155682Smarkm sscanf(buf, "%d", &code); 37255682Smarkm if(code == 631){ 373102644Snectar code = 0; 37455682Smarkm sec_read_msg(buf, prot_safe); 37555682Smarkm sscanf(buf, "%d", &code); 37655682Smarkm lead_string = "S:"; 37755682Smarkm } else if(code == 632){ 378102644Snectar code = 0; 37955682Smarkm sec_read_msg(buf, prot_private); 38055682Smarkm sscanf(buf, "%d", &code); 38155682Smarkm lead_string = "P:"; 38255682Smarkm }else if(code == 633){ 383102644Snectar code = 0; 38455682Smarkm sec_read_msg(buf, prot_confidential); 38555682Smarkm sscanf(buf, "%d", &code); 38655682Smarkm lead_string = "C:"; 38755682Smarkm }else if(sec_complete) 38855682Smarkm lead_string = "!!"; 38955682Smarkm else 39055682Smarkm lead_string = ""; 391102644Snectar if(code != 0 && reply_code == 0) 392102644Snectar reply_code = code; 39355682Smarkm if (verbose > 0 || (verbose > -1 && code > 499)) 39455682Smarkm fprintf (stdout, "%s%s\n", lead_string, buf); 395102644Snectar if (code == reply_code && buf[3] == ' ') { 396102644Snectar strlcpy (reply_string, buf, sizeof(reply_string)); 39755682Smarkm if (code >= 200) 39855682Smarkm cpend = 0; 39955682Smarkm sigaction (SIGINT, &osa, NULL); 40055682Smarkm if (code == 421) 40155682Smarkm lostpeer (0); 40255682Smarkm#if 1 40355682Smarkm if (abrtflag && 40455682Smarkm osa.sa_handler != cmdabort && 40555682Smarkm osa.sa_handler != SIG_IGN) 40655682Smarkm osa.sa_handler (SIGINT); 40755682Smarkm#endif 40855682Smarkm if (code == 227 || code == 229) { 409178825Sdfr char *q; 41055682Smarkm 411178825Sdfr q = strchr (reply_string, '('); 412178825Sdfr if (q) { 413178825Sdfr q++; 414178825Sdfr strlcpy(pasv, q, sizeof(pasv)); 415178825Sdfr q = strrchr(pasv, ')'); 416178825Sdfr if (q) 417178825Sdfr *q = '\0'; 41855682Smarkm } 41955682Smarkm } 42055682Smarkm return code / 100; 42155682Smarkm } 42255682Smarkm }else{ 42355682Smarkm if(verbose > 0 || (verbose > -1 && code > 499)){ 42455682Smarkm if(sec_complete) 42555682Smarkm fprintf(stdout, "!!"); 42655682Smarkm fprintf(stdout, "%s\n", buf); 42755682Smarkm } 42855682Smarkm } 42955682Smarkm p = buf; 430102644Snectar long_warn = 0; 43155682Smarkm continue; 43255682Smarkm default: 433102644Snectar if(p < buf + sizeof(buf) - 1) 434233294Sstas *p++ = c; 435102644Snectar else if(long_warn == 0) { 436102644Snectar fprintf(stderr, "WARNING: incredibly long line received\n"); 437102644Snectar long_warn = 1; 438102644Snectar } 43955682Smarkm } 44055682Smarkm } 44155682Smarkm 44255682Smarkm} 44355682Smarkm 44455682Smarkm 44555682Smarkm#if 0 44655682Smarkmint 44755682Smarkmgetreply (int expecteof) 44855682Smarkm{ 44955682Smarkm int c, n; 45055682Smarkm int dig; 45155682Smarkm int originalcode = 0, continuation = 0; 45255682Smarkm sighand oldintr; 45355682Smarkm int pflag = 0; 45455682Smarkm char *cp, *pt = pasv; 45555682Smarkm 45655682Smarkm oldintr = signal (SIGINT, cmdabort); 45755682Smarkm for (;;) { 45855682Smarkm dig = n = code = 0; 45955682Smarkm cp = reply_string; 46055682Smarkm while ((c = getc (cin)) != '\n') { 46155682Smarkm if (c == IAC) { /* handle telnet commands */ 46255682Smarkm switch (c = getc (cin)) { 46355682Smarkm case WILL: 46455682Smarkm case WONT: 46555682Smarkm c = getc (cin); 46655682Smarkm fprintf (cout, "%c%c%c", IAC, DONT, c); 46755682Smarkm fflush (cout); 46855682Smarkm break; 46955682Smarkm case DO: 47055682Smarkm case DONT: 47155682Smarkm c = getc (cin); 47255682Smarkm fprintf (cout, "%c%c%c", IAC, WONT, c); 47355682Smarkm fflush (cout); 47455682Smarkm break; 47555682Smarkm default: 47655682Smarkm break; 47755682Smarkm } 47855682Smarkm continue; 47955682Smarkm } 48055682Smarkm dig++; 48155682Smarkm if (c == EOF) { 48255682Smarkm if (expecteof) { 48355682Smarkm signal (SIGINT, oldintr); 48455682Smarkm code = 221; 48555682Smarkm return (0); 48655682Smarkm } 48755682Smarkm lostpeer (0); 48855682Smarkm if (verbose) { 48955682Smarkm printf ("421 Service not available, remote server has closed connection\n"); 49055682Smarkm fflush (stdout); 49155682Smarkm } 49255682Smarkm code = 421; 49355682Smarkm return (4); 49455682Smarkm } 49555682Smarkm if (c != '\r' && (verbose > 0 || 49655682Smarkm (verbose > -1 && n == '5' && dig > 4))) { 49755682Smarkm if (proxflag && 49855682Smarkm (dig == 1 || dig == 5 && verbose == 0)) 49955682Smarkm printf ("%s:", hostname); 50055682Smarkm putchar (c); 50155682Smarkm } 50255682Smarkm if (dig < 4 && isdigit (c)) 50355682Smarkm code = code * 10 + (c - '0'); 50455682Smarkm if (!pflag && code == 227) 50555682Smarkm pflag = 1; 50655682Smarkm if (dig > 4 && pflag == 1 && isdigit (c)) 50755682Smarkm pflag = 2; 50855682Smarkm if (pflag == 2) { 50955682Smarkm if (c != '\r' && c != ')') 51055682Smarkm *pt++ = c; 51155682Smarkm else { 51255682Smarkm *pt = '\0'; 51355682Smarkm pflag = 3; 51455682Smarkm } 51555682Smarkm } 51655682Smarkm if (dig == 4 && c == '-') { 51755682Smarkm if (continuation) 51855682Smarkm code = 0; 51955682Smarkm continuation++; 52055682Smarkm } 52155682Smarkm if (n == 0) 52255682Smarkm n = c; 52355682Smarkm if (cp < &reply_string[sizeof (reply_string) - 1]) 52455682Smarkm *cp++ = c; 52555682Smarkm } 52655682Smarkm if (verbose > 0 || verbose > -1 && n == '5') { 52755682Smarkm putchar (c); 52855682Smarkm fflush (stdout); 52955682Smarkm } 53055682Smarkm if (continuation && code != originalcode) { 53155682Smarkm if (originalcode == 0) 53255682Smarkm originalcode = code; 53355682Smarkm continue; 53455682Smarkm } 53555682Smarkm *cp = '\0'; 53655682Smarkm if(sec_complete){ 53755682Smarkm if(code == 631) 53855682Smarkm sec_read_msg(reply_string, prot_safe); 53955682Smarkm else if(code == 632) 54055682Smarkm sec_read_msg(reply_string, prot_private); 54155682Smarkm else if(code == 633) 54255682Smarkm sec_read_msg(reply_string, prot_confidential); 54355682Smarkm n = code / 100 + '0'; 54455682Smarkm } 54555682Smarkm if (n != '1') 54655682Smarkm cpend = 0; 54755682Smarkm signal (SIGINT, oldintr); 54855682Smarkm if (code == 421 || originalcode == 421) 54955682Smarkm lostpeer (0); 55055682Smarkm if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 55155682Smarkm (*oldintr) (SIGINT); 55255682Smarkm return (n - '0'); 55355682Smarkm } 55455682Smarkm} 55555682Smarkm 55655682Smarkm#endif 55755682Smarkm 55855682Smarkmint 55955682Smarkmempty (fd_set * mask, int sec) 56055682Smarkm{ 56155682Smarkm struct timeval t; 56255682Smarkm 56372445Sassar t.tv_sec = sec; 56455682Smarkm t.tv_usec = 0; 56572445Sassar return (select (FD_SETSIZE, mask, NULL, NULL, &t)); 56655682Smarkm} 56755682Smarkm 56855682Smarkmjmp_buf sendabort; 56955682Smarkm 57055682Smarkmstatic RETSIGTYPE 57155682Smarkmabortsend (int sig) 57255682Smarkm{ 57355682Smarkm 57455682Smarkm mflag = 0; 57555682Smarkm abrtflag = 0; 57655682Smarkm printf ("\nsend aborted\nwaiting for remote to finish abort\n"); 57755682Smarkm fflush (stdout); 57855682Smarkm longjmp (sendabort, 1); 57955682Smarkm} 58055682Smarkm 58155682Smarkm#define HASHBYTES 1024 58255682Smarkm 58355682Smarkmstatic int 58455682Smarkmcopy_stream (FILE * from, FILE * to) 58555682Smarkm{ 58655682Smarkm static size_t bufsize; 58755682Smarkm static char *buf; 58855682Smarkm int n; 58955682Smarkm int bytes = 0; 59055682Smarkm int werr = 0; 59155682Smarkm int hashbytes = HASHBYTES; 59255682Smarkm struct stat st; 59355682Smarkm 59455682Smarkm#if defined(HAVE_MMAP) && !defined(NO_MMAP) 59555682Smarkm void *chunk; 596233294Sstas size_t off; 59755682Smarkm 598233294Sstas#define BLOCKSIZE (1024 * 1024 * 10) 599233294Sstas 60055682Smarkm#ifndef MAP_FAILED 60155682Smarkm#define MAP_FAILED (-1) 60255682Smarkm#endif 60355682Smarkm 60455682Smarkm if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) { 60555682Smarkm /* 60655682Smarkm * mmap zero bytes has potential of loosing, don't do it. 60755682Smarkm */ 60855682Smarkm if (st.st_size == 0) 60955682Smarkm return 0; 610233294Sstas off = 0; 611233294Sstas while (off != st.st_size) { 612233294Sstas size_t len; 613233294Sstas ssize_t res; 61455682Smarkm 615233294Sstas len = st.st_size - off; 616233294Sstas if (len > BLOCKSIZE) 617233294Sstas len = BLOCKSIZE; 618233294Sstas 619233294Sstas chunk = mmap (0, len, PROT_READ, MAP_SHARED, fileno (from), off); 620233294Sstas if (chunk == (void *) MAP_FAILED) { 621233294Sstas if (off == 0) /* try read if mmap doesn't work */ 622233294Sstas goto try_read; 623233294Sstas break; 624233294Sstas } 625233294Sstas 626233294Sstas res = sec_write (fileno (to), chunk, len); 627233294Sstas if (msync (chunk, len, MS_ASYNC)) 628233294Sstas warn ("msync"); 629233294Sstas if (munmap (chunk, len) < 0) 63055682Smarkm warn ("munmap"); 63155682Smarkm sec_fflush (to); 632233294Sstas if (res != len) 633233294Sstas return off; 634233294Sstas off += len; 63555682Smarkm } 636233294Sstas return off; 63755682Smarkm } 638233294Sstastry_read: 63955682Smarkm#endif 64055682Smarkm 64155682Smarkm buf = alloc_buffer (buf, &bufsize, 64255682Smarkm fstat (fileno (from), &st) >= 0 ? &st : NULL); 64355682Smarkm if (buf == NULL) 64455682Smarkm return -1; 64555682Smarkm 64655682Smarkm while ((n = read (fileno (from), buf, bufsize)) > 0) { 64755682Smarkm werr = sec_write (fileno (to), buf, n); 64855682Smarkm if (werr < 0) 64955682Smarkm break; 65055682Smarkm bytes += werr; 65155682Smarkm while (hash && bytes > hashbytes) { 65255682Smarkm putchar ('#'); 65355682Smarkm hashbytes += HASHBYTES; 65455682Smarkm } 65555682Smarkm } 65655682Smarkm sec_fflush (to); 65755682Smarkm if (n < 0) 65855682Smarkm warn ("local"); 65955682Smarkm 66055682Smarkm if (werr < 0) { 66155682Smarkm if (errno != EPIPE) 66255682Smarkm warn ("netout"); 66355682Smarkm bytes = -1; 66455682Smarkm } 66555682Smarkm return bytes; 66655682Smarkm} 66755682Smarkm 66855682Smarkmvoid 66955682Smarkmsendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames) 67055682Smarkm{ 67155682Smarkm struct stat st; 67255682Smarkm struct timeval start, stop; 67355682Smarkm int c, d; 67455682Smarkm FILE *fin, *dout = 0; 67555682Smarkm int (*closefunc) (FILE *); 67672445Sassar RETSIGTYPE (*oldintr)(int), (*oldintp)(int); 67755682Smarkm long bytes = 0, hashbytes = HASHBYTES; 67855682Smarkm char *rmode = "w"; 67955682Smarkm 68055682Smarkm if (verbose && printnames) { 681233294Sstas if (strcmp (local, "-") != 0) 68255682Smarkm printf ("local: %s ", local); 68355682Smarkm if (remote) 68455682Smarkm printf ("remote: %s\n", remote); 68555682Smarkm } 68655682Smarkm if (proxy) { 68755682Smarkm proxtrans (cmd, local, remote); 68855682Smarkm return; 68955682Smarkm } 69055682Smarkm if (curtype != type) 69155682Smarkm changetype (type, 0); 69255682Smarkm closefunc = NULL; 69355682Smarkm oldintr = NULL; 69455682Smarkm oldintp = NULL; 69555682Smarkm 69655682Smarkm if (setjmp (sendabort)) { 69755682Smarkm while (cpend) { 69855682Smarkm getreply (0); 69955682Smarkm } 70055682Smarkm if (data >= 0) { 70155682Smarkm close (data); 70255682Smarkm data = -1; 70355682Smarkm } 70455682Smarkm if (oldintr) 70555682Smarkm signal (SIGINT, oldintr); 70655682Smarkm if (oldintp) 70755682Smarkm signal (SIGPIPE, oldintp); 70855682Smarkm code = -1; 70955682Smarkm return; 71055682Smarkm } 71155682Smarkm oldintr = signal (SIGINT, abortsend); 71255682Smarkm if (strcmp (local, "-") == 0) 71355682Smarkm fin = stdin; 71455682Smarkm else if (*local == '|') { 71555682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 71655682Smarkm fin = popen (local + 1, lmode); 71755682Smarkm if (fin == NULL) { 71855682Smarkm warn ("%s", local + 1); 71955682Smarkm signal (SIGINT, oldintr); 72055682Smarkm signal (SIGPIPE, oldintp); 72155682Smarkm code = -1; 72255682Smarkm return; 72355682Smarkm } 72455682Smarkm closefunc = pclose; 72555682Smarkm } else { 72655682Smarkm fin = fopen (local, lmode); 72755682Smarkm if (fin == NULL) { 72855682Smarkm warn ("local: %s", local); 72955682Smarkm signal (SIGINT, oldintr); 73055682Smarkm code = -1; 73155682Smarkm return; 73255682Smarkm } 73355682Smarkm closefunc = fclose; 734233294Sstas if (fstat (fileno (fin), &st) < 0 || !S_ISREG(st.st_mode)) { 73555682Smarkm fprintf (stdout, "%s: not a plain file.\n", local); 73655682Smarkm signal (SIGINT, oldintr); 73755682Smarkm fclose (fin); 73855682Smarkm code = -1; 73955682Smarkm return; 74055682Smarkm } 74155682Smarkm } 74255682Smarkm if (initconn ()) { 74355682Smarkm signal (SIGINT, oldintr); 74455682Smarkm if (oldintp) 74555682Smarkm signal (SIGPIPE, oldintp); 74655682Smarkm code = -1; 74755682Smarkm if (closefunc != NULL) 74855682Smarkm (*closefunc) (fin); 74955682Smarkm return; 75055682Smarkm } 75155682Smarkm if (setjmp (sendabort)) 75255682Smarkm goto abort; 75355682Smarkm 75455682Smarkm if (restart_point && 75555682Smarkm (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) { 75655682Smarkm int rc; 75755682Smarkm 75855682Smarkm switch (curtype) { 75955682Smarkm case TYPE_A: 76055682Smarkm rc = fseek (fin, (long) restart_point, SEEK_SET); 76155682Smarkm break; 76255682Smarkm case TYPE_I: 76355682Smarkm case TYPE_L: 76455682Smarkm rc = lseek (fileno (fin), restart_point, SEEK_SET); 76555682Smarkm break; 766178825Sdfr default: 767178825Sdfr abort(); 76855682Smarkm } 76955682Smarkm if (rc < 0) { 77055682Smarkm warn ("local: %s", local); 77155682Smarkm restart_point = 0; 77255682Smarkm if (closefunc != NULL) 77355682Smarkm (*closefunc) (fin); 77455682Smarkm return; 77555682Smarkm } 77655682Smarkm if (command ("REST %ld", (long) restart_point) 77755682Smarkm != CONTINUE) { 77855682Smarkm restart_point = 0; 77955682Smarkm if (closefunc != NULL) 78055682Smarkm (*closefunc) (fin); 78155682Smarkm return; 78255682Smarkm } 78355682Smarkm restart_point = 0; 78455682Smarkm rmode = "r+w"; 78555682Smarkm } 78655682Smarkm if (remote) { 78755682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 78855682Smarkm signal (SIGINT, oldintr); 78955682Smarkm if (oldintp) 79055682Smarkm signal (SIGPIPE, oldintp); 79155682Smarkm if (closefunc != NULL) 79255682Smarkm (*closefunc) (fin); 79355682Smarkm return; 79455682Smarkm } 79555682Smarkm } else if (command ("%s", cmd) != PRELIM) { 79655682Smarkm signal(SIGINT, oldintr); 79755682Smarkm if (oldintp) 79855682Smarkm signal(SIGPIPE, oldintp); 79955682Smarkm if (closefunc != NULL) 80055682Smarkm (*closefunc)(fin); 80155682Smarkm return; 80255682Smarkm } 80355682Smarkm dout = dataconn(rmode); 80455682Smarkm if (dout == NULL) 80555682Smarkm goto abort; 80655682Smarkm set_buffer_size (fileno (dout), 0); 80755682Smarkm gettimeofday (&start, (struct timezone *) 0); 80855682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 80955682Smarkm switch (curtype) { 81055682Smarkm 81155682Smarkm case TYPE_I: 81255682Smarkm case TYPE_L: 81355682Smarkm errno = d = c = 0; 81455682Smarkm bytes = copy_stream (fin, dout); 81555682Smarkm break; 81655682Smarkm 81755682Smarkm case TYPE_A: 81855682Smarkm while ((c = getc (fin)) != EOF) { 81955682Smarkm if (c == '\n') { 82055682Smarkm while (hash && (bytes >= hashbytes)) { 82155682Smarkm putchar ('#'); 82255682Smarkm fflush (stdout); 82355682Smarkm hashbytes += HASHBYTES; 82455682Smarkm } 82555682Smarkm if (ferror (dout)) 82655682Smarkm break; 82755682Smarkm sec_putc ('\r', dout); 82855682Smarkm bytes++; 82955682Smarkm } 83055682Smarkm sec_putc (c, dout); 83155682Smarkm bytes++; 83255682Smarkm } 83355682Smarkm sec_fflush (dout); 83455682Smarkm if (hash) { 83555682Smarkm if (bytes < hashbytes) 83655682Smarkm putchar ('#'); 83755682Smarkm putchar ('\n'); 83855682Smarkm fflush (stdout); 83955682Smarkm } 84055682Smarkm if (ferror (fin)) 84155682Smarkm warn ("local: %s", local); 84255682Smarkm if (ferror (dout)) { 84355682Smarkm if (errno != EPIPE) 84455682Smarkm warn ("netout"); 84555682Smarkm bytes = -1; 84655682Smarkm } 84755682Smarkm break; 84855682Smarkm } 84955682Smarkm if (closefunc != NULL) 85055682Smarkm (*closefunc) (fin); 85155682Smarkm fclose (dout); 85255682Smarkm gettimeofday (&stop, (struct timezone *) 0); 85355682Smarkm getreply (0); 85455682Smarkm signal (SIGINT, oldintr); 85555682Smarkm if (oldintp) 85655682Smarkm signal (SIGPIPE, oldintp); 85755682Smarkm if (bytes > 0) 85855682Smarkm ptransfer ("sent", bytes, &start, &stop); 85955682Smarkm return; 86055682Smarkmabort: 86155682Smarkm signal (SIGINT, oldintr); 86255682Smarkm if (oldintp) 86355682Smarkm signal (SIGPIPE, oldintp); 86455682Smarkm if (!cpend) { 86555682Smarkm code = -1; 86655682Smarkm return; 86755682Smarkm } 86855682Smarkm if (data >= 0) { 86955682Smarkm close (data); 87055682Smarkm data = -1; 87155682Smarkm } 87255682Smarkm if (dout) 87355682Smarkm fclose (dout); 87455682Smarkm getreply (0); 87555682Smarkm code = -1; 87655682Smarkm if (closefunc != NULL && fin != NULL) 87755682Smarkm (*closefunc) (fin); 87855682Smarkm gettimeofday (&stop, (struct timezone *) 0); 87955682Smarkm if (bytes > 0) 88055682Smarkm ptransfer ("sent", bytes, &start, &stop); 88155682Smarkm} 88255682Smarkm 88355682Smarkmjmp_buf recvabort; 88455682Smarkm 88555682Smarkmvoid 88655682Smarkmabortrecv (int sig) 88755682Smarkm{ 88855682Smarkm 88955682Smarkm mflag = 0; 89055682Smarkm abrtflag = 0; 89155682Smarkm printf ("\nreceive aborted\nwaiting for remote to finish abort\n"); 89255682Smarkm fflush (stdout); 89355682Smarkm longjmp (recvabort, 1); 89455682Smarkm} 89555682Smarkm 89655682Smarkmvoid 89755682Smarkmrecvrequest (char *cmd, char *local, char *remote, 89855682Smarkm char *lmode, int printnames, int local_given) 89955682Smarkm{ 900178825Sdfr FILE *fout = NULL, *din = NULL; 90155682Smarkm int (*closefunc) (FILE *); 90255682Smarkm sighand oldintr, oldintp; 90355682Smarkm int c, d, is_retr, tcrflag, bare_lfs = 0; 90455682Smarkm static size_t bufsize; 90555682Smarkm static char *buf; 90655682Smarkm long bytes = 0, hashbytes = HASHBYTES; 90755682Smarkm struct timeval start, stop; 90855682Smarkm struct stat st; 90955682Smarkm 91055682Smarkm is_retr = strcmp (cmd, "RETR") == 0; 91155682Smarkm if (is_retr && verbose && printnames) { 912233294Sstas if (strcmp (local, "-") != 0) 91355682Smarkm printf ("local: %s ", local); 91455682Smarkm if (remote) 91555682Smarkm printf ("remote: %s\n", remote); 91655682Smarkm } 91755682Smarkm if (proxy && is_retr) { 91855682Smarkm proxtrans (cmd, local, remote); 91955682Smarkm return; 92055682Smarkm } 92155682Smarkm closefunc = NULL; 92255682Smarkm oldintr = NULL; 92355682Smarkm oldintp = NULL; 92455682Smarkm tcrflag = !crflag && is_retr; 92555682Smarkm if (setjmp (recvabort)) { 92655682Smarkm while (cpend) { 92755682Smarkm getreply (0); 92855682Smarkm } 92955682Smarkm if (data >= 0) { 93055682Smarkm close (data); 93155682Smarkm data = -1; 93255682Smarkm } 93355682Smarkm if (oldintr) 93455682Smarkm signal (SIGINT, oldintr); 93555682Smarkm code = -1; 93655682Smarkm return; 93755682Smarkm } 93855682Smarkm oldintr = signal (SIGINT, abortrecv); 939233294Sstas if (!local_given || (strcmp(local, "-") && *local != '|')) { 94055682Smarkm if (access (local, 2) < 0) { 94155682Smarkm char *dir = strrchr (local, '/'); 94255682Smarkm 94355682Smarkm if (errno != ENOENT && errno != EACCES) { 94455682Smarkm warn ("local: %s", local); 94555682Smarkm signal (SIGINT, oldintr); 94655682Smarkm code = -1; 94755682Smarkm return; 94855682Smarkm } 94955682Smarkm if (dir != NULL) 95055682Smarkm *dir = 0; 95155682Smarkm d = access (dir ? local : ".", 2); 95255682Smarkm if (dir != NULL) 95355682Smarkm *dir = '/'; 95455682Smarkm if (d < 0) { 95555682Smarkm warn ("local: %s", local); 95655682Smarkm signal (SIGINT, oldintr); 95755682Smarkm code = -1; 95855682Smarkm return; 95955682Smarkm } 96055682Smarkm if (!runique && errno == EACCES && 96155682Smarkm chmod (local, 0600) < 0) { 96255682Smarkm warn ("local: %s", local); 96355682Smarkm signal (SIGINT, oldintr); 96455682Smarkm signal (SIGINT, oldintr); 96555682Smarkm code = -1; 96655682Smarkm return; 96755682Smarkm } 96855682Smarkm if (runique && errno == EACCES && 96955682Smarkm (local = gunique (local)) == NULL) { 97055682Smarkm signal (SIGINT, oldintr); 97155682Smarkm code = -1; 97255682Smarkm return; 97355682Smarkm } 97455682Smarkm } else if (runique && (local = gunique (local)) == NULL) { 97555682Smarkm signal(SIGINT, oldintr); 97655682Smarkm code = -1; 97755682Smarkm return; 97855682Smarkm } 97955682Smarkm } 98055682Smarkm if (!is_retr) { 98155682Smarkm if (curtype != TYPE_A) 98255682Smarkm changetype (TYPE_A, 0); 98355682Smarkm } else if (curtype != type) 98455682Smarkm changetype (type, 0); 98555682Smarkm if (initconn ()) { 98655682Smarkm signal (SIGINT, oldintr); 98755682Smarkm code = -1; 98855682Smarkm return; 98955682Smarkm } 99055682Smarkm if (setjmp (recvabort)) 99155682Smarkm goto abort; 99255682Smarkm if (is_retr && restart_point && 99355682Smarkm command ("REST %ld", (long) restart_point) != CONTINUE) 99455682Smarkm return; 99555682Smarkm if (remote) { 99655682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 99755682Smarkm signal (SIGINT, oldintr); 99855682Smarkm return; 99955682Smarkm } 100055682Smarkm } else { 100155682Smarkm if (command ("%s", cmd) != PRELIM) { 100255682Smarkm signal (SIGINT, oldintr); 100355682Smarkm return; 100455682Smarkm } 100555682Smarkm } 100655682Smarkm din = dataconn ("r"); 100755682Smarkm if (din == NULL) 100855682Smarkm goto abort; 100955682Smarkm set_buffer_size (fileno (din), 1); 101055682Smarkm if (local_given && strcmp (local, "-") == 0) 101155682Smarkm fout = stdout; 101255682Smarkm else if (local_given && *local == '|') { 101355682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 101455682Smarkm fout = popen (local + 1, "w"); 101555682Smarkm if (fout == NULL) { 101655682Smarkm warn ("%s", local + 1); 101755682Smarkm goto abort; 101855682Smarkm } 101955682Smarkm closefunc = pclose; 102055682Smarkm } else { 102155682Smarkm fout = fopen (local, lmode); 102255682Smarkm if (fout == NULL) { 102355682Smarkm warn ("local: %s", local); 102455682Smarkm goto abort; 102555682Smarkm } 102655682Smarkm closefunc = fclose; 102755682Smarkm } 102855682Smarkm buf = alloc_buffer (buf, &bufsize, 102955682Smarkm fstat (fileno (fout), &st) >= 0 ? &st : NULL); 103055682Smarkm if (buf == NULL) 103155682Smarkm goto abort; 103255682Smarkm 103355682Smarkm gettimeofday (&start, (struct timezone *) 0); 103455682Smarkm switch (curtype) { 103555682Smarkm 103655682Smarkm case TYPE_I: 103755682Smarkm case TYPE_L: 103855682Smarkm if (restart_point && 103955682Smarkm lseek (fileno (fout), restart_point, SEEK_SET) < 0) { 104055682Smarkm warn ("local: %s", local); 104155682Smarkm if (closefunc != NULL) 104255682Smarkm (*closefunc) (fout); 104355682Smarkm return; 104455682Smarkm } 104555682Smarkm errno = d = 0; 104655682Smarkm while ((c = sec_read (fileno (din), buf, bufsize)) > 0) { 104755682Smarkm if ((d = write (fileno (fout), buf, c)) != c) 104855682Smarkm break; 104955682Smarkm bytes += c; 105055682Smarkm if (hash) { 105155682Smarkm while (bytes >= hashbytes) { 105255682Smarkm putchar ('#'); 105355682Smarkm hashbytes += HASHBYTES; 105455682Smarkm } 105555682Smarkm fflush (stdout); 105655682Smarkm } 105755682Smarkm } 105855682Smarkm if (hash && bytes > 0) { 105955682Smarkm if (bytes < HASHBYTES) 106055682Smarkm putchar ('#'); 106155682Smarkm putchar ('\n'); 106255682Smarkm fflush (stdout); 106355682Smarkm } 106455682Smarkm if (c < 0) { 106555682Smarkm if (errno != EPIPE) 106655682Smarkm warn ("netin"); 106755682Smarkm bytes = -1; 106855682Smarkm } 106955682Smarkm if (d < c) { 107055682Smarkm if (d < 0) 107155682Smarkm warn ("local: %s", local); 107255682Smarkm else 107355682Smarkm warnx ("%s: short write", local); 107455682Smarkm } 107555682Smarkm break; 107655682Smarkm 107755682Smarkm case TYPE_A: 107855682Smarkm if (restart_point) { 107955682Smarkm int i, n, ch; 108055682Smarkm 108155682Smarkm if (fseek (fout, 0L, SEEK_SET) < 0) 108255682Smarkm goto done; 108355682Smarkm n = restart_point; 108455682Smarkm for (i = 0; i++ < n;) { 108555682Smarkm if ((ch = sec_getc (fout)) == EOF) 108655682Smarkm goto done; 108755682Smarkm if (ch == '\n') 108855682Smarkm i++; 108955682Smarkm } 109055682Smarkm if (fseek (fout, 0L, SEEK_CUR) < 0) { 109155682Smarkm done: 109255682Smarkm warn ("local: %s", local); 109355682Smarkm if (closefunc != NULL) 109455682Smarkm (*closefunc) (fout); 109555682Smarkm return; 109655682Smarkm } 109755682Smarkm } 109855682Smarkm while ((c = sec_getc(din)) != EOF) { 109955682Smarkm if (c == '\n') 110055682Smarkm bare_lfs++; 110155682Smarkm while (c == '\r') { 110255682Smarkm while (hash && (bytes >= hashbytes)) { 110355682Smarkm putchar ('#'); 110455682Smarkm fflush (stdout); 110555682Smarkm hashbytes += HASHBYTES; 110655682Smarkm } 110755682Smarkm bytes++; 110855682Smarkm if ((c = sec_getc (din)) != '\n' || tcrflag) { 110955682Smarkm if (ferror (fout)) 111055682Smarkm goto break2; 111155682Smarkm putc ('\r', fout); 111255682Smarkm if (c == '\0') { 111355682Smarkm bytes++; 111455682Smarkm goto contin2; 111555682Smarkm } 111655682Smarkm if (c == EOF) 111755682Smarkm goto contin2; 111855682Smarkm } 111955682Smarkm } 112055682Smarkm putc (c, fout); 112155682Smarkm bytes++; 112255682Smarkm contin2:; 112355682Smarkm } 112455682Smarkmbreak2: 112555682Smarkm if (bare_lfs) { 112655682Smarkm printf ("WARNING! %d bare linefeeds received in ASCII mode\n", 112755682Smarkm bare_lfs); 112855682Smarkm printf ("File may not have transferred correctly.\n"); 112955682Smarkm } 113055682Smarkm if (hash) { 113155682Smarkm if (bytes < hashbytes) 113255682Smarkm putchar ('#'); 113355682Smarkm putchar ('\n'); 113455682Smarkm fflush (stdout); 113555682Smarkm } 113655682Smarkm if (ferror (din)) { 113755682Smarkm if (errno != EPIPE) 113855682Smarkm warn ("netin"); 113955682Smarkm bytes = -1; 114055682Smarkm } 114155682Smarkm if (ferror (fout)) 114255682Smarkm warn ("local: %s", local); 114355682Smarkm break; 114455682Smarkm } 114555682Smarkm if (closefunc != NULL) 114655682Smarkm (*closefunc) (fout); 114755682Smarkm signal (SIGINT, oldintr); 114855682Smarkm if (oldintp) 114955682Smarkm signal (SIGPIPE, oldintp); 115055682Smarkm fclose (din); 115155682Smarkm gettimeofday (&stop, (struct timezone *) 0); 115255682Smarkm getreply (0); 115355682Smarkm if (bytes > 0 && is_retr) 115455682Smarkm ptransfer ("received", bytes, &start, &stop); 115555682Smarkm return; 115655682Smarkmabort: 115755682Smarkm 115855682Smarkm /* abort using RFC959 recommended IP,SYNC sequence */ 115955682Smarkm 116055682Smarkm if (oldintp) 116155682Smarkm signal (SIGPIPE, oldintr); 116255682Smarkm signal (SIGINT, SIG_IGN); 116355682Smarkm if (!cpend) { 116455682Smarkm code = -1; 116555682Smarkm signal (SIGINT, oldintr); 116655682Smarkm return; 116755682Smarkm } 116855682Smarkm abort_remote(din); 116955682Smarkm code = -1; 117055682Smarkm if (data >= 0) { 117155682Smarkm close (data); 117255682Smarkm data = -1; 117355682Smarkm } 117455682Smarkm if (closefunc != NULL && fout != NULL) 117555682Smarkm (*closefunc) (fout); 117655682Smarkm if (din) 117755682Smarkm fclose (din); 117855682Smarkm gettimeofday (&stop, (struct timezone *) 0); 117955682Smarkm if (bytes > 0) 118055682Smarkm ptransfer ("received", bytes, &start, &stop); 118155682Smarkm signal (SIGINT, oldintr); 118255682Smarkm} 118355682Smarkm 118455682Smarkmstatic int 118555682Smarkmparse_epsv (const char *str) 118655682Smarkm{ 118755682Smarkm char sep; 118855682Smarkm char *end; 118955682Smarkm int port; 119055682Smarkm 119155682Smarkm if (*str == '\0') 119255682Smarkm return -1; 119355682Smarkm sep = *str++; 119455682Smarkm if (sep != *str++) 119555682Smarkm return -1; 119655682Smarkm if (sep != *str++) 119755682Smarkm return -1; 119855682Smarkm port = strtol (str, &end, 0); 119955682Smarkm if (str == end) 120055682Smarkm return -1; 120155682Smarkm if (end[0] != sep || end[1] != '\0') 120255682Smarkm return -1; 120355682Smarkm return htons(port); 120455682Smarkm} 120555682Smarkm 120655682Smarkmstatic int 1207178825Sdfrparse_pasv (struct sockaddr_in *sin4, const char *str) 120855682Smarkm{ 120955682Smarkm int a0, a1, a2, a3, p0, p1; 121055682Smarkm 121155682Smarkm /* 121255682Smarkm * What we've got at this point is a string of comma separated 121355682Smarkm * one-byte unsigned integer values. The first four are the an IP 121455682Smarkm * address. The fifth is the MSB of the port number, the sixth is the 121555682Smarkm * LSB. From that we'll prepare a sockaddr_in. 121655682Smarkm */ 121755682Smarkm 121855682Smarkm if (sscanf (str, "%d,%d,%d,%d,%d,%d", 121955682Smarkm &a0, &a1, &a2, &a3, &p0, &p1) != 6) { 122055682Smarkm printf ("Passive mode address scan failure. " 122155682Smarkm "Shouldn't happen!\n"); 122255682Smarkm return -1; 122355682Smarkm } 122455682Smarkm if (a0 < 0 || a0 > 255 || 122555682Smarkm a1 < 0 || a1 > 255 || 122655682Smarkm a2 < 0 || a2 > 255 || 122755682Smarkm a3 < 0 || a3 > 255 || 122855682Smarkm p0 < 0 || p0 > 255 || 122955682Smarkm p1 < 0 || p1 > 255) { 123055682Smarkm printf ("Can't parse passive mode string.\n"); 123155682Smarkm return -1; 123255682Smarkm } 1233178825Sdfr memset (sin4, 0, sizeof(*sin4)); 1234178825Sdfr sin4->sin_family = AF_INET; 1235178825Sdfr sin4->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) | 123655682Smarkm (a2 << 8) | a3); 1237178825Sdfr sin4->sin_port = htons ((p0 << 8) | p1); 123855682Smarkm return 0; 123955682Smarkm} 124055682Smarkm 124155682Smarkmstatic int 124255682Smarkmpassive_mode (void) 124355682Smarkm{ 124455682Smarkm int port; 124555682Smarkm 124655682Smarkm data = socket (myctladdr->sa_family, SOCK_STREAM, 0); 124755682Smarkm if (data < 0) { 124855682Smarkm warn ("socket"); 124955682Smarkm return (1); 125055682Smarkm } 125155682Smarkm if (options & SO_DEBUG) 125255682Smarkm socket_set_debug (data); 125355682Smarkm if (command ("EPSV") != COMPLETE) { 125455682Smarkm if (command ("PASV") != COMPLETE) { 125555682Smarkm printf ("Passive mode refused.\n"); 125655682Smarkm goto bad; 125755682Smarkm } 125855682Smarkm } 125955682Smarkm 126055682Smarkm /* 126155682Smarkm * Parse the reply to EPSV or PASV 126255682Smarkm */ 126355682Smarkm 126455682Smarkm port = parse_epsv (pasv); 126555682Smarkm if (port > 0) { 126655682Smarkm data_addr->sa_family = myctladdr->sa_family; 126755682Smarkm socket_set_address_and_port (data_addr, 126855682Smarkm socket_get_address (hisctladdr), 126955682Smarkm port); 127055682Smarkm } else { 127155682Smarkm if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0) 127255682Smarkm goto bad; 127355682Smarkm } 127455682Smarkm 127555682Smarkm if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) { 127655682Smarkm warn ("connect"); 127755682Smarkm goto bad; 127855682Smarkm } 127955682Smarkm#ifdef IPTOS_THROUGHPUT 128055682Smarkm socket_set_tos (data, IPTOS_THROUGHPUT); 128155682Smarkm#endif 128255682Smarkm return (0); 128355682Smarkmbad: 128455682Smarkm close (data); 128555682Smarkm data = -1; 128655682Smarkm sendport = 1; 128755682Smarkm return (1); 128855682Smarkm} 128955682Smarkm 129055682Smarkm 129155682Smarkmstatic int 129255682Smarkmactive_mode (void) 129355682Smarkm{ 129455682Smarkm int tmpno = 0; 129572445Sassar socklen_t len; 129655682Smarkm int result; 129755682Smarkm 129855682Smarkmnoport: 129955682Smarkm data_addr->sa_family = myctladdr->sa_family; 130055682Smarkm socket_set_address_and_port (data_addr, socket_get_address (myctladdr), 130155682Smarkm sendport ? 0 : socket_get_port (myctladdr)); 130255682Smarkm 130355682Smarkm if (data != -1) 130455682Smarkm close (data); 130555682Smarkm data = socket (data_addr->sa_family, SOCK_STREAM, 0); 130655682Smarkm if (data < 0) { 130755682Smarkm warn ("socket"); 130855682Smarkm if (tmpno) 130955682Smarkm sendport = 1; 131055682Smarkm return (1); 131155682Smarkm } 131255682Smarkm if (!sendport) 131355682Smarkm socket_set_reuseaddr (data, 1); 131455682Smarkm if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) { 131555682Smarkm warn ("bind"); 131655682Smarkm goto bad; 131755682Smarkm } 131855682Smarkm if (options & SO_DEBUG) 131955682Smarkm socket_set_debug (data); 132055682Smarkm len = sizeof (data_addr_ss); 132155682Smarkm if (getsockname (data, data_addr, &len) < 0) { 132255682Smarkm warn ("getsockname"); 132355682Smarkm goto bad; 132455682Smarkm } 132555682Smarkm if (listen (data, 1) < 0) 132655682Smarkm warn ("listen"); 132755682Smarkm if (sendport) { 132855682Smarkm char addr_str[256]; 132955682Smarkm int inet_af; 133055682Smarkm int overbose; 133155682Smarkm 133255682Smarkm if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr), 133355682Smarkm addr_str, sizeof(addr_str)) == NULL) 133455682Smarkm errx (1, "inet_ntop failed"); 133555682Smarkm switch (data_addr->sa_family) { 133655682Smarkm case AF_INET : 133755682Smarkm inet_af = 1; 133855682Smarkm break; 133955682Smarkm#ifdef HAVE_IPV6 134055682Smarkm case AF_INET6 : 134155682Smarkm inet_af = 2; 134255682Smarkm break; 134355682Smarkm#endif 134455682Smarkm default : 134555682Smarkm errx (1, "bad address family %d", data_addr->sa_family); 134655682Smarkm } 134755682Smarkm 134855682Smarkm 134955682Smarkm overbose = verbose; 135055682Smarkm if (debug == 0) 135155682Smarkm verbose = -1; 135255682Smarkm 1353103423Snectar result = command ("EPRT |%d|%s|%d|", 1354233294Sstas inet_af, addr_str, 1355103423Snectar ntohs(socket_get_port (data_addr))); 135655682Smarkm verbose = overbose; 135755682Smarkm 135855682Smarkm if (result == ERROR) { 1359178825Sdfr struct sockaddr_in *sin4 = (struct sockaddr_in *)data_addr; 136055682Smarkm 1361178825Sdfr unsigned int a = ntohl(sin4->sin_addr.s_addr); 1362178825Sdfr unsigned int p = ntohs(sin4->sin_port); 136355682Smarkm 136455682Smarkm if (data_addr->sa_family != AF_INET) { 136555682Smarkm warnx ("remote server doesn't support EPRT"); 136655682Smarkm goto bad; 136755682Smarkm } 136855682Smarkm 1369233294Sstas result = command("PORT %d,%d,%d,%d,%d,%d", 137055682Smarkm (a >> 24) & 0xff, 137155682Smarkm (a >> 16) & 0xff, 137255682Smarkm (a >> 8) & 0xff, 137355682Smarkm a & 0xff, 137455682Smarkm (p >> 8) & 0xff, 137555682Smarkm p & 0xff); 137655682Smarkm if (result == ERROR && sendport == -1) { 137755682Smarkm sendport = 0; 137855682Smarkm tmpno = 1; 137955682Smarkm goto noport; 138055682Smarkm } 138155682Smarkm return (result != COMPLETE); 138255682Smarkm } 138355682Smarkm return result != COMPLETE; 138455682Smarkm } 138555682Smarkm if (tmpno) 138655682Smarkm sendport = 1; 138755682Smarkm 138855682Smarkm 138955682Smarkm#ifdef IPTOS_THROUGHPUT 139055682Smarkm socket_set_tos (data, IPTOS_THROUGHPUT); 139155682Smarkm#endif 139255682Smarkm return (0); 139355682Smarkmbad: 139455682Smarkm close (data); 139555682Smarkm data = -1; 139655682Smarkm if (tmpno) 139755682Smarkm sendport = 1; 139855682Smarkm return (1); 139955682Smarkm} 140055682Smarkm 140155682Smarkm/* 140255682Smarkm * Need to start a listen on the data channel before we send the command, 140355682Smarkm * otherwise the server's connect may fail. 140455682Smarkm */ 140555682Smarkmint 140655682Smarkminitconn (void) 140755682Smarkm{ 1408233294Sstas if (passivemode) 140955682Smarkm return passive_mode (); 141055682Smarkm else 141155682Smarkm return active_mode (); 141255682Smarkm} 141355682Smarkm 141455682SmarkmFILE * 141555682Smarkmdataconn (const char *lmode) 141655682Smarkm{ 141755682Smarkm struct sockaddr_storage from_ss; 141855682Smarkm struct sockaddr *from = (struct sockaddr *)&from_ss; 141972445Sassar socklen_t fromlen = sizeof(from_ss); 142072445Sassar int s; 142155682Smarkm 142255682Smarkm if (passivemode) 142355682Smarkm return (fdopen (data, lmode)); 142455682Smarkm 142555682Smarkm s = accept (data, from, &fromlen); 142655682Smarkm if (s < 0) { 142755682Smarkm warn ("accept"); 142855682Smarkm close (data), data = -1; 142955682Smarkm return (NULL); 143055682Smarkm } 143155682Smarkm close (data); 143255682Smarkm data = s; 143355682Smarkm#ifdef IPTOS_THROUGHPUT 143455682Smarkm socket_set_tos (s, IPTOS_THROUGHPUT); 143555682Smarkm#endif 143655682Smarkm return (fdopen (data, lmode)); 143755682Smarkm} 143855682Smarkm 143955682Smarkmvoid 144055682Smarkmptransfer (char *direction, long int bytes, 144155682Smarkm struct timeval * t0, struct timeval * t1) 144255682Smarkm{ 144355682Smarkm struct timeval td; 144455682Smarkm float s; 144555682Smarkm float bs; 144655682Smarkm int prec; 144755682Smarkm char *unit; 144855682Smarkm 144955682Smarkm if (verbose) { 145055682Smarkm td.tv_sec = t1->tv_sec - t0->tv_sec; 145155682Smarkm td.tv_usec = t1->tv_usec - t0->tv_usec; 145255682Smarkm if (td.tv_usec < 0) { 145355682Smarkm td.tv_sec--; 145455682Smarkm td.tv_usec += 1000000; 145555682Smarkm } 145655682Smarkm s = td.tv_sec + (td.tv_usec / 1000000.); 145755682Smarkm bs = bytes / (s ? s : 1); 145855682Smarkm if (bs >= 1048576) { 145955682Smarkm bs /= 1048576; 146055682Smarkm unit = "M"; 146155682Smarkm prec = 2; 146255682Smarkm } else if (bs >= 1024) { 146355682Smarkm bs /= 1024; 146455682Smarkm unit = "k"; 146555682Smarkm prec = 1; 146655682Smarkm } else { 146755682Smarkm unit = ""; 146855682Smarkm prec = 0; 146955682Smarkm } 147055682Smarkm 147155682Smarkm printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", 147255682Smarkm bytes, direction, s, prec, bs, unit); 147355682Smarkm } 147455682Smarkm} 147555682Smarkm 147655682Smarkmvoid 147755682Smarkmpsabort (int sig) 147855682Smarkm{ 147955682Smarkm 148055682Smarkm abrtflag++; 148155682Smarkm} 148255682Smarkm 148355682Smarkmvoid 148455682Smarkmpswitch (int flag) 148555682Smarkm{ 148655682Smarkm sighand oldintr; 148755682Smarkm static struct comvars { 148855682Smarkm int connect; 148955682Smarkm char name[MaxHostNameLen]; 149055682Smarkm struct sockaddr_storage mctl; 149155682Smarkm struct sockaddr_storage hctl; 149255682Smarkm FILE *in; 149355682Smarkm FILE *out; 149455682Smarkm int tpe; 149555682Smarkm int curtpe; 149655682Smarkm int cpnd; 149755682Smarkm int sunqe; 149855682Smarkm int runqe; 149955682Smarkm int mcse; 150055682Smarkm int ntflg; 150155682Smarkm char nti[17]; 150255682Smarkm char nto[17]; 150355682Smarkm int mapflg; 150455682Smarkm char mi[MaxPathLen]; 150555682Smarkm char mo[MaxPathLen]; 150655682Smarkm } proxstruct, tmpstruct; 150755682Smarkm struct comvars *ip, *op; 150855682Smarkm 150955682Smarkm abrtflag = 0; 151055682Smarkm oldintr = signal (SIGINT, psabort); 151155682Smarkm if (flag) { 151255682Smarkm if (proxy) 151355682Smarkm return; 151455682Smarkm ip = &tmpstruct; 151555682Smarkm op = &proxstruct; 151655682Smarkm proxy++; 151755682Smarkm } else { 151855682Smarkm if (!proxy) 151955682Smarkm return; 152055682Smarkm ip = &proxstruct; 152155682Smarkm op = &tmpstruct; 152255682Smarkm proxy = 0; 152355682Smarkm } 152455682Smarkm ip->connect = connected; 152555682Smarkm connected = op->connect; 152655682Smarkm if (hostname) { 152755682Smarkm strlcpy (ip->name, hostname, sizeof (ip->name)); 152855682Smarkm } else 152955682Smarkm ip->name[0] = 0; 153055682Smarkm hostname = op->name; 153155682Smarkm ip->hctl = hisctladdr_ss; 153255682Smarkm hisctladdr_ss = op->hctl; 153355682Smarkm ip->mctl = myctladdr_ss; 153455682Smarkm myctladdr_ss = op->mctl; 153555682Smarkm ip->in = cin; 153655682Smarkm cin = op->in; 153755682Smarkm ip->out = cout; 153855682Smarkm cout = op->out; 153955682Smarkm ip->tpe = type; 154055682Smarkm type = op->tpe; 154155682Smarkm ip->curtpe = curtype; 154255682Smarkm curtype = op->curtpe; 154355682Smarkm ip->cpnd = cpend; 154455682Smarkm cpend = op->cpnd; 154555682Smarkm ip->sunqe = sunique; 154655682Smarkm sunique = op->sunqe; 154755682Smarkm ip->runqe = runique; 154855682Smarkm runique = op->runqe; 154955682Smarkm ip->mcse = mcase; 155055682Smarkm mcase = op->mcse; 155155682Smarkm ip->ntflg = ntflag; 155255682Smarkm ntflag = op->ntflg; 155355682Smarkm strlcpy (ip->nti, ntin, sizeof (ip->nti)); 155455682Smarkm strlcpy (ntin, op->nti, 17); 155555682Smarkm strlcpy (ip->nto, ntout, sizeof (ip->nto)); 155655682Smarkm strlcpy (ntout, op->nto, 17); 155755682Smarkm ip->mapflg = mapflag; 155855682Smarkm mapflag = op->mapflg; 155955682Smarkm strlcpy (ip->mi, mapin, MaxPathLen); 156055682Smarkm strlcpy (mapin, op->mi, MaxPathLen); 156155682Smarkm strlcpy (ip->mo, mapout, MaxPathLen); 156255682Smarkm strlcpy (mapout, op->mo, MaxPathLen); 156355682Smarkm signal(SIGINT, oldintr); 156455682Smarkm if (abrtflag) { 156555682Smarkm abrtflag = 0; 156655682Smarkm (*oldintr) (SIGINT); 156755682Smarkm } 156855682Smarkm} 156955682Smarkm 157055682Smarkmvoid 157155682Smarkmabortpt (int sig) 157255682Smarkm{ 157355682Smarkm 157455682Smarkm printf ("\n"); 157555682Smarkm fflush (stdout); 157655682Smarkm ptabflg++; 157755682Smarkm mflag = 0; 157855682Smarkm abrtflag = 0; 157955682Smarkm longjmp (ptabort, 1); 158055682Smarkm} 158155682Smarkm 158255682Smarkmvoid 158355682Smarkmproxtrans (char *cmd, char *local, char *remote) 158455682Smarkm{ 1585178825Sdfr sighand oldintr = NULL; 158655682Smarkm int secndflag = 0, prox_type, nfnd; 158755682Smarkm char *cmd2; 158855682Smarkm fd_set mask; 158955682Smarkm 159055682Smarkm if (strcmp (cmd, "RETR")) 159155682Smarkm cmd2 = "RETR"; 159255682Smarkm else 159355682Smarkm cmd2 = runique ? "STOU" : "STOR"; 159455682Smarkm if ((prox_type = type) == 0) { 159555682Smarkm if (unix_server && unix_proxy) 159655682Smarkm prox_type = TYPE_I; 159755682Smarkm else 159855682Smarkm prox_type = TYPE_A; 159955682Smarkm } 160055682Smarkm if (curtype != prox_type) 160155682Smarkm changetype (prox_type, 1); 160255682Smarkm if (command ("PASV") != COMPLETE) { 160355682Smarkm printf ("proxy server does not support third party transfers.\n"); 160455682Smarkm return; 160555682Smarkm } 160655682Smarkm pswitch (0); 160755682Smarkm if (!connected) { 160855682Smarkm printf ("No primary connection\n"); 160955682Smarkm pswitch (1); 161055682Smarkm code = -1; 161155682Smarkm return; 161255682Smarkm } 161355682Smarkm if (curtype != prox_type) 161455682Smarkm changetype (prox_type, 1); 161555682Smarkm if (command ("PORT %s", pasv) != COMPLETE) { 161655682Smarkm pswitch (1); 161755682Smarkm return; 161855682Smarkm } 161955682Smarkm if (setjmp (ptabort)) 162055682Smarkm goto abort; 162155682Smarkm oldintr = signal (SIGINT, abortpt); 162255682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 162355682Smarkm signal (SIGINT, oldintr); 162455682Smarkm pswitch (1); 162555682Smarkm return; 162655682Smarkm } 162755682Smarkm sleep (2); 162855682Smarkm pswitch (1); 162955682Smarkm secndflag++; 163055682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) 163155682Smarkm goto abort; 163255682Smarkm ptflag++; 163355682Smarkm getreply (0); 163455682Smarkm pswitch (0); 163555682Smarkm getreply (0); 163655682Smarkm signal (SIGINT, oldintr); 163755682Smarkm pswitch (1); 163855682Smarkm ptflag = 0; 163955682Smarkm printf ("local: %s remote: %s\n", local, remote); 164055682Smarkm return; 164155682Smarkmabort: 164255682Smarkm signal (SIGINT, SIG_IGN); 164355682Smarkm ptflag = 0; 164455682Smarkm if (strcmp (cmd, "RETR") && !proxy) 164555682Smarkm pswitch (1); 164655682Smarkm else if (!strcmp (cmd, "RETR") && proxy) 164755682Smarkm pswitch (0); 164855682Smarkm if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 164955682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) { 165055682Smarkm pswitch (0); 165155682Smarkm if (cpend) 165255682Smarkm abort_remote ((FILE *) NULL); 165355682Smarkm } 165455682Smarkm pswitch (1); 165555682Smarkm if (ptabflg) 165655682Smarkm code = -1; 1657178825Sdfr if (oldintr) 1658178825Sdfr signal (SIGINT, oldintr); 165955682Smarkm return; 166055682Smarkm } 166155682Smarkm if (cpend) 166255682Smarkm abort_remote ((FILE *) NULL); 166355682Smarkm pswitch (!proxy); 166455682Smarkm if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 166555682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) { 166655682Smarkm pswitch (0); 166755682Smarkm if (cpend) 166855682Smarkm abort_remote ((FILE *) NULL); 166955682Smarkm pswitch (1); 167055682Smarkm if (ptabflg) 167155682Smarkm code = -1; 167255682Smarkm signal (SIGINT, oldintr); 167355682Smarkm return; 167455682Smarkm } 167555682Smarkm } 167655682Smarkm if (cpend) 167755682Smarkm abort_remote ((FILE *) NULL); 167855682Smarkm pswitch (!proxy); 167955682Smarkm if (cpend) { 168055682Smarkm FD_ZERO (&mask); 168172445Sassar if (fileno(cin) >= FD_SETSIZE) 168272445Sassar errx (1, "fd too large"); 168355682Smarkm FD_SET (fileno (cin), &mask); 168455682Smarkm if ((nfnd = empty (&mask, 10)) <= 0) { 168555682Smarkm if (nfnd < 0) { 168655682Smarkm warn ("abort"); 168755682Smarkm } 168855682Smarkm if (ptabflg) 168955682Smarkm code = -1; 169055682Smarkm lostpeer (0); 169155682Smarkm } 169255682Smarkm getreply (0); 169355682Smarkm getreply (0); 169455682Smarkm } 169555682Smarkm if (proxy) 169655682Smarkm pswitch (0); 169755682Smarkm pswitch (1); 169855682Smarkm if (ptabflg) 169955682Smarkm code = -1; 170055682Smarkm signal (SIGINT, oldintr); 170155682Smarkm} 170255682Smarkm 170355682Smarkmvoid 170455682Smarkmreset (int argc, char **argv) 170555682Smarkm{ 170655682Smarkm fd_set mask; 170755682Smarkm int nfnd = 1; 170855682Smarkm 170955682Smarkm FD_ZERO (&mask); 171055682Smarkm while (nfnd > 0) { 171172445Sassar if (fileno (cin) >= FD_SETSIZE) 171272445Sassar errx (1, "fd too large"); 171355682Smarkm FD_SET (fileno (cin), &mask); 171455682Smarkm if ((nfnd = empty (&mask, 0)) < 0) { 171555682Smarkm warn ("reset"); 171655682Smarkm code = -1; 171755682Smarkm lostpeer(0); 171855682Smarkm } else if (nfnd) { 171955682Smarkm getreply(0); 172055682Smarkm } 172155682Smarkm } 172255682Smarkm} 172355682Smarkm 172455682Smarkmchar * 172555682Smarkmgunique (char *local) 172655682Smarkm{ 172755682Smarkm static char new[MaxPathLen]; 172855682Smarkm char *cp = strrchr (local, '/'); 172955682Smarkm int d, count = 0; 173055682Smarkm char ext = '1'; 173155682Smarkm 173255682Smarkm if (cp) 173355682Smarkm *cp = '\0'; 173455682Smarkm d = access (cp ? local : ".", 2); 173555682Smarkm if (cp) 173655682Smarkm *cp = '/'; 173755682Smarkm if (d < 0) { 173855682Smarkm warn ("local: %s", local); 173955682Smarkm return NULL; 174055682Smarkm } 174155682Smarkm strlcpy (new, local, sizeof(new)); 174255682Smarkm cp = new + strlen(new); 174355682Smarkm *cp++ = '.'; 174455682Smarkm while (!d) { 174555682Smarkm if (++count == 100) { 174655682Smarkm printf ("runique: can't find unique file name.\n"); 174755682Smarkm return NULL; 174855682Smarkm } 174955682Smarkm *cp++ = ext; 175055682Smarkm *cp = '\0'; 175155682Smarkm if (ext == '9') 175255682Smarkm ext = '0'; 175355682Smarkm else 175455682Smarkm ext++; 175555682Smarkm if ((d = access (new, 0)) < 0) 175655682Smarkm break; 175755682Smarkm if (ext != '0') 175855682Smarkm cp--; 175955682Smarkm else if (*(cp - 2) == '.') 176055682Smarkm *(cp - 1) = '1'; 176155682Smarkm else { 176255682Smarkm *(cp - 2) = *(cp - 2) + 1; 176355682Smarkm cp--; 176455682Smarkm } 176555682Smarkm } 176655682Smarkm return (new); 176755682Smarkm} 176855682Smarkm 176955682Smarkmvoid 177055682Smarkmabort_remote (FILE * din) 177155682Smarkm{ 177255682Smarkm char buf[BUFSIZ]; 177355682Smarkm int nfnd; 177455682Smarkm fd_set mask; 177555682Smarkm 177655682Smarkm /* 177755682Smarkm * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 177855682Smarkm * after urgent byte rather than before as is protocol now 177955682Smarkm */ 178055682Smarkm snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC); 178155682Smarkm if (send (fileno (cout), buf, 3, MSG_OOB) != 3) 178255682Smarkm warn ("abort"); 1783142403Snectar fprintf (cout, "%c", DM); 1784142403Snectar sec_fprintf(cout, "ABOR"); 1785142403Snectar sec_fflush (cout); 1786142403Snectar fprintf (cout, "\r\n"); 1787142403Snectar fflush(cout); 178855682Smarkm FD_ZERO (&mask); 178972445Sassar if (fileno (cin) >= FD_SETSIZE) 179072445Sassar errx (1, "fd too large"); 179155682Smarkm FD_SET (fileno (cin), &mask); 179255682Smarkm if (din) { 1793178825Sdfr if (fileno (din) >= FD_SETSIZE) 1794178825Sdfr errx (1, "fd too large"); 179555682Smarkm FD_SET (fileno (din), &mask); 179655682Smarkm } 179755682Smarkm if ((nfnd = empty (&mask, 10)) <= 0) { 179855682Smarkm if (nfnd < 0) { 179955682Smarkm warn ("abort"); 180055682Smarkm } 180155682Smarkm if (ptabflg) 180255682Smarkm code = -1; 180355682Smarkm lostpeer (0); 180455682Smarkm } 180555682Smarkm if (din && FD_ISSET (fileno (din), &mask)) { 180655682Smarkm while (read (fileno (din), buf, BUFSIZ) > 0) 180755682Smarkm /* LOOP */ ; 180855682Smarkm } 180955682Smarkm if (getreply (0) == ERROR && code == 552) { 181055682Smarkm /* 552 needed for nic style abort */ 181155682Smarkm getreply (0); 181255682Smarkm } 181355682Smarkm getreply (0); 181455682Smarkm} 1815