ftp.c revision 142403
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" 35142403SnectarRCSID ("$Id: ftp.c,v 1.75.2.1 2004/08/20 14:59:06 lha Exp $"); 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 8255682Smarkm for (a = ai; a != NULL; a = a->ai_next) { 8355682Smarkm s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 8455682Smarkm if (s < 0) 8555682Smarkm continue; 8655682Smarkm 8755682Smarkm if (a->ai_canonname != NULL) 8855682Smarkm strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf)); 8955682Smarkm 9055682Smarkm memcpy (hisctladdr, a->ai_addr, a->ai_addrlen); 9155682Smarkm 9255682Smarkm error = connect (s, a->ai_addr, a->ai_addrlen); 9355682Smarkm if (error < 0) { 9455682Smarkm char addrstr[256]; 9555682Smarkm 9655682Smarkm if (getnameinfo (a->ai_addr, a->ai_addrlen, 9755682Smarkm addrstr, sizeof(addrstr), 9855682Smarkm NULL, 0, NI_NUMERICHOST) != 0) 9955682Smarkm strlcpy (addrstr, "unknown address", sizeof(addrstr)); 10055682Smarkm 10155682Smarkm warn ("connect %s", addrstr); 10255682Smarkm close (s); 10355682Smarkm continue; 10455682Smarkm } 10555682Smarkm break; 10655682Smarkm } 10755682Smarkm freeaddrinfo (ai); 10855682Smarkm if (error < 0) { 10955682Smarkm warnx ("failed to contact %s", host); 11055682Smarkm code = -1; 11155682Smarkm return NULL; 11255682Smarkm } 11355682Smarkm 11455682Smarkm len = sizeof(myctladdr_ss); 11555682Smarkm if (getsockname (s, myctladdr, &len) < 0) { 11655682Smarkm warn ("getsockname"); 11755682Smarkm code = -1; 11855682Smarkm close (s); 11955682Smarkm return NULL; 12055682Smarkm } 12155682Smarkm#ifdef IPTOS_LOWDELAY 12255682Smarkm socket_set_tos (s, IPTOS_LOWDELAY); 12355682Smarkm#endif 12455682Smarkm cin = fdopen (s, "r"); 12555682Smarkm cout = fdopen (s, "w"); 12655682Smarkm if (cin == NULL || cout == NULL) { 12755682Smarkm warnx ("fdopen failed."); 12855682Smarkm if (cin) 12955682Smarkm fclose (cin); 13055682Smarkm if (cout) 13155682Smarkm fclose (cout); 13255682Smarkm code = -1; 13355682Smarkm goto bad; 13455682Smarkm } 13555682Smarkm if (verbose) 13655682Smarkm printf ("Connected to %s.\n", hostname); 13755682Smarkm if (getreply (0) > 2) { /* read startup message from server */ 13855682Smarkm if (cin) 13955682Smarkm fclose (cin); 14055682Smarkm if (cout) 14155682Smarkm fclose (cout); 14255682Smarkm code = -1; 14355682Smarkm goto bad; 14455682Smarkm } 14555682Smarkm#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) 14655682Smarkm { 14755682Smarkm int on = 1; 14855682Smarkm 14955682Smarkm if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on)) 15055682Smarkm < 0 && debug) { 15155682Smarkm warn ("setsockopt"); 15255682Smarkm } 15355682Smarkm } 15455682Smarkm#endif /* SO_OOBINLINE */ 15555682Smarkm 15655682Smarkm return (hostname); 15755682Smarkmbad: 15855682Smarkm close (s); 15955682Smarkm return NULL; 16055682Smarkm} 16155682Smarkm 16255682Smarkmint 16355682Smarkmlogin (char *host) 16455682Smarkm{ 16555682Smarkm char tmp[80]; 16655682Smarkm char defaultpass[128]; 16755682Smarkm char *user, *pass, *acct; 16855682Smarkm int n, aflag = 0; 16955682Smarkm 17055682Smarkm char *myname = NULL; 17155682Smarkm struct passwd *pw = k_getpwuid(getuid()); 17255682Smarkm 17355682Smarkm if (pw != NULL) 17455682Smarkm myname = pw->pw_name; 17555682Smarkm 17655682Smarkm user = pass = acct = 0; 17755682Smarkm 17855682Smarkm if(sec_login(host)) 17955682Smarkm printf("\n*** Using plaintext user and password ***\n\n"); 18055682Smarkm else{ 18155682Smarkm printf("Authentication successful.\n\n"); 18255682Smarkm } 18355682Smarkm 18455682Smarkm if (ruserpass (host, &user, &pass, &acct) < 0) { 18555682Smarkm code = -1; 18655682Smarkm return (0); 18755682Smarkm } 18855682Smarkm while (user == NULL) { 18955682Smarkm if (myname) 19055682Smarkm printf ("Name (%s:%s): ", host, myname); 19155682Smarkm else 19255682Smarkm printf ("Name (%s): ", host); 19372445Sassar *tmp = '\0'; 19472445Sassar if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL) 19572445Sassar tmp[strlen (tmp) - 1] = '\0'; 19655682Smarkm if (*tmp == '\0') 19755682Smarkm user = myname; 19855682Smarkm else 19955682Smarkm user = tmp; 20055682Smarkm } 20155682Smarkm strlcpy(username, user, sizeof(username)); 20255682Smarkm n = command("USER %s", user); 20372445Sassar if (n == COMPLETE) 20472445Sassar n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */ 20572445Sassar else if(n == CONTINUE) { 20672445Sassar if (pass == NULL) { 20755682Smarkm char prompt[128]; 20855682Smarkm if(myname && 20972445Sassar (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))) { 21055682Smarkm snprintf(defaultpass, sizeof(defaultpass), 21155682Smarkm "%s@%s", myname, mydomain); 21255682Smarkm snprintf(prompt, sizeof(prompt), 21355682Smarkm "Password (%s): ", defaultpass); 21472445Sassar } else if (sec_complete) { 21572445Sassar pass = myname; 21672445Sassar } else { 21755682Smarkm *defaultpass = '\0'; 21855682Smarkm snprintf(prompt, sizeof(prompt), "Password: "); 21955682Smarkm } 22072445Sassar if (pass == NULL) { 22172445Sassar pass = defaultpass; 22272445Sassar des_read_pw_string (tmp, sizeof (tmp), prompt, 0); 22372445Sassar if (tmp[0]) 22472445Sassar pass = tmp; 22572445Sassar } 22655682Smarkm } 22755682Smarkm n = command ("PASS %s", pass); 22855682Smarkm } 22955682Smarkm if (n == CONTINUE) { 23055682Smarkm aflag++; 23155682Smarkm acct = tmp; 23255682Smarkm des_read_pw_string (acct, 128, "Account:", 0); 23355682Smarkm n = command ("ACCT %s", acct); 23455682Smarkm } 23555682Smarkm if (n != COMPLETE) { 23655682Smarkm warnx ("Login failed."); 23755682Smarkm return (0); 23855682Smarkm } 23955682Smarkm if (!aflag && acct != NULL) 24055682Smarkm command ("ACCT %s", acct); 24155682Smarkm if (proxy) 24255682Smarkm return (1); 24355682Smarkm for (n = 0; n < macnum; ++n) { 24455682Smarkm if (!strcmp("init", macros[n].mac_name)) { 24555682Smarkm strlcpy (line, "$init", sizeof (line)); 24655682Smarkm makeargv(); 24755682Smarkm domacro(margc, margv); 24855682Smarkm break; 24955682Smarkm } 25055682Smarkm } 25155682Smarkm sec_set_protection_level (); 25255682Smarkm return (1); 25355682Smarkm} 25455682Smarkm 25555682Smarkmvoid 25655682Smarkmcmdabort (int sig) 25755682Smarkm{ 25855682Smarkm 25955682Smarkm printf ("\n"); 26055682Smarkm fflush (stdout); 26155682Smarkm abrtflag++; 26255682Smarkm if (ptflag) 26355682Smarkm longjmp (ptabort, 1); 26455682Smarkm} 26555682Smarkm 26655682Smarkmint 26755682Smarkmcommand (char *fmt,...) 26855682Smarkm{ 26955682Smarkm va_list ap; 27055682Smarkm int r; 27155682Smarkm sighand oldintr; 27255682Smarkm 27355682Smarkm abrtflag = 0; 27455682Smarkm if (cout == NULL) { 27555682Smarkm warn ("No control connection for command"); 27655682Smarkm code = -1; 27755682Smarkm return (0); 27855682Smarkm } 27955682Smarkm oldintr = signal(SIGINT, cmdabort); 28055682Smarkm if(debug){ 28155682Smarkm printf("---> "); 28255682Smarkm if (strncmp("PASS ", fmt, 5) == 0) 28355682Smarkm printf("PASS XXXX"); 284102644Snectar else { 285102644Snectar va_start(ap, fmt); 28655682Smarkm vfprintf(stdout, fmt, ap); 287102644Snectar va_end(ap); 288102644Snectar } 28955682Smarkm } 290102644Snectar va_start(ap, fmt); 29155682Smarkm sec_vfprintf(cout, fmt, ap); 29255682Smarkm va_end(ap); 29355682Smarkm if(debug){ 29455682Smarkm printf("\n"); 29555682Smarkm fflush(stdout); 29655682Smarkm } 29755682Smarkm fprintf (cout, "\r\n"); 29855682Smarkm fflush (cout); 29955682Smarkm cpend = 1; 30055682Smarkm r = getreply (!strcmp (fmt, "QUIT")); 30155682Smarkm if (abrtflag && oldintr != SIG_IGN) 30255682Smarkm (*oldintr) (SIGINT); 30355682Smarkm signal (SIGINT, oldintr); 30455682Smarkm return (r); 30555682Smarkm} 30655682Smarkm 30755682Smarkmchar reply_string[BUFSIZ]; /* last line of previous reply */ 30855682Smarkm 30955682Smarkmint 31055682Smarkmgetreply (int expecteof) 31155682Smarkm{ 31255682Smarkm char *p; 31355682Smarkm char *lead_string; 31455682Smarkm int c; 31555682Smarkm struct sigaction sa, osa; 316102644Snectar char buf[8192]; 317102644Snectar int reply_code; 318102644Snectar int long_warn = 0; 31955682Smarkm 32055682Smarkm sigemptyset (&sa.sa_mask); 32155682Smarkm sa.sa_flags = 0; 32255682Smarkm sa.sa_handler = cmdabort; 32355682Smarkm sigaction (SIGINT, &sa, &osa); 32455682Smarkm 32555682Smarkm p = buf; 32655682Smarkm 327102644Snectar reply_code = 0; 32855682Smarkm while (1) { 32955682Smarkm c = getc (cin); 33055682Smarkm switch (c) { 33155682Smarkm case EOF: 33255682Smarkm if (expecteof) { 33355682Smarkm sigaction (SIGINT, &osa, NULL); 33455682Smarkm code = 221; 33555682Smarkm return 0; 33655682Smarkm } 33755682Smarkm lostpeer (0); 33855682Smarkm if (verbose) { 33955682Smarkm printf ("421 Service not available, " 34055682Smarkm "remote server has closed connection\n"); 34155682Smarkm fflush (stdout); 34255682Smarkm } 34355682Smarkm code = 421; 34455682Smarkm return (4); 34555682Smarkm case IAC: 34655682Smarkm c = getc (cin); 34755682Smarkm if (c == WILL || c == WONT) 34855682Smarkm fprintf (cout, "%c%c%c", IAC, DONT, getc (cin)); 34955682Smarkm if (c == DO || c == DONT) 35055682Smarkm fprintf (cout, "%c%c%c", IAC, WONT, getc (cin)); 35155682Smarkm continue; 35255682Smarkm case '\n': 35355682Smarkm *p++ = '\0'; 35455682Smarkm if(isdigit(buf[0])){ 35555682Smarkm sscanf(buf, "%d", &code); 35655682Smarkm if(code == 631){ 357102644Snectar code = 0; 35855682Smarkm sec_read_msg(buf, prot_safe); 35955682Smarkm sscanf(buf, "%d", &code); 36055682Smarkm lead_string = "S:"; 36155682Smarkm } else if(code == 632){ 362102644Snectar code = 0; 36355682Smarkm sec_read_msg(buf, prot_private); 36455682Smarkm sscanf(buf, "%d", &code); 36555682Smarkm lead_string = "P:"; 36655682Smarkm }else if(code == 633){ 367102644Snectar code = 0; 36855682Smarkm sec_read_msg(buf, prot_confidential); 36955682Smarkm sscanf(buf, "%d", &code); 37055682Smarkm lead_string = "C:"; 37155682Smarkm }else if(sec_complete) 37255682Smarkm lead_string = "!!"; 37355682Smarkm else 37455682Smarkm lead_string = ""; 375102644Snectar if(code != 0 && reply_code == 0) 376102644Snectar reply_code = code; 37755682Smarkm if (verbose > 0 || (verbose > -1 && code > 499)) 37855682Smarkm fprintf (stdout, "%s%s\n", lead_string, buf); 379102644Snectar if (code == reply_code && buf[3] == ' ') { 380102644Snectar strlcpy (reply_string, buf, sizeof(reply_string)); 38155682Smarkm if (code >= 200) 38255682Smarkm cpend = 0; 38355682Smarkm sigaction (SIGINT, &osa, NULL); 38455682Smarkm if (code == 421) 38555682Smarkm lostpeer (0); 38655682Smarkm#if 1 38755682Smarkm if (abrtflag && 38855682Smarkm osa.sa_handler != cmdabort && 38955682Smarkm osa.sa_handler != SIG_IGN) 39055682Smarkm osa.sa_handler (SIGINT); 39155682Smarkm#endif 39255682Smarkm if (code == 227 || code == 229) { 393102644Snectar char *p; 39455682Smarkm 39555682Smarkm p = strchr (reply_string, '('); 39655682Smarkm if (p) { 39755682Smarkm p++; 398102644Snectar strlcpy(pasv, p, sizeof(pasv)); 399107207Snectar p = strrchr(pasv, ')'); 400107207Snectar if (p) 401107207Snectar *p = '\0'; 40255682Smarkm } 40355682Smarkm } 40455682Smarkm return code / 100; 40555682Smarkm } 40655682Smarkm }else{ 40755682Smarkm if(verbose > 0 || (verbose > -1 && code > 499)){ 40855682Smarkm if(sec_complete) 40955682Smarkm fprintf(stdout, "!!"); 41055682Smarkm fprintf(stdout, "%s\n", buf); 41155682Smarkm } 41255682Smarkm } 41355682Smarkm p = buf; 414102644Snectar long_warn = 0; 41555682Smarkm continue; 41655682Smarkm default: 417102644Snectar if(p < buf + sizeof(buf) - 1) 418102644Snectar *p++ = c; 419102644Snectar else if(long_warn == 0) { 420102644Snectar fprintf(stderr, "WARNING: incredibly long line received\n"); 421102644Snectar long_warn = 1; 422102644Snectar } 42355682Smarkm } 42455682Smarkm } 42555682Smarkm 42655682Smarkm} 42755682Smarkm 42855682Smarkm 42955682Smarkm#if 0 43055682Smarkmint 43155682Smarkmgetreply (int expecteof) 43255682Smarkm{ 43355682Smarkm int c, n; 43455682Smarkm int dig; 43555682Smarkm int originalcode = 0, continuation = 0; 43655682Smarkm sighand oldintr; 43755682Smarkm int pflag = 0; 43855682Smarkm char *cp, *pt = pasv; 43955682Smarkm 44055682Smarkm oldintr = signal (SIGINT, cmdabort); 44155682Smarkm for (;;) { 44255682Smarkm dig = n = code = 0; 44355682Smarkm cp = reply_string; 44455682Smarkm while ((c = getc (cin)) != '\n') { 44555682Smarkm if (c == IAC) { /* handle telnet commands */ 44655682Smarkm switch (c = getc (cin)) { 44755682Smarkm case WILL: 44855682Smarkm case WONT: 44955682Smarkm c = getc (cin); 45055682Smarkm fprintf (cout, "%c%c%c", IAC, DONT, c); 45155682Smarkm fflush (cout); 45255682Smarkm break; 45355682Smarkm case DO: 45455682Smarkm case DONT: 45555682Smarkm c = getc (cin); 45655682Smarkm fprintf (cout, "%c%c%c", IAC, WONT, c); 45755682Smarkm fflush (cout); 45855682Smarkm break; 45955682Smarkm default: 46055682Smarkm break; 46155682Smarkm } 46255682Smarkm continue; 46355682Smarkm } 46455682Smarkm dig++; 46555682Smarkm if (c == EOF) { 46655682Smarkm if (expecteof) { 46755682Smarkm signal (SIGINT, oldintr); 46855682Smarkm code = 221; 46955682Smarkm return (0); 47055682Smarkm } 47155682Smarkm lostpeer (0); 47255682Smarkm if (verbose) { 47355682Smarkm printf ("421 Service not available, remote server has closed connection\n"); 47455682Smarkm fflush (stdout); 47555682Smarkm } 47655682Smarkm code = 421; 47755682Smarkm return (4); 47855682Smarkm } 47955682Smarkm if (c != '\r' && (verbose > 0 || 48055682Smarkm (verbose > -1 && n == '5' && dig > 4))) { 48155682Smarkm if (proxflag && 48255682Smarkm (dig == 1 || dig == 5 && verbose == 0)) 48355682Smarkm printf ("%s:", hostname); 48455682Smarkm putchar (c); 48555682Smarkm } 48655682Smarkm if (dig < 4 && isdigit (c)) 48755682Smarkm code = code * 10 + (c - '0'); 48855682Smarkm if (!pflag && code == 227) 48955682Smarkm pflag = 1; 49055682Smarkm if (dig > 4 && pflag == 1 && isdigit (c)) 49155682Smarkm pflag = 2; 49255682Smarkm if (pflag == 2) { 49355682Smarkm if (c != '\r' && c != ')') 49455682Smarkm *pt++ = c; 49555682Smarkm else { 49655682Smarkm *pt = '\0'; 49755682Smarkm pflag = 3; 49855682Smarkm } 49955682Smarkm } 50055682Smarkm if (dig == 4 && c == '-') { 50155682Smarkm if (continuation) 50255682Smarkm code = 0; 50355682Smarkm continuation++; 50455682Smarkm } 50555682Smarkm if (n == 0) 50655682Smarkm n = c; 50755682Smarkm if (cp < &reply_string[sizeof (reply_string) - 1]) 50855682Smarkm *cp++ = c; 50955682Smarkm } 51055682Smarkm if (verbose > 0 || verbose > -1 && n == '5') { 51155682Smarkm putchar (c); 51255682Smarkm fflush (stdout); 51355682Smarkm } 51455682Smarkm if (continuation && code != originalcode) { 51555682Smarkm if (originalcode == 0) 51655682Smarkm originalcode = code; 51755682Smarkm continue; 51855682Smarkm } 51955682Smarkm *cp = '\0'; 52055682Smarkm if(sec_complete){ 52155682Smarkm if(code == 631) 52255682Smarkm sec_read_msg(reply_string, prot_safe); 52355682Smarkm else if(code == 632) 52455682Smarkm sec_read_msg(reply_string, prot_private); 52555682Smarkm else if(code == 633) 52655682Smarkm sec_read_msg(reply_string, prot_confidential); 52755682Smarkm n = code / 100 + '0'; 52855682Smarkm } 52955682Smarkm if (n != '1') 53055682Smarkm cpend = 0; 53155682Smarkm signal (SIGINT, oldintr); 53255682Smarkm if (code == 421 || originalcode == 421) 53355682Smarkm lostpeer (0); 53455682Smarkm if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 53555682Smarkm (*oldintr) (SIGINT); 53655682Smarkm return (n - '0'); 53755682Smarkm } 53855682Smarkm} 53955682Smarkm 54055682Smarkm#endif 54155682Smarkm 54255682Smarkmint 54355682Smarkmempty (fd_set * mask, int sec) 54455682Smarkm{ 54555682Smarkm struct timeval t; 54655682Smarkm 54772445Sassar t.tv_sec = sec; 54855682Smarkm t.tv_usec = 0; 54972445Sassar return (select (FD_SETSIZE, mask, NULL, NULL, &t)); 55055682Smarkm} 55155682Smarkm 55255682Smarkmjmp_buf sendabort; 55355682Smarkm 55455682Smarkmstatic RETSIGTYPE 55555682Smarkmabortsend (int sig) 55655682Smarkm{ 55755682Smarkm 55855682Smarkm mflag = 0; 55955682Smarkm abrtflag = 0; 56055682Smarkm printf ("\nsend aborted\nwaiting for remote to finish abort\n"); 56155682Smarkm fflush (stdout); 56255682Smarkm longjmp (sendabort, 1); 56355682Smarkm} 56455682Smarkm 56555682Smarkm#define HASHBYTES 1024 56655682Smarkm 56755682Smarkmstatic int 56855682Smarkmcopy_stream (FILE * from, FILE * to) 56955682Smarkm{ 57055682Smarkm static size_t bufsize; 57155682Smarkm static char *buf; 57255682Smarkm int n; 57355682Smarkm int bytes = 0; 57455682Smarkm int werr = 0; 57555682Smarkm int hashbytes = HASHBYTES; 57655682Smarkm struct stat st; 57755682Smarkm 57855682Smarkm#if defined(HAVE_MMAP) && !defined(NO_MMAP) 57955682Smarkm void *chunk; 58055682Smarkm 58155682Smarkm#ifndef MAP_FAILED 58255682Smarkm#define MAP_FAILED (-1) 58355682Smarkm#endif 58455682Smarkm 58555682Smarkm if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) { 58655682Smarkm /* 58755682Smarkm * mmap zero bytes has potential of loosing, don't do it. 58855682Smarkm */ 58955682Smarkm if (st.st_size == 0) 59055682Smarkm return 0; 59155682Smarkm chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0); 59255682Smarkm if (chunk != (void *) MAP_FAILED) { 59355682Smarkm int res; 59455682Smarkm 59555682Smarkm res = sec_write (fileno (to), chunk, st.st_size); 59655682Smarkm if (munmap (chunk, st.st_size) < 0) 59755682Smarkm warn ("munmap"); 59855682Smarkm sec_fflush (to); 59955682Smarkm return res; 60055682Smarkm } 60155682Smarkm } 60255682Smarkm#endif 60355682Smarkm 60455682Smarkm buf = alloc_buffer (buf, &bufsize, 60555682Smarkm fstat (fileno (from), &st) >= 0 ? &st : NULL); 60655682Smarkm if (buf == NULL) 60755682Smarkm return -1; 60855682Smarkm 60955682Smarkm while ((n = read (fileno (from), buf, bufsize)) > 0) { 61055682Smarkm werr = sec_write (fileno (to), buf, n); 61155682Smarkm if (werr < 0) 61255682Smarkm break; 61355682Smarkm bytes += werr; 61455682Smarkm while (hash && bytes > hashbytes) { 61555682Smarkm putchar ('#'); 61655682Smarkm hashbytes += HASHBYTES; 61755682Smarkm } 61855682Smarkm } 61955682Smarkm sec_fflush (to); 62055682Smarkm if (n < 0) 62155682Smarkm warn ("local"); 62255682Smarkm 62355682Smarkm if (werr < 0) { 62455682Smarkm if (errno != EPIPE) 62555682Smarkm warn ("netout"); 62655682Smarkm bytes = -1; 62755682Smarkm } 62855682Smarkm return bytes; 62955682Smarkm} 63055682Smarkm 63155682Smarkmvoid 63255682Smarkmsendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames) 63355682Smarkm{ 63455682Smarkm struct stat st; 63555682Smarkm struct timeval start, stop; 63655682Smarkm int c, d; 63755682Smarkm FILE *fin, *dout = 0; 63855682Smarkm int (*closefunc) (FILE *); 63972445Sassar RETSIGTYPE (*oldintr)(int), (*oldintp)(int); 64055682Smarkm long bytes = 0, hashbytes = HASHBYTES; 64155682Smarkm char *rmode = "w"; 64255682Smarkm 64355682Smarkm if (verbose && printnames) { 64455682Smarkm if (local && strcmp (local, "-") != 0) 64555682Smarkm printf ("local: %s ", local); 64655682Smarkm if (remote) 64755682Smarkm printf ("remote: %s\n", remote); 64855682Smarkm } 64955682Smarkm if (proxy) { 65055682Smarkm proxtrans (cmd, local, remote); 65155682Smarkm return; 65255682Smarkm } 65355682Smarkm if (curtype != type) 65455682Smarkm changetype (type, 0); 65555682Smarkm closefunc = NULL; 65655682Smarkm oldintr = NULL; 65755682Smarkm oldintp = NULL; 65855682Smarkm 65955682Smarkm if (setjmp (sendabort)) { 66055682Smarkm while (cpend) { 66155682Smarkm getreply (0); 66255682Smarkm } 66355682Smarkm if (data >= 0) { 66455682Smarkm close (data); 66555682Smarkm data = -1; 66655682Smarkm } 66755682Smarkm if (oldintr) 66855682Smarkm signal (SIGINT, oldintr); 66955682Smarkm if (oldintp) 67055682Smarkm signal (SIGPIPE, oldintp); 67155682Smarkm code = -1; 67255682Smarkm return; 67355682Smarkm } 67455682Smarkm oldintr = signal (SIGINT, abortsend); 67555682Smarkm if (strcmp (local, "-") == 0) 67655682Smarkm fin = stdin; 67755682Smarkm else if (*local == '|') { 67855682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 67955682Smarkm fin = popen (local + 1, lmode); 68055682Smarkm if (fin == NULL) { 68155682Smarkm warn ("%s", local + 1); 68255682Smarkm signal (SIGINT, oldintr); 68355682Smarkm signal (SIGPIPE, oldintp); 68455682Smarkm code = -1; 68555682Smarkm return; 68655682Smarkm } 68755682Smarkm closefunc = pclose; 68855682Smarkm } else { 68955682Smarkm fin = fopen (local, lmode); 69055682Smarkm if (fin == NULL) { 69155682Smarkm warn ("local: %s", local); 69255682Smarkm signal (SIGINT, oldintr); 69355682Smarkm code = -1; 69455682Smarkm return; 69555682Smarkm } 69655682Smarkm closefunc = fclose; 69755682Smarkm if (fstat (fileno (fin), &st) < 0 || 69855682Smarkm (st.st_mode & S_IFMT) != S_IFREG) { 69955682Smarkm fprintf (stdout, "%s: not a plain file.\n", local); 70055682Smarkm signal (SIGINT, oldintr); 70155682Smarkm fclose (fin); 70255682Smarkm code = -1; 70355682Smarkm return; 70455682Smarkm } 70555682Smarkm } 70655682Smarkm if (initconn ()) { 70755682Smarkm signal (SIGINT, oldintr); 70855682Smarkm if (oldintp) 70955682Smarkm signal (SIGPIPE, oldintp); 71055682Smarkm code = -1; 71155682Smarkm if (closefunc != NULL) 71255682Smarkm (*closefunc) (fin); 71355682Smarkm return; 71455682Smarkm } 71555682Smarkm if (setjmp (sendabort)) 71655682Smarkm goto abort; 71755682Smarkm 71855682Smarkm if (restart_point && 71955682Smarkm (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) { 72055682Smarkm int rc; 72155682Smarkm 72255682Smarkm switch (curtype) { 72355682Smarkm case TYPE_A: 72455682Smarkm rc = fseek (fin, (long) restart_point, SEEK_SET); 72555682Smarkm break; 72655682Smarkm case TYPE_I: 72755682Smarkm case TYPE_L: 72855682Smarkm rc = lseek (fileno (fin), restart_point, SEEK_SET); 72955682Smarkm break; 73055682Smarkm } 73155682Smarkm if (rc < 0) { 73255682Smarkm warn ("local: %s", local); 73355682Smarkm restart_point = 0; 73455682Smarkm if (closefunc != NULL) 73555682Smarkm (*closefunc) (fin); 73655682Smarkm return; 73755682Smarkm } 73855682Smarkm if (command ("REST %ld", (long) restart_point) 73955682Smarkm != CONTINUE) { 74055682Smarkm restart_point = 0; 74155682Smarkm if (closefunc != NULL) 74255682Smarkm (*closefunc) (fin); 74355682Smarkm return; 74455682Smarkm } 74555682Smarkm restart_point = 0; 74655682Smarkm rmode = "r+w"; 74755682Smarkm } 74855682Smarkm if (remote) { 74955682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 75055682Smarkm signal (SIGINT, oldintr); 75155682Smarkm if (oldintp) 75255682Smarkm signal (SIGPIPE, oldintp); 75355682Smarkm if (closefunc != NULL) 75455682Smarkm (*closefunc) (fin); 75555682Smarkm return; 75655682Smarkm } 75755682Smarkm } else if (command ("%s", cmd) != PRELIM) { 75855682Smarkm signal(SIGINT, oldintr); 75955682Smarkm if (oldintp) 76055682Smarkm signal(SIGPIPE, oldintp); 76155682Smarkm if (closefunc != NULL) 76255682Smarkm (*closefunc)(fin); 76355682Smarkm return; 76455682Smarkm } 76555682Smarkm dout = dataconn(rmode); 76655682Smarkm if (dout == NULL) 76755682Smarkm goto abort; 76855682Smarkm set_buffer_size (fileno (dout), 0); 76955682Smarkm gettimeofday (&start, (struct timezone *) 0); 77055682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 77155682Smarkm switch (curtype) { 77255682Smarkm 77355682Smarkm case TYPE_I: 77455682Smarkm case TYPE_L: 77555682Smarkm errno = d = c = 0; 77655682Smarkm bytes = copy_stream (fin, dout); 77755682Smarkm break; 77855682Smarkm 77955682Smarkm case TYPE_A: 78055682Smarkm while ((c = getc (fin)) != EOF) { 78155682Smarkm if (c == '\n') { 78255682Smarkm while (hash && (bytes >= hashbytes)) { 78355682Smarkm putchar ('#'); 78455682Smarkm fflush (stdout); 78555682Smarkm hashbytes += HASHBYTES; 78655682Smarkm } 78755682Smarkm if (ferror (dout)) 78855682Smarkm break; 78955682Smarkm sec_putc ('\r', dout); 79055682Smarkm bytes++; 79155682Smarkm } 79255682Smarkm sec_putc (c, dout); 79355682Smarkm bytes++; 79455682Smarkm } 79555682Smarkm sec_fflush (dout); 79655682Smarkm if (hash) { 79755682Smarkm if (bytes < hashbytes) 79855682Smarkm putchar ('#'); 79955682Smarkm putchar ('\n'); 80055682Smarkm fflush (stdout); 80155682Smarkm } 80255682Smarkm if (ferror (fin)) 80355682Smarkm warn ("local: %s", local); 80455682Smarkm if (ferror (dout)) { 80555682Smarkm if (errno != EPIPE) 80655682Smarkm warn ("netout"); 80755682Smarkm bytes = -1; 80855682Smarkm } 80955682Smarkm break; 81055682Smarkm } 81155682Smarkm if (closefunc != NULL) 81255682Smarkm (*closefunc) (fin); 81355682Smarkm fclose (dout); 81455682Smarkm gettimeofday (&stop, (struct timezone *) 0); 81555682Smarkm getreply (0); 81655682Smarkm signal (SIGINT, oldintr); 81755682Smarkm if (oldintp) 81855682Smarkm signal (SIGPIPE, oldintp); 81955682Smarkm if (bytes > 0) 82055682Smarkm ptransfer ("sent", bytes, &start, &stop); 82155682Smarkm return; 82255682Smarkmabort: 82355682Smarkm signal (SIGINT, oldintr); 82455682Smarkm if (oldintp) 82555682Smarkm signal (SIGPIPE, oldintp); 82655682Smarkm if (!cpend) { 82755682Smarkm code = -1; 82855682Smarkm return; 82955682Smarkm } 83055682Smarkm if (data >= 0) { 83155682Smarkm close (data); 83255682Smarkm data = -1; 83355682Smarkm } 83455682Smarkm if (dout) 83555682Smarkm fclose (dout); 83655682Smarkm getreply (0); 83755682Smarkm code = -1; 83855682Smarkm if (closefunc != NULL && fin != NULL) 83955682Smarkm (*closefunc) (fin); 84055682Smarkm gettimeofday (&stop, (struct timezone *) 0); 84155682Smarkm if (bytes > 0) 84255682Smarkm ptransfer ("sent", bytes, &start, &stop); 84355682Smarkm} 84455682Smarkm 84555682Smarkmjmp_buf recvabort; 84655682Smarkm 84755682Smarkmvoid 84855682Smarkmabortrecv (int sig) 84955682Smarkm{ 85055682Smarkm 85155682Smarkm mflag = 0; 85255682Smarkm abrtflag = 0; 85355682Smarkm printf ("\nreceive aborted\nwaiting for remote to finish abort\n"); 85455682Smarkm fflush (stdout); 85555682Smarkm longjmp (recvabort, 1); 85655682Smarkm} 85755682Smarkm 85855682Smarkmvoid 85955682Smarkmrecvrequest (char *cmd, char *local, char *remote, 86055682Smarkm char *lmode, int printnames, int local_given) 86155682Smarkm{ 86255682Smarkm FILE *fout, *din = 0; 86355682Smarkm int (*closefunc) (FILE *); 86455682Smarkm sighand oldintr, oldintp; 86555682Smarkm int c, d, is_retr, tcrflag, bare_lfs = 0; 86655682Smarkm static size_t bufsize; 86755682Smarkm static char *buf; 86855682Smarkm long bytes = 0, hashbytes = HASHBYTES; 86955682Smarkm struct timeval start, stop; 87055682Smarkm struct stat st; 87155682Smarkm 87255682Smarkm is_retr = strcmp (cmd, "RETR") == 0; 87355682Smarkm if (is_retr && verbose && printnames) { 87455682Smarkm if (local && strcmp (local, "-") != 0) 87555682Smarkm printf ("local: %s ", local); 87655682Smarkm if (remote) 87755682Smarkm printf ("remote: %s\n", remote); 87855682Smarkm } 87955682Smarkm if (proxy && is_retr) { 88055682Smarkm proxtrans (cmd, local, remote); 88155682Smarkm return; 88255682Smarkm } 88355682Smarkm closefunc = NULL; 88455682Smarkm oldintr = NULL; 88555682Smarkm oldintp = NULL; 88655682Smarkm tcrflag = !crflag && is_retr; 88755682Smarkm if (setjmp (recvabort)) { 88855682Smarkm while (cpend) { 88955682Smarkm getreply (0); 89055682Smarkm } 89155682Smarkm if (data >= 0) { 89255682Smarkm close (data); 89355682Smarkm data = -1; 89455682Smarkm } 89555682Smarkm if (oldintr) 89655682Smarkm signal (SIGINT, oldintr); 89755682Smarkm code = -1; 89855682Smarkm return; 89955682Smarkm } 90055682Smarkm oldintr = signal (SIGINT, abortrecv); 90155682Smarkm if (!local_given || (strcmp (local, "-") && *local != '|')) { 90255682Smarkm if (access (local, 2) < 0) { 90355682Smarkm char *dir = strrchr (local, '/'); 90455682Smarkm 90555682Smarkm if (errno != ENOENT && errno != EACCES) { 90655682Smarkm warn ("local: %s", local); 90755682Smarkm signal (SIGINT, oldintr); 90855682Smarkm code = -1; 90955682Smarkm return; 91055682Smarkm } 91155682Smarkm if (dir != NULL) 91255682Smarkm *dir = 0; 91355682Smarkm d = access (dir ? local : ".", 2); 91455682Smarkm if (dir != NULL) 91555682Smarkm *dir = '/'; 91655682Smarkm if (d < 0) { 91755682Smarkm warn ("local: %s", local); 91855682Smarkm signal (SIGINT, oldintr); 91955682Smarkm code = -1; 92055682Smarkm return; 92155682Smarkm } 92255682Smarkm if (!runique && errno == EACCES && 92355682Smarkm chmod (local, 0600) < 0) { 92455682Smarkm warn ("local: %s", local); 92555682Smarkm signal (SIGINT, oldintr); 92655682Smarkm signal (SIGINT, oldintr); 92755682Smarkm code = -1; 92855682Smarkm return; 92955682Smarkm } 93055682Smarkm if (runique && errno == EACCES && 93155682Smarkm (local = gunique (local)) == NULL) { 93255682Smarkm signal (SIGINT, oldintr); 93355682Smarkm code = -1; 93455682Smarkm return; 93555682Smarkm } 93655682Smarkm } else if (runique && (local = gunique (local)) == NULL) { 93755682Smarkm signal(SIGINT, oldintr); 93855682Smarkm code = -1; 93955682Smarkm return; 94055682Smarkm } 94155682Smarkm } 94255682Smarkm if (!is_retr) { 94355682Smarkm if (curtype != TYPE_A) 94455682Smarkm changetype (TYPE_A, 0); 94555682Smarkm } else if (curtype != type) 94655682Smarkm changetype (type, 0); 94755682Smarkm if (initconn ()) { 94855682Smarkm signal (SIGINT, oldintr); 94955682Smarkm code = -1; 95055682Smarkm return; 95155682Smarkm } 95255682Smarkm if (setjmp (recvabort)) 95355682Smarkm goto abort; 95455682Smarkm if (is_retr && restart_point && 95555682Smarkm command ("REST %ld", (long) restart_point) != CONTINUE) 95655682Smarkm return; 95755682Smarkm if (remote) { 95855682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 95955682Smarkm signal (SIGINT, oldintr); 96055682Smarkm return; 96155682Smarkm } 96255682Smarkm } else { 96355682Smarkm if (command ("%s", cmd) != PRELIM) { 96455682Smarkm signal (SIGINT, oldintr); 96555682Smarkm return; 96655682Smarkm } 96755682Smarkm } 96855682Smarkm din = dataconn ("r"); 96955682Smarkm if (din == NULL) 97055682Smarkm goto abort; 97155682Smarkm set_buffer_size (fileno (din), 1); 97255682Smarkm if (local_given && strcmp (local, "-") == 0) 97355682Smarkm fout = stdout; 97455682Smarkm else if (local_given && *local == '|') { 97555682Smarkm oldintp = signal (SIGPIPE, SIG_IGN); 97655682Smarkm fout = popen (local + 1, "w"); 97755682Smarkm if (fout == NULL) { 97855682Smarkm warn ("%s", local + 1); 97955682Smarkm goto abort; 98055682Smarkm } 98155682Smarkm closefunc = pclose; 98255682Smarkm } else { 98355682Smarkm fout = fopen (local, lmode); 98455682Smarkm if (fout == NULL) { 98555682Smarkm warn ("local: %s", local); 98655682Smarkm goto abort; 98755682Smarkm } 98855682Smarkm closefunc = fclose; 98955682Smarkm } 99055682Smarkm buf = alloc_buffer (buf, &bufsize, 99155682Smarkm fstat (fileno (fout), &st) >= 0 ? &st : NULL); 99255682Smarkm if (buf == NULL) 99355682Smarkm goto abort; 99455682Smarkm 99555682Smarkm gettimeofday (&start, (struct timezone *) 0); 99655682Smarkm switch (curtype) { 99755682Smarkm 99855682Smarkm case TYPE_I: 99955682Smarkm case TYPE_L: 100055682Smarkm if (restart_point && 100155682Smarkm lseek (fileno (fout), restart_point, SEEK_SET) < 0) { 100255682Smarkm warn ("local: %s", local); 100355682Smarkm if (closefunc != NULL) 100455682Smarkm (*closefunc) (fout); 100555682Smarkm return; 100655682Smarkm } 100755682Smarkm errno = d = 0; 100855682Smarkm while ((c = sec_read (fileno (din), buf, bufsize)) > 0) { 100955682Smarkm if ((d = write (fileno (fout), buf, c)) != c) 101055682Smarkm break; 101155682Smarkm bytes += c; 101255682Smarkm if (hash) { 101355682Smarkm while (bytes >= hashbytes) { 101455682Smarkm putchar ('#'); 101555682Smarkm hashbytes += HASHBYTES; 101655682Smarkm } 101755682Smarkm fflush (stdout); 101855682Smarkm } 101955682Smarkm } 102055682Smarkm if (hash && bytes > 0) { 102155682Smarkm if (bytes < HASHBYTES) 102255682Smarkm putchar ('#'); 102355682Smarkm putchar ('\n'); 102455682Smarkm fflush (stdout); 102555682Smarkm } 102655682Smarkm if (c < 0) { 102755682Smarkm if (errno != EPIPE) 102855682Smarkm warn ("netin"); 102955682Smarkm bytes = -1; 103055682Smarkm } 103155682Smarkm if (d < c) { 103255682Smarkm if (d < 0) 103355682Smarkm warn ("local: %s", local); 103455682Smarkm else 103555682Smarkm warnx ("%s: short write", local); 103655682Smarkm } 103755682Smarkm break; 103855682Smarkm 103955682Smarkm case TYPE_A: 104055682Smarkm if (restart_point) { 104155682Smarkm int i, n, ch; 104255682Smarkm 104355682Smarkm if (fseek (fout, 0L, SEEK_SET) < 0) 104455682Smarkm goto done; 104555682Smarkm n = restart_point; 104655682Smarkm for (i = 0; i++ < n;) { 104755682Smarkm if ((ch = sec_getc (fout)) == EOF) 104855682Smarkm goto done; 104955682Smarkm if (ch == '\n') 105055682Smarkm i++; 105155682Smarkm } 105255682Smarkm if (fseek (fout, 0L, SEEK_CUR) < 0) { 105355682Smarkm done: 105455682Smarkm warn ("local: %s", local); 105555682Smarkm if (closefunc != NULL) 105655682Smarkm (*closefunc) (fout); 105755682Smarkm return; 105855682Smarkm } 105955682Smarkm } 106055682Smarkm while ((c = sec_getc(din)) != EOF) { 106155682Smarkm if (c == '\n') 106255682Smarkm bare_lfs++; 106355682Smarkm while (c == '\r') { 106455682Smarkm while (hash && (bytes >= hashbytes)) { 106555682Smarkm putchar ('#'); 106655682Smarkm fflush (stdout); 106755682Smarkm hashbytes += HASHBYTES; 106855682Smarkm } 106955682Smarkm bytes++; 107055682Smarkm if ((c = sec_getc (din)) != '\n' || tcrflag) { 107155682Smarkm if (ferror (fout)) 107255682Smarkm goto break2; 107355682Smarkm putc ('\r', fout); 107455682Smarkm if (c == '\0') { 107555682Smarkm bytes++; 107655682Smarkm goto contin2; 107755682Smarkm } 107855682Smarkm if (c == EOF) 107955682Smarkm goto contin2; 108055682Smarkm } 108155682Smarkm } 108255682Smarkm putc (c, fout); 108355682Smarkm bytes++; 108455682Smarkm contin2:; 108555682Smarkm } 108655682Smarkmbreak2: 108755682Smarkm if (bare_lfs) { 108855682Smarkm printf ("WARNING! %d bare linefeeds received in ASCII mode\n", 108955682Smarkm bare_lfs); 109055682Smarkm printf ("File may not have transferred correctly.\n"); 109155682Smarkm } 109255682Smarkm if (hash) { 109355682Smarkm if (bytes < hashbytes) 109455682Smarkm putchar ('#'); 109555682Smarkm putchar ('\n'); 109655682Smarkm fflush (stdout); 109755682Smarkm } 109855682Smarkm if (ferror (din)) { 109955682Smarkm if (errno != EPIPE) 110055682Smarkm warn ("netin"); 110155682Smarkm bytes = -1; 110255682Smarkm } 110355682Smarkm if (ferror (fout)) 110455682Smarkm warn ("local: %s", local); 110555682Smarkm break; 110655682Smarkm } 110755682Smarkm if (closefunc != NULL) 110855682Smarkm (*closefunc) (fout); 110955682Smarkm signal (SIGINT, oldintr); 111055682Smarkm if (oldintp) 111155682Smarkm signal (SIGPIPE, oldintp); 111255682Smarkm fclose (din); 111355682Smarkm gettimeofday (&stop, (struct timezone *) 0); 111455682Smarkm getreply (0); 111555682Smarkm if (bytes > 0 && is_retr) 111655682Smarkm ptransfer ("received", bytes, &start, &stop); 111755682Smarkm return; 111855682Smarkmabort: 111955682Smarkm 112055682Smarkm /* abort using RFC959 recommended IP,SYNC sequence */ 112155682Smarkm 112255682Smarkm if (oldintp) 112355682Smarkm signal (SIGPIPE, oldintr); 112455682Smarkm signal (SIGINT, SIG_IGN); 112555682Smarkm if (!cpend) { 112655682Smarkm code = -1; 112755682Smarkm signal (SIGINT, oldintr); 112855682Smarkm return; 112955682Smarkm } 113055682Smarkm abort_remote(din); 113155682Smarkm code = -1; 113255682Smarkm if (data >= 0) { 113355682Smarkm close (data); 113455682Smarkm data = -1; 113555682Smarkm } 113655682Smarkm if (closefunc != NULL && fout != NULL) 113755682Smarkm (*closefunc) (fout); 113855682Smarkm if (din) 113955682Smarkm fclose (din); 114055682Smarkm gettimeofday (&stop, (struct timezone *) 0); 114155682Smarkm if (bytes > 0) 114255682Smarkm ptransfer ("received", bytes, &start, &stop); 114355682Smarkm signal (SIGINT, oldintr); 114455682Smarkm} 114555682Smarkm 114655682Smarkmstatic int 114755682Smarkmparse_epsv (const char *str) 114855682Smarkm{ 114955682Smarkm char sep; 115055682Smarkm char *end; 115155682Smarkm int port; 115255682Smarkm 115355682Smarkm if (*str == '\0') 115455682Smarkm return -1; 115555682Smarkm sep = *str++; 115655682Smarkm if (sep != *str++) 115755682Smarkm return -1; 115855682Smarkm if (sep != *str++) 115955682Smarkm return -1; 116055682Smarkm port = strtol (str, &end, 0); 116155682Smarkm if (str == end) 116255682Smarkm return -1; 116355682Smarkm if (end[0] != sep || end[1] != '\0') 116455682Smarkm return -1; 116555682Smarkm return htons(port); 116655682Smarkm} 116755682Smarkm 116855682Smarkmstatic int 116955682Smarkmparse_pasv (struct sockaddr_in *sin, const char *str) 117055682Smarkm{ 117155682Smarkm int a0, a1, a2, a3, p0, p1; 117255682Smarkm 117355682Smarkm /* 117455682Smarkm * What we've got at this point is a string of comma separated 117555682Smarkm * one-byte unsigned integer values. The first four are the an IP 117655682Smarkm * address. The fifth is the MSB of the port number, the sixth is the 117755682Smarkm * LSB. From that we'll prepare a sockaddr_in. 117855682Smarkm */ 117955682Smarkm 118055682Smarkm if (sscanf (str, "%d,%d,%d,%d,%d,%d", 118155682Smarkm &a0, &a1, &a2, &a3, &p0, &p1) != 6) { 118255682Smarkm printf ("Passive mode address scan failure. " 118355682Smarkm "Shouldn't happen!\n"); 118455682Smarkm return -1; 118555682Smarkm } 118655682Smarkm if (a0 < 0 || a0 > 255 || 118755682Smarkm a1 < 0 || a1 > 255 || 118855682Smarkm a2 < 0 || a2 > 255 || 118955682Smarkm a3 < 0 || a3 > 255 || 119055682Smarkm p0 < 0 || p0 > 255 || 119155682Smarkm p1 < 0 || p1 > 255) { 119255682Smarkm printf ("Can't parse passive mode string.\n"); 119355682Smarkm return -1; 119455682Smarkm } 119555682Smarkm memset (sin, 0, sizeof(*sin)); 119655682Smarkm sin->sin_family = AF_INET; 119755682Smarkm sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) | 119855682Smarkm (a2 << 8) | a3); 119955682Smarkm sin->sin_port = htons ((p0 << 8) | p1); 120055682Smarkm return 0; 120155682Smarkm} 120255682Smarkm 120355682Smarkmstatic int 120455682Smarkmpassive_mode (void) 120555682Smarkm{ 120655682Smarkm int port; 120755682Smarkm 120855682Smarkm data = socket (myctladdr->sa_family, SOCK_STREAM, 0); 120955682Smarkm if (data < 0) { 121055682Smarkm warn ("socket"); 121155682Smarkm return (1); 121255682Smarkm } 121355682Smarkm if (options & SO_DEBUG) 121455682Smarkm socket_set_debug (data); 121555682Smarkm if (command ("EPSV") != COMPLETE) { 121655682Smarkm if (command ("PASV") != COMPLETE) { 121755682Smarkm printf ("Passive mode refused.\n"); 121855682Smarkm goto bad; 121955682Smarkm } 122055682Smarkm } 122155682Smarkm 122255682Smarkm /* 122355682Smarkm * Parse the reply to EPSV or PASV 122455682Smarkm */ 122555682Smarkm 122655682Smarkm port = parse_epsv (pasv); 122755682Smarkm if (port > 0) { 122855682Smarkm data_addr->sa_family = myctladdr->sa_family; 122955682Smarkm socket_set_address_and_port (data_addr, 123055682Smarkm socket_get_address (hisctladdr), 123155682Smarkm port); 123255682Smarkm } else { 123355682Smarkm if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0) 123455682Smarkm goto bad; 123555682Smarkm } 123655682Smarkm 123755682Smarkm if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) { 123855682Smarkm warn ("connect"); 123955682Smarkm goto bad; 124055682Smarkm } 124155682Smarkm#ifdef IPTOS_THROUGHPUT 124255682Smarkm socket_set_tos (data, IPTOS_THROUGHPUT); 124355682Smarkm#endif 124455682Smarkm return (0); 124555682Smarkmbad: 124655682Smarkm close (data); 124755682Smarkm data = -1; 124855682Smarkm sendport = 1; 124955682Smarkm return (1); 125055682Smarkm} 125155682Smarkm 125255682Smarkm 125355682Smarkmstatic int 125455682Smarkmactive_mode (void) 125555682Smarkm{ 125655682Smarkm int tmpno = 0; 125772445Sassar socklen_t len; 125855682Smarkm int result; 125955682Smarkm 126055682Smarkmnoport: 126155682Smarkm data_addr->sa_family = myctladdr->sa_family; 126255682Smarkm socket_set_address_and_port (data_addr, socket_get_address (myctladdr), 126355682Smarkm sendport ? 0 : socket_get_port (myctladdr)); 126455682Smarkm 126555682Smarkm if (data != -1) 126655682Smarkm close (data); 126755682Smarkm data = socket (data_addr->sa_family, SOCK_STREAM, 0); 126855682Smarkm if (data < 0) { 126955682Smarkm warn ("socket"); 127055682Smarkm if (tmpno) 127155682Smarkm sendport = 1; 127255682Smarkm return (1); 127355682Smarkm } 127455682Smarkm if (!sendport) 127555682Smarkm socket_set_reuseaddr (data, 1); 127655682Smarkm if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) { 127755682Smarkm warn ("bind"); 127855682Smarkm goto bad; 127955682Smarkm } 128055682Smarkm if (options & SO_DEBUG) 128155682Smarkm socket_set_debug (data); 128255682Smarkm len = sizeof (data_addr_ss); 128355682Smarkm if (getsockname (data, data_addr, &len) < 0) { 128455682Smarkm warn ("getsockname"); 128555682Smarkm goto bad; 128655682Smarkm } 128755682Smarkm if (listen (data, 1) < 0) 128855682Smarkm warn ("listen"); 128955682Smarkm if (sendport) { 129055682Smarkm char addr_str[256]; 129155682Smarkm int inet_af; 129255682Smarkm int overbose; 129355682Smarkm 129455682Smarkm if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr), 129555682Smarkm addr_str, sizeof(addr_str)) == NULL) 129655682Smarkm errx (1, "inet_ntop failed"); 129755682Smarkm switch (data_addr->sa_family) { 129855682Smarkm case AF_INET : 129955682Smarkm inet_af = 1; 130055682Smarkm break; 130155682Smarkm#ifdef HAVE_IPV6 130255682Smarkm case AF_INET6 : 130355682Smarkm inet_af = 2; 130455682Smarkm break; 130555682Smarkm#endif 130655682Smarkm default : 130755682Smarkm errx (1, "bad address family %d", data_addr->sa_family); 130855682Smarkm } 130955682Smarkm 131055682Smarkm 131155682Smarkm overbose = verbose; 131255682Smarkm if (debug == 0) 131355682Smarkm verbose = -1; 131455682Smarkm 1315103423Snectar result = command ("EPRT |%d|%s|%d|", 1316103423Snectar inet_af, addr_str, 1317103423Snectar ntohs(socket_get_port (data_addr))); 131855682Smarkm verbose = overbose; 131955682Smarkm 132055682Smarkm if (result == ERROR) { 132155682Smarkm struct sockaddr_in *sin = (struct sockaddr_in *)data_addr; 132255682Smarkm 132355682Smarkm unsigned int a = ntohl(sin->sin_addr.s_addr); 132455682Smarkm unsigned int p = ntohs(sin->sin_port); 132555682Smarkm 132655682Smarkm if (data_addr->sa_family != AF_INET) { 132755682Smarkm warnx ("remote server doesn't support EPRT"); 132855682Smarkm goto bad; 132955682Smarkm } 133055682Smarkm 133155682Smarkm result = command("PORT %d,%d,%d,%d,%d,%d", 133255682Smarkm (a >> 24) & 0xff, 133355682Smarkm (a >> 16) & 0xff, 133455682Smarkm (a >> 8) & 0xff, 133555682Smarkm a & 0xff, 133655682Smarkm (p >> 8) & 0xff, 133755682Smarkm p & 0xff); 133855682Smarkm if (result == ERROR && sendport == -1) { 133955682Smarkm sendport = 0; 134055682Smarkm tmpno = 1; 134155682Smarkm goto noport; 134255682Smarkm } 134355682Smarkm return (result != COMPLETE); 134455682Smarkm } 134555682Smarkm return result != COMPLETE; 134655682Smarkm } 134755682Smarkm if (tmpno) 134855682Smarkm sendport = 1; 134955682Smarkm 135055682Smarkm 135155682Smarkm#ifdef IPTOS_THROUGHPUT 135255682Smarkm socket_set_tos (data, IPTOS_THROUGHPUT); 135355682Smarkm#endif 135455682Smarkm return (0); 135555682Smarkmbad: 135655682Smarkm close (data); 135755682Smarkm data = -1; 135855682Smarkm if (tmpno) 135955682Smarkm sendport = 1; 136055682Smarkm return (1); 136155682Smarkm} 136255682Smarkm 136355682Smarkm/* 136455682Smarkm * Need to start a listen on the data channel before we send the command, 136555682Smarkm * otherwise the server's connect may fail. 136655682Smarkm */ 136755682Smarkmint 136855682Smarkminitconn (void) 136955682Smarkm{ 137055682Smarkm if (passivemode) 137155682Smarkm return passive_mode (); 137255682Smarkm else 137355682Smarkm return active_mode (); 137455682Smarkm} 137555682Smarkm 137655682SmarkmFILE * 137755682Smarkmdataconn (const char *lmode) 137855682Smarkm{ 137955682Smarkm struct sockaddr_storage from_ss; 138055682Smarkm struct sockaddr *from = (struct sockaddr *)&from_ss; 138172445Sassar socklen_t fromlen = sizeof(from_ss); 138272445Sassar int s; 138355682Smarkm 138455682Smarkm if (passivemode) 138555682Smarkm return (fdopen (data, lmode)); 138655682Smarkm 138755682Smarkm s = accept (data, from, &fromlen); 138855682Smarkm if (s < 0) { 138955682Smarkm warn ("accept"); 139055682Smarkm close (data), data = -1; 139155682Smarkm return (NULL); 139255682Smarkm } 139355682Smarkm close (data); 139455682Smarkm data = s; 139555682Smarkm#ifdef IPTOS_THROUGHPUT 139655682Smarkm socket_set_tos (s, IPTOS_THROUGHPUT); 139755682Smarkm#endif 139855682Smarkm return (fdopen (data, lmode)); 139955682Smarkm} 140055682Smarkm 140155682Smarkmvoid 140255682Smarkmptransfer (char *direction, long int bytes, 140355682Smarkm struct timeval * t0, struct timeval * t1) 140455682Smarkm{ 140555682Smarkm struct timeval td; 140655682Smarkm float s; 140755682Smarkm float bs; 140855682Smarkm int prec; 140955682Smarkm char *unit; 141055682Smarkm 141155682Smarkm if (verbose) { 141255682Smarkm td.tv_sec = t1->tv_sec - t0->tv_sec; 141355682Smarkm td.tv_usec = t1->tv_usec - t0->tv_usec; 141455682Smarkm if (td.tv_usec < 0) { 141555682Smarkm td.tv_sec--; 141655682Smarkm td.tv_usec += 1000000; 141755682Smarkm } 141855682Smarkm s = td.tv_sec + (td.tv_usec / 1000000.); 141955682Smarkm bs = bytes / (s ? s : 1); 142055682Smarkm if (bs >= 1048576) { 142155682Smarkm bs /= 1048576; 142255682Smarkm unit = "M"; 142355682Smarkm prec = 2; 142455682Smarkm } else if (bs >= 1024) { 142555682Smarkm bs /= 1024; 142655682Smarkm unit = "k"; 142755682Smarkm prec = 1; 142855682Smarkm } else { 142955682Smarkm unit = ""; 143055682Smarkm prec = 0; 143155682Smarkm } 143255682Smarkm 143355682Smarkm printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", 143455682Smarkm bytes, direction, s, prec, bs, unit); 143555682Smarkm } 143655682Smarkm} 143755682Smarkm 143855682Smarkmvoid 143955682Smarkmpsabort (int sig) 144055682Smarkm{ 144155682Smarkm 144255682Smarkm abrtflag++; 144355682Smarkm} 144455682Smarkm 144555682Smarkmvoid 144655682Smarkmpswitch (int flag) 144755682Smarkm{ 144855682Smarkm sighand oldintr; 144955682Smarkm static struct comvars { 145055682Smarkm int connect; 145155682Smarkm char name[MaxHostNameLen]; 145255682Smarkm struct sockaddr_storage mctl; 145355682Smarkm struct sockaddr_storage hctl; 145455682Smarkm FILE *in; 145555682Smarkm FILE *out; 145655682Smarkm int tpe; 145755682Smarkm int curtpe; 145855682Smarkm int cpnd; 145955682Smarkm int sunqe; 146055682Smarkm int runqe; 146155682Smarkm int mcse; 146255682Smarkm int ntflg; 146355682Smarkm char nti[17]; 146455682Smarkm char nto[17]; 146555682Smarkm int mapflg; 146655682Smarkm char mi[MaxPathLen]; 146755682Smarkm char mo[MaxPathLen]; 146855682Smarkm } proxstruct, tmpstruct; 146955682Smarkm struct comvars *ip, *op; 147055682Smarkm 147155682Smarkm abrtflag = 0; 147255682Smarkm oldintr = signal (SIGINT, psabort); 147355682Smarkm if (flag) { 147455682Smarkm if (proxy) 147555682Smarkm return; 147655682Smarkm ip = &tmpstruct; 147755682Smarkm op = &proxstruct; 147855682Smarkm proxy++; 147955682Smarkm } else { 148055682Smarkm if (!proxy) 148155682Smarkm return; 148255682Smarkm ip = &proxstruct; 148355682Smarkm op = &tmpstruct; 148455682Smarkm proxy = 0; 148555682Smarkm } 148655682Smarkm ip->connect = connected; 148755682Smarkm connected = op->connect; 148855682Smarkm if (hostname) { 148955682Smarkm strlcpy (ip->name, hostname, sizeof (ip->name)); 149055682Smarkm } else 149155682Smarkm ip->name[0] = 0; 149255682Smarkm hostname = op->name; 149355682Smarkm ip->hctl = hisctladdr_ss; 149455682Smarkm hisctladdr_ss = op->hctl; 149555682Smarkm ip->mctl = myctladdr_ss; 149655682Smarkm myctladdr_ss = op->mctl; 149755682Smarkm ip->in = cin; 149855682Smarkm cin = op->in; 149955682Smarkm ip->out = cout; 150055682Smarkm cout = op->out; 150155682Smarkm ip->tpe = type; 150255682Smarkm type = op->tpe; 150355682Smarkm ip->curtpe = curtype; 150455682Smarkm curtype = op->curtpe; 150555682Smarkm ip->cpnd = cpend; 150655682Smarkm cpend = op->cpnd; 150755682Smarkm ip->sunqe = sunique; 150855682Smarkm sunique = op->sunqe; 150955682Smarkm ip->runqe = runique; 151055682Smarkm runique = op->runqe; 151155682Smarkm ip->mcse = mcase; 151255682Smarkm mcase = op->mcse; 151355682Smarkm ip->ntflg = ntflag; 151455682Smarkm ntflag = op->ntflg; 151555682Smarkm strlcpy (ip->nti, ntin, sizeof (ip->nti)); 151655682Smarkm strlcpy (ntin, op->nti, 17); 151755682Smarkm strlcpy (ip->nto, ntout, sizeof (ip->nto)); 151855682Smarkm strlcpy (ntout, op->nto, 17); 151955682Smarkm ip->mapflg = mapflag; 152055682Smarkm mapflag = op->mapflg; 152155682Smarkm strlcpy (ip->mi, mapin, MaxPathLen); 152255682Smarkm strlcpy (mapin, op->mi, MaxPathLen); 152355682Smarkm strlcpy (ip->mo, mapout, MaxPathLen); 152455682Smarkm strlcpy (mapout, op->mo, MaxPathLen); 152555682Smarkm signal(SIGINT, oldintr); 152655682Smarkm if (abrtflag) { 152755682Smarkm abrtflag = 0; 152855682Smarkm (*oldintr) (SIGINT); 152955682Smarkm } 153055682Smarkm} 153155682Smarkm 153255682Smarkmvoid 153355682Smarkmabortpt (int sig) 153455682Smarkm{ 153555682Smarkm 153655682Smarkm printf ("\n"); 153755682Smarkm fflush (stdout); 153855682Smarkm ptabflg++; 153955682Smarkm mflag = 0; 154055682Smarkm abrtflag = 0; 154155682Smarkm longjmp (ptabort, 1); 154255682Smarkm} 154355682Smarkm 154455682Smarkmvoid 154555682Smarkmproxtrans (char *cmd, char *local, char *remote) 154655682Smarkm{ 154755682Smarkm sighand oldintr; 154855682Smarkm int secndflag = 0, prox_type, nfnd; 154955682Smarkm char *cmd2; 155055682Smarkm fd_set mask; 155155682Smarkm 155255682Smarkm if (strcmp (cmd, "RETR")) 155355682Smarkm cmd2 = "RETR"; 155455682Smarkm else 155555682Smarkm cmd2 = runique ? "STOU" : "STOR"; 155655682Smarkm if ((prox_type = type) == 0) { 155755682Smarkm if (unix_server && unix_proxy) 155855682Smarkm prox_type = TYPE_I; 155955682Smarkm else 156055682Smarkm prox_type = TYPE_A; 156155682Smarkm } 156255682Smarkm if (curtype != prox_type) 156355682Smarkm changetype (prox_type, 1); 156455682Smarkm if (command ("PASV") != COMPLETE) { 156555682Smarkm printf ("proxy server does not support third party transfers.\n"); 156655682Smarkm return; 156755682Smarkm } 156855682Smarkm pswitch (0); 156955682Smarkm if (!connected) { 157055682Smarkm printf ("No primary connection\n"); 157155682Smarkm pswitch (1); 157255682Smarkm code = -1; 157355682Smarkm return; 157455682Smarkm } 157555682Smarkm if (curtype != prox_type) 157655682Smarkm changetype (prox_type, 1); 157755682Smarkm if (command ("PORT %s", pasv) != COMPLETE) { 157855682Smarkm pswitch (1); 157955682Smarkm return; 158055682Smarkm } 158155682Smarkm if (setjmp (ptabort)) 158255682Smarkm goto abort; 158355682Smarkm oldintr = signal (SIGINT, abortpt); 158455682Smarkm if (command ("%s %s", cmd, remote) != PRELIM) { 158555682Smarkm signal (SIGINT, oldintr); 158655682Smarkm pswitch (1); 158755682Smarkm return; 158855682Smarkm } 158955682Smarkm sleep (2); 159055682Smarkm pswitch (1); 159155682Smarkm secndflag++; 159255682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) 159355682Smarkm goto abort; 159455682Smarkm ptflag++; 159555682Smarkm getreply (0); 159655682Smarkm pswitch (0); 159755682Smarkm getreply (0); 159855682Smarkm signal (SIGINT, oldintr); 159955682Smarkm pswitch (1); 160055682Smarkm ptflag = 0; 160155682Smarkm printf ("local: %s remote: %s\n", local, remote); 160255682Smarkm return; 160355682Smarkmabort: 160455682Smarkm signal (SIGINT, SIG_IGN); 160555682Smarkm ptflag = 0; 160655682Smarkm if (strcmp (cmd, "RETR") && !proxy) 160755682Smarkm pswitch (1); 160855682Smarkm else if (!strcmp (cmd, "RETR") && proxy) 160955682Smarkm pswitch (0); 161055682Smarkm if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 161155682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) { 161255682Smarkm pswitch (0); 161355682Smarkm if (cpend) 161455682Smarkm abort_remote ((FILE *) NULL); 161555682Smarkm } 161655682Smarkm pswitch (1); 161755682Smarkm if (ptabflg) 161855682Smarkm code = -1; 161955682Smarkm signal (SIGINT, oldintr); 162055682Smarkm return; 162155682Smarkm } 162255682Smarkm if (cpend) 162355682Smarkm abort_remote ((FILE *) NULL); 162455682Smarkm pswitch (!proxy); 162555682Smarkm if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 162655682Smarkm if (command ("%s %s", cmd2, local) != PRELIM) { 162755682Smarkm pswitch (0); 162855682Smarkm if (cpend) 162955682Smarkm abort_remote ((FILE *) NULL); 163055682Smarkm pswitch (1); 163155682Smarkm if (ptabflg) 163255682Smarkm code = -1; 163355682Smarkm signal (SIGINT, oldintr); 163455682Smarkm return; 163555682Smarkm } 163655682Smarkm } 163755682Smarkm if (cpend) 163855682Smarkm abort_remote ((FILE *) NULL); 163955682Smarkm pswitch (!proxy); 164055682Smarkm if (cpend) { 164155682Smarkm FD_ZERO (&mask); 164272445Sassar if (fileno(cin) >= FD_SETSIZE) 164372445Sassar errx (1, "fd too large"); 164455682Smarkm FD_SET (fileno (cin), &mask); 164555682Smarkm if ((nfnd = empty (&mask, 10)) <= 0) { 164655682Smarkm if (nfnd < 0) { 164755682Smarkm warn ("abort"); 164855682Smarkm } 164955682Smarkm if (ptabflg) 165055682Smarkm code = -1; 165155682Smarkm lostpeer (0); 165255682Smarkm } 165355682Smarkm getreply (0); 165455682Smarkm getreply (0); 165555682Smarkm } 165655682Smarkm if (proxy) 165755682Smarkm pswitch (0); 165855682Smarkm pswitch (1); 165955682Smarkm if (ptabflg) 166055682Smarkm code = -1; 166155682Smarkm signal (SIGINT, oldintr); 166255682Smarkm} 166355682Smarkm 166455682Smarkmvoid 166555682Smarkmreset (int argc, char **argv) 166655682Smarkm{ 166755682Smarkm fd_set mask; 166855682Smarkm int nfnd = 1; 166955682Smarkm 167055682Smarkm FD_ZERO (&mask); 167155682Smarkm while (nfnd > 0) { 167272445Sassar if (fileno (cin) >= FD_SETSIZE) 167372445Sassar errx (1, "fd too large"); 167455682Smarkm FD_SET (fileno (cin), &mask); 167555682Smarkm if ((nfnd = empty (&mask, 0)) < 0) { 167655682Smarkm warn ("reset"); 167755682Smarkm code = -1; 167855682Smarkm lostpeer(0); 167955682Smarkm } else if (nfnd) { 168055682Smarkm getreply(0); 168155682Smarkm } 168255682Smarkm } 168355682Smarkm} 168455682Smarkm 168555682Smarkmchar * 168655682Smarkmgunique (char *local) 168755682Smarkm{ 168855682Smarkm static char new[MaxPathLen]; 168955682Smarkm char *cp = strrchr (local, '/'); 169055682Smarkm int d, count = 0; 169155682Smarkm char ext = '1'; 169255682Smarkm 169355682Smarkm if (cp) 169455682Smarkm *cp = '\0'; 169555682Smarkm d = access (cp ? local : ".", 2); 169655682Smarkm if (cp) 169755682Smarkm *cp = '/'; 169855682Smarkm if (d < 0) { 169955682Smarkm warn ("local: %s", local); 170055682Smarkm return NULL; 170155682Smarkm } 170255682Smarkm strlcpy (new, local, sizeof(new)); 170355682Smarkm cp = new + strlen(new); 170455682Smarkm *cp++ = '.'; 170555682Smarkm while (!d) { 170655682Smarkm if (++count == 100) { 170755682Smarkm printf ("runique: can't find unique file name.\n"); 170855682Smarkm return NULL; 170955682Smarkm } 171055682Smarkm *cp++ = ext; 171155682Smarkm *cp = '\0'; 171255682Smarkm if (ext == '9') 171355682Smarkm ext = '0'; 171455682Smarkm else 171555682Smarkm ext++; 171655682Smarkm if ((d = access (new, 0)) < 0) 171755682Smarkm break; 171855682Smarkm if (ext != '0') 171955682Smarkm cp--; 172055682Smarkm else if (*(cp - 2) == '.') 172155682Smarkm *(cp - 1) = '1'; 172255682Smarkm else { 172355682Smarkm *(cp - 2) = *(cp - 2) + 1; 172455682Smarkm cp--; 172555682Smarkm } 172655682Smarkm } 172755682Smarkm return (new); 172855682Smarkm} 172955682Smarkm 173055682Smarkmvoid 173155682Smarkmabort_remote (FILE * din) 173255682Smarkm{ 173355682Smarkm char buf[BUFSIZ]; 173455682Smarkm int nfnd; 173555682Smarkm fd_set mask; 173655682Smarkm 173755682Smarkm /* 173855682Smarkm * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 173955682Smarkm * after urgent byte rather than before as is protocol now 174055682Smarkm */ 174155682Smarkm snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC); 174255682Smarkm if (send (fileno (cout), buf, 3, MSG_OOB) != 3) 174355682Smarkm warn ("abort"); 1744142403Snectar fprintf (cout, "%c", DM); 1745142403Snectar sec_fprintf(cout, "ABOR"); 1746142403Snectar sec_fflush (cout); 1747142403Snectar fprintf (cout, "\r\n"); 1748142403Snectar fflush(cout); 174955682Smarkm FD_ZERO (&mask); 175072445Sassar if (fileno (cin) >= FD_SETSIZE) 175172445Sassar errx (1, "fd too large"); 175255682Smarkm FD_SET (fileno (cin), &mask); 175355682Smarkm if (din) { 175472445Sassar if (fileno (din) >= FD_SETSIZE) 175572445Sassar errx (1, "fd too large"); 175655682Smarkm FD_SET (fileno (din), &mask); 175755682Smarkm } 175855682Smarkm if ((nfnd = empty (&mask, 10)) <= 0) { 175955682Smarkm if (nfnd < 0) { 176055682Smarkm warn ("abort"); 176155682Smarkm } 176255682Smarkm if (ptabflg) 176355682Smarkm code = -1; 176455682Smarkm lostpeer (0); 176555682Smarkm } 176655682Smarkm if (din && FD_ISSET (fileno (din), &mask)) { 176755682Smarkm while (read (fileno (din), buf, BUFSIZ) > 0) 176855682Smarkm /* LOOP */ ; 176955682Smarkm } 177055682Smarkm if (getreply (0) == ERROR && code == 552) { 177155682Smarkm /* 552 needed for nic style abort */ 177255682Smarkm getreply (0); 177355682Smarkm } 177455682Smarkm getreply (0); 177555682Smarkm} 1776