ftp.c revision 142403
1230363Sdas/*
2230363Sdas * Copyright (c) 1985, 1989, 1993, 1994
3230363Sdas *	The Regents of the University of California.  All rights reserved.
4230363Sdas *
5230363Sdas * Redistribution and use in source and binary forms, with or without
6230363Sdas * modification, are permitted provided that the following conditions
7230363Sdas * are met:
8230363Sdas * 1. Redistributions of source code must retain the above copyright
9230363Sdas *    notice, this list of conditions and the following disclaimer.
10230363Sdas * 2. Redistributions in binary form must reproduce the above copyright
11230363Sdas *    notice, this list of conditions and the following disclaimer in the
12230363Sdas *    documentation and/or other materials provided with the distribution.
13230363Sdas * 3. All advertising materials mentioning features or use of this software
14230363Sdas *    must display the following acknowledgement:
15230363Sdas *	This product includes software developed by the University of
16230363Sdas *	California, Berkeley and its contributors.
17230363Sdas * 4. Neither the name of the University nor the names of its contributors
18230363Sdas *    may be used to endorse or promote products derived from this software
19230363Sdas *    without specific prior written permission.
20230363Sdas *
21230363Sdas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22230363Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23230363Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24230363Sdas * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25230363Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26230363Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27230363Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "ftp_locl.h"
35RCSID ("$Id: ftp.c,v 1.75.2.1 2004/08/20 14:59:06 lha Exp $");
36
37struct sockaddr_storage hisctladdr_ss;
38struct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss;
39struct sockaddr_storage data_addr_ss;
40struct sockaddr *data_addr  = (struct sockaddr *)&data_addr_ss;
41struct sockaddr_storage myctladdr_ss;
42struct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss;
43int data = -1;
44int abrtflag = 0;
45jmp_buf ptabort;
46int ptabflg;
47int ptflag = 0;
48off_t restart_point = 0;
49
50
51FILE *cin, *cout;
52
53typedef void (*sighand) (int);
54
55char *
56hookup (const char *host, int port)
57{
58    static char hostnamebuf[MaxHostNameLen];
59    struct addrinfo *ai, *a;
60    struct addrinfo hints;
61    int error;
62    char portstr[NI_MAXSERV];
63    socklen_t len;
64    int s;
65
66    memset (&hints, 0, sizeof(hints));
67    hints.ai_socktype = SOCK_STREAM;
68    hints.ai_protocol = IPPROTO_TCP;
69    hints.ai_flags    = AI_CANONNAME;
70
71    snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
72
73    error = getaddrinfo (host, portstr, &hints, &ai);
74    if (error) {
75	warnx ("%s: %s", host, gai_strerror(error));
76	code = -1;
77	return NULL;
78    }
79    strlcpy (hostnamebuf, host, sizeof(hostnamebuf));
80    hostname = hostnamebuf;
81
82    for (a = ai; a != NULL; a = a->ai_next) {
83	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
84	if (s < 0)
85	    continue;
86
87	if (a->ai_canonname != NULL)
88	    strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf));
89
90	memcpy (hisctladdr, a->ai_addr, a->ai_addrlen);
91
92	error = connect (s, a->ai_addr, a->ai_addrlen);
93	if (error < 0) {
94	    char addrstr[256];
95
96	    if (getnameinfo (a->ai_addr, a->ai_addrlen,
97			     addrstr, sizeof(addrstr),
98			     NULL, 0, NI_NUMERICHOST) != 0)
99		strlcpy (addrstr, "unknown address", sizeof(addrstr));
100
101	    warn ("connect %s", addrstr);
102	    close (s);
103	    continue;
104	}
105	break;
106    }
107    freeaddrinfo (ai);
108    if (error < 0) {
109	warnx ("failed to contact %s", host);
110	code = -1;
111	return NULL;
112    }
113
114    len = sizeof(myctladdr_ss);
115    if (getsockname (s, myctladdr, &len) < 0) {
116	warn ("getsockname");
117	code = -1;
118	close (s);
119	return NULL;
120    }
121#ifdef IPTOS_LOWDELAY
122    socket_set_tos (s, IPTOS_LOWDELAY);
123#endif
124    cin = fdopen (s, "r");
125    cout = fdopen (s, "w");
126    if (cin == NULL || cout == NULL) {
127	warnx ("fdopen failed.");
128	if (cin)
129	    fclose (cin);
130	if (cout)
131	    fclose (cout);
132	code = -1;
133	goto bad;
134    }
135    if (verbose)
136	printf ("Connected to %s.\n", hostname);
137    if (getreply (0) > 2) {	/* read startup message from server */
138	if (cin)
139	    fclose (cin);
140	if (cout)
141	    fclose (cout);
142	code = -1;
143	goto bad;
144    }
145#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
146    {
147	int on = 1;
148
149	if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
150	    < 0 && debug) {
151	    warn ("setsockopt");
152	}
153    }
154#endif				/* SO_OOBINLINE */
155
156    return (hostname);
157bad:
158    close (s);
159    return NULL;
160}
161
162int
163login (char *host)
164{
165    char tmp[80];
166    char defaultpass[128];
167    char *user, *pass, *acct;
168    int n, aflag = 0;
169
170    char *myname = NULL;
171    struct passwd *pw = k_getpwuid(getuid());
172
173    if (pw != NULL)
174	myname = pw->pw_name;
175
176    user = pass = acct = 0;
177
178    if(sec_login(host))
179	printf("\n*** Using plaintext user and password ***\n\n");
180    else{
181	printf("Authentication successful.\n\n");
182    }
183
184    if (ruserpass (host, &user, &pass, &acct) < 0) {
185	code = -1;
186	return (0);
187    }
188    while (user == NULL) {
189	if (myname)
190	    printf ("Name (%s:%s): ", host, myname);
191	else
192	    printf ("Name (%s): ", host);
193	*tmp = '\0';
194	if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL)
195	    tmp[strlen (tmp) - 1] = '\0';
196	if (*tmp == '\0')
197	    user = myname;
198	else
199	    user = tmp;
200    }
201    strlcpy(username, user, sizeof(username));
202    n = command("USER %s", user);
203    if (n == COMPLETE)
204       n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */
205    else if(n == CONTINUE) {
206	if (pass == NULL) {
207	    char prompt[128];
208	    if(myname &&
209	       (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))) {
210		snprintf(defaultpass, sizeof(defaultpass),
211			 "%s@%s", myname, mydomain);
212		snprintf(prompt, sizeof(prompt),
213			 "Password (%s): ", defaultpass);
214	    } else if (sec_complete) {
215		pass = myname;
216	    } else {
217		*defaultpass = '\0';
218		snprintf(prompt, sizeof(prompt), "Password: ");
219	    }
220	    if (pass == NULL) {
221		pass = defaultpass;
222		des_read_pw_string (tmp, sizeof (tmp), prompt, 0);
223		if (tmp[0])
224		    pass = tmp;
225	    }
226	}
227	n = command ("PASS %s", pass);
228    }
229    if (n == CONTINUE) {
230	aflag++;
231	acct = tmp;
232	des_read_pw_string (acct, 128, "Account:", 0);
233	n = command ("ACCT %s", acct);
234    }
235    if (n != COMPLETE) {
236	warnx ("Login failed.");
237	return (0);
238    }
239    if (!aflag && acct != NULL)
240	command ("ACCT %s", acct);
241    if (proxy)
242	return (1);
243    for (n = 0; n < macnum; ++n) {
244	if (!strcmp("init", macros[n].mac_name)) {
245	    strlcpy (line, "$init", sizeof (line));
246	    makeargv();
247	    domacro(margc, margv);
248	    break;
249	}
250    }
251    sec_set_protection_level ();
252    return (1);
253}
254
255void
256cmdabort (int sig)
257{
258
259    printf ("\n");
260    fflush (stdout);
261    abrtflag++;
262    if (ptflag)
263	longjmp (ptabort, 1);
264}
265
266int
267command (char *fmt,...)
268{
269    va_list ap;
270    int r;
271    sighand oldintr;
272
273    abrtflag = 0;
274    if (cout == NULL) {
275	warn ("No control connection for command");
276	code = -1;
277	return (0);
278    }
279    oldintr = signal(SIGINT, cmdabort);
280    if(debug){
281	printf("---> ");
282	if (strncmp("PASS ", fmt, 5) == 0)
283	    printf("PASS XXXX");
284	else {
285	    va_start(ap, fmt);
286	    vfprintf(stdout, fmt, ap);
287	    va_end(ap);
288	}
289    }
290    va_start(ap, fmt);
291    sec_vfprintf(cout, fmt, ap);
292    va_end(ap);
293    if(debug){
294	printf("\n");
295	fflush(stdout);
296    }
297    fprintf (cout, "\r\n");
298    fflush (cout);
299    cpend = 1;
300    r = getreply (!strcmp (fmt, "QUIT"));
301    if (abrtflag && oldintr != SIG_IGN)
302	(*oldintr) (SIGINT);
303    signal (SIGINT, oldintr);
304    return (r);
305}
306
307char reply_string[BUFSIZ];	/* last line of previous reply */
308
309int
310getreply (int expecteof)
311{
312    char *p;
313    char *lead_string;
314    int c;
315    struct sigaction sa, osa;
316    char buf[8192];
317    int reply_code;
318    int long_warn = 0;
319
320    sigemptyset (&sa.sa_mask);
321    sa.sa_flags = 0;
322    sa.sa_handler = cmdabort;
323    sigaction (SIGINT, &sa, &osa);
324
325    p = buf;
326
327    reply_code = 0;
328    while (1) {
329	c = getc (cin);
330	switch (c) {
331	case EOF:
332	    if (expecteof) {
333		sigaction (SIGINT, &osa, NULL);
334		code = 221;
335		return 0;
336	    }
337	    lostpeer (0);
338	    if (verbose) {
339		printf ("421 Service not available, "
340			"remote server has closed connection\n");
341		fflush (stdout);
342	    }
343	    code = 421;
344	    return (4);
345	case IAC:
346	    c = getc (cin);
347	    if (c == WILL || c == WONT)
348		fprintf (cout, "%c%c%c", IAC, DONT, getc (cin));
349	    if (c == DO || c == DONT)
350		fprintf (cout, "%c%c%c", IAC, WONT, getc (cin));
351	    continue;
352	case '\n':
353	    *p++ = '\0';
354	    if(isdigit(buf[0])){
355		sscanf(buf, "%d", &code);
356		if(code == 631){
357		    code = 0;
358		    sec_read_msg(buf, prot_safe);
359		    sscanf(buf, "%d", &code);
360		    lead_string = "S:";
361		} else if(code == 632){
362		    code = 0;
363		    sec_read_msg(buf, prot_private);
364		    sscanf(buf, "%d", &code);
365		    lead_string = "P:";
366		}else if(code == 633){
367		    code = 0;
368		    sec_read_msg(buf, prot_confidential);
369		    sscanf(buf, "%d", &code);
370		    lead_string = "C:";
371		}else if(sec_complete)
372		    lead_string = "!!";
373		else
374		    lead_string = "";
375		if(code != 0 && reply_code == 0)
376		    reply_code = code;
377		if (verbose > 0 || (verbose > -1 && code > 499))
378		    fprintf (stdout, "%s%s\n", lead_string, buf);
379		if (code == reply_code && buf[3] == ' ') {
380		    strlcpy (reply_string, buf, sizeof(reply_string));
381		    if (code >= 200)
382			cpend = 0;
383		    sigaction (SIGINT, &osa, NULL);
384		    if (code == 421)
385			lostpeer (0);
386#if 1
387		    if (abrtflag &&
388			osa.sa_handler != cmdabort &&
389			osa.sa_handler != SIG_IGN)
390			osa.sa_handler (SIGINT);
391#endif
392		    if (code == 227 || code == 229) {
393			char *p;
394
395			p = strchr (reply_string, '(');
396			if (p) {
397			    p++;
398			    strlcpy(pasv, p, sizeof(pasv));
399			    p = strrchr(pasv, ')');
400			    if (p)
401				*p = '\0';
402			}
403		    }
404		    return code / 100;
405		}
406	    }else{
407		if(verbose > 0 || (verbose > -1 && code > 499)){
408		    if(sec_complete)
409			fprintf(stdout, "!!");
410		    fprintf(stdout, "%s\n", buf);
411		}
412	    }
413	    p = buf;
414	    long_warn = 0;
415	    continue;
416	default:
417	    if(p < buf + sizeof(buf) - 1)
418		*p++ = c;
419	    else if(long_warn == 0) {
420		fprintf(stderr, "WARNING: incredibly long line received\n");
421		long_warn = 1;
422	    }
423	}
424    }
425
426}
427
428
429#if 0
430int
431getreply (int expecteof)
432{
433    int c, n;
434    int dig;
435    int originalcode = 0, continuation = 0;
436    sighand oldintr;
437    int pflag = 0;
438    char *cp, *pt = pasv;
439
440    oldintr = signal (SIGINT, cmdabort);
441    for (;;) {
442	dig = n = code = 0;
443	cp = reply_string;
444	while ((c = getc (cin)) != '\n') {
445	    if (c == IAC) {	/* handle telnet commands */
446		switch (c = getc (cin)) {
447		case WILL:
448		case WONT:
449		    c = getc (cin);
450		    fprintf (cout, "%c%c%c", IAC, DONT, c);
451		    fflush (cout);
452		    break;
453		case DO:
454		case DONT:
455		    c = getc (cin);
456		    fprintf (cout, "%c%c%c", IAC, WONT, c);
457		    fflush (cout);
458		    break;
459		default:
460		    break;
461		}
462		continue;
463	    }
464	    dig++;
465	    if (c == EOF) {
466		if (expecteof) {
467		    signal (SIGINT, oldintr);
468		    code = 221;
469		    return (0);
470		}
471		lostpeer (0);
472		if (verbose) {
473		    printf ("421 Service not available, remote server has closed connection\n");
474		    fflush (stdout);
475		}
476		code = 421;
477		return (4);
478	    }
479	    if (c != '\r' && (verbose > 0 ||
480			      (verbose > -1 && n == '5' && dig > 4))) {
481		if (proxflag &&
482		    (dig == 1 || dig == 5 && verbose == 0))
483		    printf ("%s:", hostname);
484		putchar (c);
485	    }
486	    if (dig < 4 && isdigit (c))
487		code = code * 10 + (c - '0');
488	    if (!pflag && code == 227)
489		pflag = 1;
490	    if (dig > 4 && pflag == 1 && isdigit (c))
491		pflag = 2;
492	    if (pflag == 2) {
493		if (c != '\r' && c != ')')
494		    *pt++ = c;
495		else {
496		    *pt = '\0';
497		    pflag = 3;
498		}
499	    }
500	    if (dig == 4 && c == '-') {
501		if (continuation)
502		    code = 0;
503		continuation++;
504	    }
505	    if (n == 0)
506		n = c;
507	    if (cp < &reply_string[sizeof (reply_string) - 1])
508		*cp++ = c;
509	}
510	if (verbose > 0 || verbose > -1 && n == '5') {
511	    putchar (c);
512	    fflush (stdout);
513	}
514	if (continuation && code != originalcode) {
515	    if (originalcode == 0)
516		originalcode = code;
517	    continue;
518	}
519	*cp = '\0';
520	if(sec_complete){
521	    if(code == 631)
522		sec_read_msg(reply_string, prot_safe);
523	    else if(code == 632)
524		sec_read_msg(reply_string, prot_private);
525	    else if(code == 633)
526		sec_read_msg(reply_string, prot_confidential);
527	    n = code / 100 + '0';
528	}
529	if (n != '1')
530	    cpend = 0;
531	signal (SIGINT, oldintr);
532	if (code == 421 || originalcode == 421)
533	    lostpeer (0);
534	if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
535	    (*oldintr) (SIGINT);
536	return (n - '0');
537    }
538}
539
540#endif
541
542int
543empty (fd_set * mask, int sec)
544{
545    struct timeval t;
546
547    t.tv_sec = sec;
548    t.tv_usec = 0;
549    return (select (FD_SETSIZE, mask, NULL, NULL, &t));
550}
551
552jmp_buf sendabort;
553
554static RETSIGTYPE
555abortsend (int sig)
556{
557
558    mflag = 0;
559    abrtflag = 0;
560    printf ("\nsend aborted\nwaiting for remote to finish abort\n");
561    fflush (stdout);
562    longjmp (sendabort, 1);
563}
564
565#define HASHBYTES 1024
566
567static int
568copy_stream (FILE * from, FILE * to)
569{
570    static size_t bufsize;
571    static char *buf;
572    int n;
573    int bytes = 0;
574    int werr = 0;
575    int hashbytes = HASHBYTES;
576    struct stat st;
577
578#if defined(HAVE_MMAP) && !defined(NO_MMAP)
579    void *chunk;
580
581#ifndef MAP_FAILED
582#define MAP_FAILED (-1)
583#endif
584
585    if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
586	/*
587	 * mmap zero bytes has potential of loosing, don't do it.
588	 */
589	if (st.st_size == 0)
590	    return 0;
591	chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
592	if (chunk != (void *) MAP_FAILED) {
593	    int res;
594
595	    res = sec_write (fileno (to), chunk, st.st_size);
596	    if (munmap (chunk, st.st_size) < 0)
597		warn ("munmap");
598	    sec_fflush (to);
599	    return res;
600	}
601    }
602#endif
603
604    buf = alloc_buffer (buf, &bufsize,
605			fstat (fileno (from), &st) >= 0 ? &st : NULL);
606    if (buf == NULL)
607	return -1;
608
609    while ((n = read (fileno (from), buf, bufsize)) > 0) {
610	werr = sec_write (fileno (to), buf, n);
611	if (werr < 0)
612	    break;
613	bytes += werr;
614	while (hash && bytes > hashbytes) {
615	    putchar ('#');
616	    hashbytes += HASHBYTES;
617	}
618    }
619    sec_fflush (to);
620    if (n < 0)
621	warn ("local");
622
623    if (werr < 0) {
624	if (errno != EPIPE)
625	    warn ("netout");
626	bytes = -1;
627    }
628    return bytes;
629}
630
631void
632sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
633{
634    struct stat st;
635    struct timeval start, stop;
636    int c, d;
637    FILE *fin, *dout = 0;
638    int (*closefunc) (FILE *);
639    RETSIGTYPE (*oldintr)(int), (*oldintp)(int);
640    long bytes = 0, hashbytes = HASHBYTES;
641    char *rmode = "w";
642
643    if (verbose && printnames) {
644	if (local && strcmp (local, "-") != 0)
645	    printf ("local: %s ", local);
646	if (remote)
647	    printf ("remote: %s\n", remote);
648    }
649    if (proxy) {
650	proxtrans (cmd, local, remote);
651	return;
652    }
653    if (curtype != type)
654	changetype (type, 0);
655    closefunc = NULL;
656    oldintr = NULL;
657    oldintp = NULL;
658
659    if (setjmp (sendabort)) {
660	while (cpend) {
661	    getreply (0);
662	}
663	if (data >= 0) {
664	    close (data);
665	    data = -1;
666	}
667	if (oldintr)
668	    signal (SIGINT, oldintr);
669	if (oldintp)
670	    signal (SIGPIPE, oldintp);
671	code = -1;
672	return;
673    }
674    oldintr = signal (SIGINT, abortsend);
675    if (strcmp (local, "-") == 0)
676	fin = stdin;
677    else if (*local == '|') {
678	oldintp = signal (SIGPIPE, SIG_IGN);
679	fin = popen (local + 1, lmode);
680	if (fin == NULL) {
681	    warn ("%s", local + 1);
682	    signal (SIGINT, oldintr);
683	    signal (SIGPIPE, oldintp);
684	    code = -1;
685	    return;
686	}
687	closefunc = pclose;
688    } else {
689	fin = fopen (local, lmode);
690	if (fin == NULL) {
691	    warn ("local: %s", local);
692	    signal (SIGINT, oldintr);
693	    code = -1;
694	    return;
695	}
696	closefunc = fclose;
697	if (fstat (fileno (fin), &st) < 0 ||
698	    (st.st_mode & S_IFMT) != S_IFREG) {
699	    fprintf (stdout, "%s: not a plain file.\n", local);
700	    signal (SIGINT, oldintr);
701	    fclose (fin);
702	    code = -1;
703	    return;
704	}
705    }
706    if (initconn ()) {
707	signal (SIGINT, oldintr);
708	if (oldintp)
709	    signal (SIGPIPE, oldintp);
710	code = -1;
711	if (closefunc != NULL)
712	    (*closefunc) (fin);
713	return;
714    }
715    if (setjmp (sendabort))
716	goto abort;
717
718    if (restart_point &&
719	(strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
720	int rc;
721
722	switch (curtype) {
723	case TYPE_A:
724	    rc = fseek (fin, (long) restart_point, SEEK_SET);
725	    break;
726	case TYPE_I:
727	case TYPE_L:
728	    rc = lseek (fileno (fin), restart_point, SEEK_SET);
729	    break;
730	}
731	if (rc < 0) {
732	    warn ("local: %s", local);
733	    restart_point = 0;
734	    if (closefunc != NULL)
735		(*closefunc) (fin);
736	    return;
737	}
738	if (command ("REST %ld", (long) restart_point)
739	    != CONTINUE) {
740	    restart_point = 0;
741	    if (closefunc != NULL)
742		(*closefunc) (fin);
743	    return;
744	}
745	restart_point = 0;
746	rmode = "r+w";
747    }
748    if (remote) {
749	if (command ("%s %s", cmd, remote) != PRELIM) {
750	    signal (SIGINT, oldintr);
751	    if (oldintp)
752		signal (SIGPIPE, oldintp);
753	    if (closefunc != NULL)
754		(*closefunc) (fin);
755	    return;
756	}
757    } else if (command ("%s", cmd) != PRELIM) {
758	    signal(SIGINT, oldintr);
759	    if (oldintp)
760		signal(SIGPIPE, oldintp);
761	    if (closefunc != NULL)
762		(*closefunc)(fin);
763	    return;
764	}
765    dout = dataconn(rmode);
766    if (dout == NULL)
767	goto abort;
768    set_buffer_size (fileno (dout), 0);
769    gettimeofday (&start, (struct timezone *) 0);
770    oldintp = signal (SIGPIPE, SIG_IGN);
771    switch (curtype) {
772
773    case TYPE_I:
774    case TYPE_L:
775	errno = d = c = 0;
776	bytes = copy_stream (fin, dout);
777	break;
778
779    case TYPE_A:
780	while ((c = getc (fin)) != EOF) {
781	    if (c == '\n') {
782		while (hash && (bytes >= hashbytes)) {
783		    putchar ('#');
784		    fflush (stdout);
785		    hashbytes += HASHBYTES;
786		}
787		if (ferror (dout))
788		    break;
789		sec_putc ('\r', dout);
790		bytes++;
791	    }
792	    sec_putc (c, dout);
793	    bytes++;
794	}
795	sec_fflush (dout);
796	if (hash) {
797	    if (bytes < hashbytes)
798		putchar ('#');
799	    putchar ('\n');
800	    fflush (stdout);
801	}
802	if (ferror (fin))
803	    warn ("local: %s", local);
804	if (ferror (dout)) {
805	    if (errno != EPIPE)
806		warn ("netout");
807	    bytes = -1;
808	}
809	break;
810    }
811    if (closefunc != NULL)
812	(*closefunc) (fin);
813    fclose (dout);
814    gettimeofday (&stop, (struct timezone *) 0);
815    getreply (0);
816    signal (SIGINT, oldintr);
817    if (oldintp)
818	signal (SIGPIPE, oldintp);
819    if (bytes > 0)
820	ptransfer ("sent", bytes, &start, &stop);
821    return;
822abort:
823    signal (SIGINT, oldintr);
824    if (oldintp)
825	signal (SIGPIPE, oldintp);
826    if (!cpend) {
827	code = -1;
828	return;
829    }
830    if (data >= 0) {
831	close (data);
832	data = -1;
833    }
834    if (dout)
835	fclose (dout);
836    getreply (0);
837    code = -1;
838    if (closefunc != NULL && fin != NULL)
839	(*closefunc) (fin);
840    gettimeofday (&stop, (struct timezone *) 0);
841    if (bytes > 0)
842	ptransfer ("sent", bytes, &start, &stop);
843}
844
845jmp_buf recvabort;
846
847void
848abortrecv (int sig)
849{
850
851    mflag = 0;
852    abrtflag = 0;
853    printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
854    fflush (stdout);
855    longjmp (recvabort, 1);
856}
857
858void
859recvrequest (char *cmd, char *local, char *remote,
860	     char *lmode, int printnames, int local_given)
861{
862    FILE *fout, *din = 0;
863    int (*closefunc) (FILE *);
864    sighand oldintr, oldintp;
865    int c, d, is_retr, tcrflag, bare_lfs = 0;
866    static size_t bufsize;
867    static char *buf;
868    long bytes = 0, hashbytes = HASHBYTES;
869    struct timeval start, stop;
870    struct stat st;
871
872    is_retr = strcmp (cmd, "RETR") == 0;
873    if (is_retr && verbose && printnames) {
874	if (local && strcmp (local, "-") != 0)
875	    printf ("local: %s ", local);
876	if (remote)
877	    printf ("remote: %s\n", remote);
878    }
879    if (proxy && is_retr) {
880	proxtrans (cmd, local, remote);
881	return;
882    }
883    closefunc = NULL;
884    oldintr = NULL;
885    oldintp = NULL;
886    tcrflag = !crflag && is_retr;
887    if (setjmp (recvabort)) {
888	while (cpend) {
889	    getreply (0);
890	}
891	if (data >= 0) {
892	    close (data);
893	    data = -1;
894	}
895	if (oldintr)
896	    signal (SIGINT, oldintr);
897	code = -1;
898	return;
899    }
900    oldintr = signal (SIGINT, abortrecv);
901    if (!local_given || (strcmp (local, "-") && *local != '|')) {
902	if (access (local, 2) < 0) {
903	    char *dir = strrchr (local, '/');
904
905	    if (errno != ENOENT && errno != EACCES) {
906		warn ("local: %s", local);
907		signal (SIGINT, oldintr);
908		code = -1;
909		return;
910	    }
911	    if (dir != NULL)
912		*dir = 0;
913	    d = access (dir ? local : ".", 2);
914	    if (dir != NULL)
915		*dir = '/';
916	    if (d < 0) {
917		warn ("local: %s", local);
918		signal (SIGINT, oldintr);
919		code = -1;
920		return;
921	    }
922	    if (!runique && errno == EACCES &&
923		chmod (local, 0600) < 0) {
924		warn ("local: %s", local);
925		signal (SIGINT, oldintr);
926		signal (SIGINT, oldintr);
927		code = -1;
928		return;
929	    }
930	    if (runique && errno == EACCES &&
931		(local = gunique (local)) == NULL) {
932		signal (SIGINT, oldintr);
933		code = -1;
934		return;
935	    }
936	} else if (runique && (local = gunique (local)) == NULL) {
937	    signal(SIGINT, oldintr);
938	    code = -1;
939	    return;
940	}
941    }
942    if (!is_retr) {
943	if (curtype != TYPE_A)
944	    changetype (TYPE_A, 0);
945    } else if (curtype != type)
946	changetype (type, 0);
947    if (initconn ()) {
948	signal (SIGINT, oldintr);
949	code = -1;
950	return;
951    }
952    if (setjmp (recvabort))
953	goto abort;
954    if (is_retr && restart_point &&
955	command ("REST %ld", (long) restart_point) != CONTINUE)
956	return;
957    if (remote) {
958	if (command ("%s %s", cmd, remote) != PRELIM) {
959	    signal (SIGINT, oldintr);
960	    return;
961	}
962    } else {
963	if (command ("%s", cmd) != PRELIM) {
964	    signal (SIGINT, oldintr);
965	    return;
966	}
967    }
968    din = dataconn ("r");
969    if (din == NULL)
970	goto abort;
971    set_buffer_size (fileno (din), 1);
972    if (local_given && strcmp (local, "-") == 0)
973	fout = stdout;
974    else if (local_given && *local == '|') {
975	oldintp = signal (SIGPIPE, SIG_IGN);
976	fout = popen (local + 1, "w");
977	if (fout == NULL) {
978	    warn ("%s", local + 1);
979	    goto abort;
980	}
981	closefunc = pclose;
982    } else {
983	fout = fopen (local, lmode);
984	if (fout == NULL) {
985	    warn ("local: %s", local);
986	    goto abort;
987	}
988	closefunc = fclose;
989    }
990    buf = alloc_buffer (buf, &bufsize,
991			fstat (fileno (fout), &st) >= 0 ? &st : NULL);
992    if (buf == NULL)
993	goto abort;
994
995    gettimeofday (&start, (struct timezone *) 0);
996    switch (curtype) {
997
998    case TYPE_I:
999    case TYPE_L:
1000	if (restart_point &&
1001	    lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
1002	    warn ("local: %s", local);
1003	    if (closefunc != NULL)
1004		(*closefunc) (fout);
1005	    return;
1006	}
1007	errno = d = 0;
1008	while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
1009	    if ((d = write (fileno (fout), buf, c)) != c)
1010		break;
1011	    bytes += c;
1012	    if (hash) {
1013		while (bytes >= hashbytes) {
1014		    putchar ('#');
1015		    hashbytes += HASHBYTES;
1016		}
1017		fflush (stdout);
1018	    }
1019	}
1020	if (hash && bytes > 0) {
1021	    if (bytes < HASHBYTES)
1022		putchar ('#');
1023	    putchar ('\n');
1024	    fflush (stdout);
1025	}
1026	if (c < 0) {
1027	    if (errno != EPIPE)
1028		warn ("netin");
1029	    bytes = -1;
1030	}
1031	if (d < c) {
1032	    if (d < 0)
1033		warn ("local: %s", local);
1034	    else
1035		warnx ("%s: short write", local);
1036	}
1037	break;
1038
1039    case TYPE_A:
1040	if (restart_point) {
1041	    int i, n, ch;
1042
1043	    if (fseek (fout, 0L, SEEK_SET) < 0)
1044		goto done;
1045	    n = restart_point;
1046	    for (i = 0; i++ < n;) {
1047		if ((ch = sec_getc (fout)) == EOF)
1048		    goto done;
1049		if (ch == '\n')
1050		    i++;
1051	    }
1052	    if (fseek (fout, 0L, SEEK_CUR) < 0) {
1053	done:
1054		warn ("local: %s", local);
1055		if (closefunc != NULL)
1056		    (*closefunc) (fout);
1057		return;
1058	    }
1059	}
1060	while ((c = sec_getc(din)) != EOF) {
1061	    if (c == '\n')
1062		bare_lfs++;
1063	    while (c == '\r') {
1064		while (hash && (bytes >= hashbytes)) {
1065		    putchar ('#');
1066		    fflush (stdout);
1067		    hashbytes += HASHBYTES;
1068		}
1069		bytes++;
1070		if ((c = sec_getc (din)) != '\n' || tcrflag) {
1071		    if (ferror (fout))
1072			goto break2;
1073		    putc ('\r', fout);
1074		    if (c == '\0') {
1075			bytes++;
1076			goto contin2;
1077		    }
1078		    if (c == EOF)
1079			goto contin2;
1080		}
1081	    }
1082	    putc (c, fout);
1083	    bytes++;
1084    contin2:;
1085	}
1086break2:
1087	if (bare_lfs) {
1088	    printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
1089		    bare_lfs);
1090	    printf ("File may not have transferred correctly.\n");
1091	}
1092	if (hash) {
1093	    if (bytes < hashbytes)
1094		putchar ('#');
1095	    putchar ('\n');
1096	    fflush (stdout);
1097	}
1098	if (ferror (din)) {
1099	    if (errno != EPIPE)
1100		warn ("netin");
1101	    bytes = -1;
1102	}
1103	if (ferror (fout))
1104	    warn ("local: %s", local);
1105	break;
1106    }
1107    if (closefunc != NULL)
1108	(*closefunc) (fout);
1109    signal (SIGINT, oldintr);
1110    if (oldintp)
1111	signal (SIGPIPE, oldintp);
1112    fclose (din);
1113    gettimeofday (&stop, (struct timezone *) 0);
1114    getreply (0);
1115    if (bytes > 0 && is_retr)
1116	ptransfer ("received", bytes, &start, &stop);
1117    return;
1118abort:
1119
1120    /* abort using RFC959 recommended IP,SYNC sequence  */
1121
1122    if (oldintp)
1123	signal (SIGPIPE, oldintr);
1124    signal (SIGINT, SIG_IGN);
1125    if (!cpend) {
1126	code = -1;
1127	signal (SIGINT, oldintr);
1128	return;
1129    }
1130    abort_remote(din);
1131    code = -1;
1132    if (data >= 0) {
1133	close (data);
1134	data = -1;
1135    }
1136    if (closefunc != NULL && fout != NULL)
1137	(*closefunc) (fout);
1138    if (din)
1139	fclose (din);
1140    gettimeofday (&stop, (struct timezone *) 0);
1141    if (bytes > 0)
1142	ptransfer ("received", bytes, &start, &stop);
1143    signal (SIGINT, oldintr);
1144}
1145
1146static int
1147parse_epsv (const char *str)
1148{
1149    char sep;
1150    char *end;
1151    int port;
1152
1153    if (*str == '\0')
1154	return -1;
1155    sep = *str++;
1156    if (sep != *str++)
1157	return -1;
1158    if (sep != *str++)
1159	return -1;
1160    port = strtol (str, &end, 0);
1161    if (str == end)
1162	return -1;
1163    if (end[0] != sep || end[1] != '\0')
1164	return -1;
1165    return htons(port);
1166}
1167
1168static int
1169parse_pasv (struct sockaddr_in *sin, const char *str)
1170{
1171    int a0, a1, a2, a3, p0, p1;
1172
1173    /*
1174     * What we've got at this point is a string of comma separated
1175     * one-byte unsigned integer values. The first four are the an IP
1176     * address. The fifth is the MSB of the port number, the sixth is the
1177     * LSB. From that we'll prepare a sockaddr_in.
1178     */
1179
1180    if (sscanf (str, "%d,%d,%d,%d,%d,%d",
1181		&a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1182	printf ("Passive mode address scan failure. "
1183		"Shouldn't happen!\n");
1184	return -1;
1185    }
1186    if (a0 < 0 || a0 > 255 ||
1187	a1 < 0 || a1 > 255 ||
1188	a2 < 0 || a2 > 255 ||
1189	a3 < 0 || a3 > 255 ||
1190	p0 < 0 || p0 > 255 ||
1191	p1 < 0 || p1 > 255) {
1192	printf ("Can't parse passive mode string.\n");
1193	return -1;
1194    }
1195    memset (sin, 0, sizeof(*sin));
1196    sin->sin_family      = AF_INET;
1197    sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
1198				  (a2 << 8) | a3);
1199    sin->sin_port = htons ((p0 << 8) | p1);
1200    return 0;
1201}
1202
1203static int
1204passive_mode (void)
1205{
1206    int port;
1207
1208    data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
1209    if (data < 0) {
1210	warn ("socket");
1211	return (1);
1212    }
1213    if (options & SO_DEBUG)
1214	socket_set_debug (data);
1215    if (command ("EPSV") != COMPLETE) {
1216	if (command ("PASV") != COMPLETE) {
1217	    printf ("Passive mode refused.\n");
1218	    goto bad;
1219	}
1220    }
1221
1222    /*
1223     * Parse the reply to EPSV or PASV
1224     */
1225
1226    port = parse_epsv (pasv);
1227    if (port > 0) {
1228	data_addr->sa_family = myctladdr->sa_family;
1229	socket_set_address_and_port (data_addr,
1230				     socket_get_address (hisctladdr),
1231				     port);
1232    } else {
1233	if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
1234	    goto bad;
1235    }
1236
1237    if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1238	warn ("connect");
1239	goto bad;
1240    }
1241#ifdef IPTOS_THROUGHPUT
1242    socket_set_tos (data, IPTOS_THROUGHPUT);
1243#endif
1244    return (0);
1245bad:
1246    close (data);
1247    data = -1;
1248    sendport = 1;
1249    return (1);
1250}
1251
1252
1253static int
1254active_mode (void)
1255{
1256    int tmpno = 0;
1257    socklen_t len;
1258    int result;
1259
1260noport:
1261    data_addr->sa_family = myctladdr->sa_family;
1262    socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
1263				 sendport ? 0 : socket_get_port (myctladdr));
1264
1265    if (data != -1)
1266	close (data);
1267    data = socket (data_addr->sa_family, SOCK_STREAM, 0);
1268    if (data < 0) {
1269	warn ("socket");
1270	if (tmpno)
1271	    sendport = 1;
1272	return (1);
1273    }
1274    if (!sendport)
1275	socket_set_reuseaddr (data, 1);
1276    if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1277	warn ("bind");
1278	goto bad;
1279    }
1280    if (options & SO_DEBUG)
1281	socket_set_debug (data);
1282    len = sizeof (data_addr_ss);
1283    if (getsockname (data, data_addr, &len) < 0) {
1284	warn ("getsockname");
1285	goto bad;
1286    }
1287    if (listen (data, 1) < 0)
1288	warn ("listen");
1289    if (sendport) {
1290	char addr_str[256];
1291	int inet_af;
1292	int overbose;
1293
1294	if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
1295		       addr_str, sizeof(addr_str)) == NULL)
1296	    errx (1, "inet_ntop failed");
1297	switch (data_addr->sa_family) {
1298	case AF_INET :
1299	    inet_af = 1;
1300	    break;
1301#ifdef HAVE_IPV6
1302	case AF_INET6 :
1303	    inet_af = 2;
1304	    break;
1305#endif
1306	default :
1307	    errx (1, "bad address family %d", data_addr->sa_family);
1308	}
1309
1310
1311	overbose = verbose;
1312	if (debug == 0)
1313	    verbose  = -1;
1314
1315	result = command ("EPRT |%d|%s|%d|",
1316			  inet_af, addr_str,
1317			  ntohs(socket_get_port (data_addr)));
1318	verbose = overbose;
1319
1320	if (result == ERROR) {
1321	    struct sockaddr_in *sin = (struct sockaddr_in *)data_addr;
1322
1323	    unsigned int a = ntohl(sin->sin_addr.s_addr);
1324	    unsigned int p = ntohs(sin->sin_port);
1325
1326	    if (data_addr->sa_family != AF_INET) {
1327		warnx ("remote server doesn't support EPRT");
1328		goto bad;
1329	    }
1330
1331	    result = command("PORT %d,%d,%d,%d,%d,%d",
1332			     (a >> 24) & 0xff,
1333			     (a >> 16) & 0xff,
1334			     (a >> 8) & 0xff,
1335			     a & 0xff,
1336			     (p >> 8) & 0xff,
1337			     p & 0xff);
1338	    if (result == ERROR && sendport == -1) {
1339		sendport = 0;
1340		tmpno = 1;
1341		goto noport;
1342	    }
1343	    return (result != COMPLETE);
1344	}
1345	return result != COMPLETE;
1346    }
1347    if (tmpno)
1348	sendport = 1;
1349
1350
1351#ifdef IPTOS_THROUGHPUT
1352    socket_set_tos (data, IPTOS_THROUGHPUT);
1353#endif
1354    return (0);
1355bad:
1356    close (data);
1357    data = -1;
1358    if (tmpno)
1359	sendport = 1;
1360    return (1);
1361}
1362
1363/*
1364 * Need to start a listen on the data channel before we send the command,
1365 * otherwise the server's connect may fail.
1366 */
1367int
1368initconn (void)
1369{
1370    if (passivemode)
1371	return passive_mode ();
1372    else
1373	return active_mode ();
1374}
1375
1376FILE *
1377dataconn (const char *lmode)
1378{
1379    struct sockaddr_storage from_ss;
1380    struct sockaddr *from = (struct sockaddr *)&from_ss;
1381    socklen_t fromlen = sizeof(from_ss);
1382    int s;
1383
1384    if (passivemode)
1385	return (fdopen (data, lmode));
1386
1387    s = accept (data, from, &fromlen);
1388    if (s < 0) {
1389	warn ("accept");
1390	close (data), data = -1;
1391	return (NULL);
1392    }
1393    close (data);
1394    data = s;
1395#ifdef IPTOS_THROUGHPUT
1396    socket_set_tos (s, IPTOS_THROUGHPUT);
1397#endif
1398    return (fdopen (data, lmode));
1399}
1400
1401void
1402ptransfer (char *direction, long int bytes,
1403	   struct timeval * t0, struct timeval * t1)
1404{
1405    struct timeval td;
1406    float s;
1407    float bs;
1408    int prec;
1409    char *unit;
1410
1411    if (verbose) {
1412	td.tv_sec = t1->tv_sec - t0->tv_sec;
1413	td.tv_usec = t1->tv_usec - t0->tv_usec;
1414	if (td.tv_usec < 0) {
1415	    td.tv_sec--;
1416	    td.tv_usec += 1000000;
1417	}
1418	s = td.tv_sec + (td.tv_usec / 1000000.);
1419	bs = bytes / (s ? s : 1);
1420	if (bs >= 1048576) {
1421	    bs /= 1048576;
1422	    unit = "M";
1423	    prec = 2;
1424	} else if (bs >= 1024) {
1425	    bs /= 1024;
1426	    unit = "k";
1427	    prec = 1;
1428	} else {
1429	    unit = "";
1430	    prec = 0;
1431	}
1432
1433	printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
1434		bytes, direction, s, prec, bs, unit);
1435    }
1436}
1437
1438void
1439psabort (int sig)
1440{
1441
1442    abrtflag++;
1443}
1444
1445void
1446pswitch (int flag)
1447{
1448    sighand oldintr;
1449    static struct comvars {
1450	int connect;
1451	char name[MaxHostNameLen];
1452	struct sockaddr_storage mctl;
1453	struct sockaddr_storage hctl;
1454	FILE *in;
1455	FILE *out;
1456	int tpe;
1457	int curtpe;
1458	int cpnd;
1459	int sunqe;
1460	int runqe;
1461	int mcse;
1462	int ntflg;
1463	char nti[17];
1464	char nto[17];
1465	int mapflg;
1466	char mi[MaxPathLen];
1467	char mo[MaxPathLen];
1468    } proxstruct, tmpstruct;
1469    struct comvars *ip, *op;
1470
1471    abrtflag = 0;
1472    oldintr = signal (SIGINT, psabort);
1473    if (flag) {
1474	if (proxy)
1475	    return;
1476	ip = &tmpstruct;
1477	op = &proxstruct;
1478	proxy++;
1479    } else {
1480	if (!proxy)
1481	    return;
1482	ip = &proxstruct;
1483	op = &tmpstruct;
1484	proxy = 0;
1485    }
1486    ip->connect = connected;
1487    connected = op->connect;
1488    if (hostname) {
1489	strlcpy (ip->name, hostname, sizeof (ip->name));
1490    } else
1491	ip->name[0] = 0;
1492    hostname = op->name;
1493    ip->hctl = hisctladdr_ss;
1494    hisctladdr_ss = op->hctl;
1495    ip->mctl = myctladdr_ss;
1496    myctladdr_ss = op->mctl;
1497    ip->in = cin;
1498    cin = op->in;
1499    ip->out = cout;
1500    cout = op->out;
1501    ip->tpe = type;
1502    type = op->tpe;
1503    ip->curtpe = curtype;
1504    curtype = op->curtpe;
1505    ip->cpnd = cpend;
1506    cpend = op->cpnd;
1507    ip->sunqe = sunique;
1508    sunique = op->sunqe;
1509    ip->runqe = runique;
1510    runique = op->runqe;
1511    ip->mcse = mcase;
1512    mcase = op->mcse;
1513    ip->ntflg = ntflag;
1514    ntflag = op->ntflg;
1515    strlcpy (ip->nti, ntin, sizeof (ip->nti));
1516    strlcpy (ntin, op->nti, 17);
1517    strlcpy (ip->nto, ntout, sizeof (ip->nto));
1518    strlcpy (ntout, op->nto, 17);
1519    ip->mapflg = mapflag;
1520    mapflag = op->mapflg;
1521    strlcpy (ip->mi, mapin, MaxPathLen);
1522    strlcpy (mapin, op->mi, MaxPathLen);
1523    strlcpy (ip->mo, mapout, MaxPathLen);
1524    strlcpy (mapout, op->mo, MaxPathLen);
1525    signal(SIGINT, oldintr);
1526    if (abrtflag) {
1527	abrtflag = 0;
1528	(*oldintr) (SIGINT);
1529    }
1530}
1531
1532void
1533abortpt (int sig)
1534{
1535
1536    printf ("\n");
1537    fflush (stdout);
1538    ptabflg++;
1539    mflag = 0;
1540    abrtflag = 0;
1541    longjmp (ptabort, 1);
1542}
1543
1544void
1545proxtrans (char *cmd, char *local, char *remote)
1546{
1547    sighand oldintr;
1548    int secndflag = 0, prox_type, nfnd;
1549    char *cmd2;
1550    fd_set mask;
1551
1552    if (strcmp (cmd, "RETR"))
1553	cmd2 = "RETR";
1554    else
1555	cmd2 = runique ? "STOU" : "STOR";
1556    if ((prox_type = type) == 0) {
1557	if (unix_server && unix_proxy)
1558	    prox_type = TYPE_I;
1559	else
1560	    prox_type = TYPE_A;
1561    }
1562    if (curtype != prox_type)
1563	changetype (prox_type, 1);
1564    if (command ("PASV") != COMPLETE) {
1565	printf ("proxy server does not support third party transfers.\n");
1566	return;
1567    }
1568    pswitch (0);
1569    if (!connected) {
1570	printf ("No primary connection\n");
1571	pswitch (1);
1572	code = -1;
1573	return;
1574    }
1575    if (curtype != prox_type)
1576	changetype (prox_type, 1);
1577    if (command ("PORT %s", pasv) != COMPLETE) {
1578	pswitch (1);
1579	return;
1580    }
1581    if (setjmp (ptabort))
1582	goto abort;
1583    oldintr = signal (SIGINT, abortpt);
1584    if (command ("%s %s", cmd, remote) != PRELIM) {
1585	signal (SIGINT, oldintr);
1586	pswitch (1);
1587	return;
1588    }
1589    sleep (2);
1590    pswitch (1);
1591    secndflag++;
1592    if (command ("%s %s", cmd2, local) != PRELIM)
1593	goto abort;
1594    ptflag++;
1595    getreply (0);
1596    pswitch (0);
1597    getreply (0);
1598    signal (SIGINT, oldintr);
1599    pswitch (1);
1600    ptflag = 0;
1601    printf ("local: %s remote: %s\n", local, remote);
1602    return;
1603abort:
1604    signal (SIGINT, SIG_IGN);
1605    ptflag = 0;
1606    if (strcmp (cmd, "RETR") && !proxy)
1607	pswitch (1);
1608    else if (!strcmp (cmd, "RETR") && proxy)
1609	pswitch (0);
1610    if (!cpend && !secndflag) {	/* only here if cmd = "STOR" (proxy=1) */
1611	if (command ("%s %s", cmd2, local) != PRELIM) {
1612	    pswitch (0);
1613	    if (cpend)
1614		abort_remote ((FILE *) NULL);
1615	}
1616	pswitch (1);
1617	if (ptabflg)
1618	    code = -1;
1619	signal (SIGINT, oldintr);
1620	return;
1621    }
1622    if (cpend)
1623	abort_remote ((FILE *) NULL);
1624    pswitch (!proxy);
1625    if (!cpend && !secndflag) {	/* only if cmd = "RETR" (proxy=1) */
1626	if (command ("%s %s", cmd2, local) != PRELIM) {
1627	    pswitch (0);
1628	    if (cpend)
1629		abort_remote ((FILE *) NULL);
1630	    pswitch (1);
1631	    if (ptabflg)
1632		code = -1;
1633	    signal (SIGINT, oldintr);
1634	    return;
1635	}
1636    }
1637    if (cpend)
1638	abort_remote ((FILE *) NULL);
1639    pswitch (!proxy);
1640    if (cpend) {
1641	FD_ZERO (&mask);
1642	if (fileno(cin) >= FD_SETSIZE)
1643	    errx (1, "fd too large");
1644	FD_SET (fileno (cin), &mask);
1645	if ((nfnd = empty (&mask, 10)) <= 0) {
1646	    if (nfnd < 0) {
1647		warn ("abort");
1648	    }
1649	    if (ptabflg)
1650		code = -1;
1651	    lostpeer (0);
1652	}
1653	getreply (0);
1654	getreply (0);
1655    }
1656    if (proxy)
1657	pswitch (0);
1658    pswitch (1);
1659    if (ptabflg)
1660	code = -1;
1661    signal (SIGINT, oldintr);
1662}
1663
1664void
1665reset (int argc, char **argv)
1666{
1667    fd_set mask;
1668    int nfnd = 1;
1669
1670    FD_ZERO (&mask);
1671    while (nfnd > 0) {
1672	if (fileno (cin) >= FD_SETSIZE)
1673	    errx (1, "fd too large");
1674	FD_SET (fileno (cin), &mask);
1675	if ((nfnd = empty (&mask, 0)) < 0) {
1676	    warn ("reset");
1677	    code = -1;
1678	    lostpeer(0);
1679	} else if (nfnd) {
1680	    getreply(0);
1681	}
1682    }
1683}
1684
1685char *
1686gunique (char *local)
1687{
1688    static char new[MaxPathLen];
1689    char *cp = strrchr (local, '/');
1690    int d, count = 0;
1691    char ext = '1';
1692
1693    if (cp)
1694	*cp = '\0';
1695    d = access (cp ? local : ".", 2);
1696    if (cp)
1697	*cp = '/';
1698    if (d < 0) {
1699	warn ("local: %s", local);
1700	return NULL;
1701    }
1702    strlcpy (new, local, sizeof(new));
1703    cp = new + strlen(new);
1704    *cp++ = '.';
1705    while (!d) {
1706	if (++count == 100) {
1707	    printf ("runique: can't find unique file name.\n");
1708	    return NULL;
1709	}
1710	*cp++ = ext;
1711	*cp = '\0';
1712	if (ext == '9')
1713	    ext = '0';
1714	else
1715	    ext++;
1716	if ((d = access (new, 0)) < 0)
1717	    break;
1718	if (ext != '0')
1719	    cp--;
1720	else if (*(cp - 2) == '.')
1721	    *(cp - 1) = '1';
1722	else {
1723	    *(cp - 2) = *(cp - 2) + 1;
1724	    cp--;
1725	}
1726    }
1727    return (new);
1728}
1729
1730void
1731abort_remote (FILE * din)
1732{
1733    char buf[BUFSIZ];
1734    int nfnd;
1735    fd_set mask;
1736
1737    /*
1738     * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1739     * after urgent byte rather than before as is protocol now
1740     */
1741    snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC);
1742    if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
1743	warn ("abort");
1744    fprintf (cout, "%c", DM);
1745    sec_fprintf(cout, "ABOR");
1746    sec_fflush (cout);
1747    fprintf (cout, "\r\n");
1748    fflush(cout);
1749    FD_ZERO (&mask);
1750    if (fileno (cin) >= FD_SETSIZE)
1751	errx (1, "fd too large");
1752    FD_SET (fileno (cin), &mask);
1753    if (din) {
1754    if (fileno (din) >= FD_SETSIZE)
1755	errx (1, "fd too large");
1756	FD_SET (fileno (din), &mask);
1757    }
1758    if ((nfnd = empty (&mask, 10)) <= 0) {
1759	if (nfnd < 0) {
1760	    warn ("abort");
1761	}
1762	if (ptabflg)
1763	    code = -1;
1764	lostpeer (0);
1765    }
1766    if (din && FD_ISSET (fileno (din), &mask)) {
1767	while (read (fileno (din), buf, BUFSIZ) > 0)
1768	     /* LOOP */ ;
1769    }
1770    if (getreply (0) == ERROR && code == 552) {
1771	/* 552 needed for nic style abort */
1772	getreply (0);
1773    }
1774    getreply (0);
1775}
1776