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