ftp.c revision 103423
1/*
2 * Copyright (c) 1985, 1989, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * 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.74 2002/09/04 22:00:12 joda 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			}
400		    }
401		    return code / 100;
402		}
403	    }else{
404		if(verbose > 0 || (verbose > -1 && code > 499)){
405		    if(sec_complete)
406			fprintf(stdout, "!!");
407		    fprintf(stdout, "%s\n", buf);
408		}
409	    }
410	    p = buf;
411	    long_warn = 0;
412	    continue;
413	default:
414	    if(p < buf + sizeof(buf) - 1)
415		*p++ = c;
416	    else if(long_warn == 0) {
417		fprintf(stderr, "WARNING: incredibly long line received\n");
418		long_warn = 1;
419	    }
420	}
421    }
422
423}
424
425
426#if 0
427int
428getreply (int expecteof)
429{
430    int c, n;
431    int dig;
432    int originalcode = 0, continuation = 0;
433    sighand oldintr;
434    int pflag = 0;
435    char *cp, *pt = pasv;
436
437    oldintr = signal (SIGINT, cmdabort);
438    for (;;) {
439	dig = n = code = 0;
440	cp = reply_string;
441	while ((c = getc (cin)) != '\n') {
442	    if (c == IAC) {	/* handle telnet commands */
443		switch (c = getc (cin)) {
444		case WILL:
445		case WONT:
446		    c = getc (cin);
447		    fprintf (cout, "%c%c%c", IAC, DONT, c);
448		    fflush (cout);
449		    break;
450		case DO:
451		case DONT:
452		    c = getc (cin);
453		    fprintf (cout, "%c%c%c", IAC, WONT, c);
454		    fflush (cout);
455		    break;
456		default:
457		    break;
458		}
459		continue;
460	    }
461	    dig++;
462	    if (c == EOF) {
463		if (expecteof) {
464		    signal (SIGINT, oldintr);
465		    code = 221;
466		    return (0);
467		}
468		lostpeer (0);
469		if (verbose) {
470		    printf ("421 Service not available, remote server has closed connection\n");
471		    fflush (stdout);
472		}
473		code = 421;
474		return (4);
475	    }
476	    if (c != '\r' && (verbose > 0 ||
477			      (verbose > -1 && n == '5' && dig > 4))) {
478		if (proxflag &&
479		    (dig == 1 || dig == 5 && verbose == 0))
480		    printf ("%s:", hostname);
481		putchar (c);
482	    }
483	    if (dig < 4 && isdigit (c))
484		code = code * 10 + (c - '0');
485	    if (!pflag && code == 227)
486		pflag = 1;
487	    if (dig > 4 && pflag == 1 && isdigit (c))
488		pflag = 2;
489	    if (pflag == 2) {
490		if (c != '\r' && c != ')')
491		    *pt++ = c;
492		else {
493		    *pt = '\0';
494		    pflag = 3;
495		}
496	    }
497	    if (dig == 4 && c == '-') {
498		if (continuation)
499		    code = 0;
500		continuation++;
501	    }
502	    if (n == 0)
503		n = c;
504	    if (cp < &reply_string[sizeof (reply_string) - 1])
505		*cp++ = c;
506	}
507	if (verbose > 0 || verbose > -1 && n == '5') {
508	    putchar (c);
509	    fflush (stdout);
510	}
511	if (continuation && code != originalcode) {
512	    if (originalcode == 0)
513		originalcode = code;
514	    continue;
515	}
516	*cp = '\0';
517	if(sec_complete){
518	    if(code == 631)
519		sec_read_msg(reply_string, prot_safe);
520	    else if(code == 632)
521		sec_read_msg(reply_string, prot_private);
522	    else if(code == 633)
523		sec_read_msg(reply_string, prot_confidential);
524	    n = code / 100 + '0';
525	}
526	if (n != '1')
527	    cpend = 0;
528	signal (SIGINT, oldintr);
529	if (code == 421 || originalcode == 421)
530	    lostpeer (0);
531	if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
532	    (*oldintr) (SIGINT);
533	return (n - '0');
534    }
535}
536
537#endif
538
539int
540empty (fd_set * mask, int sec)
541{
542    struct timeval t;
543
544    t.tv_sec = sec;
545    t.tv_usec = 0;
546    return (select (FD_SETSIZE, mask, NULL, NULL, &t));
547}
548
549jmp_buf sendabort;
550
551static RETSIGTYPE
552abortsend (int sig)
553{
554
555    mflag = 0;
556    abrtflag = 0;
557    printf ("\nsend aborted\nwaiting for remote to finish abort\n");
558    fflush (stdout);
559    longjmp (sendabort, 1);
560}
561
562#define HASHBYTES 1024
563
564static int
565copy_stream (FILE * from, FILE * to)
566{
567    static size_t bufsize;
568    static char *buf;
569    int n;
570    int bytes = 0;
571    int werr = 0;
572    int hashbytes = HASHBYTES;
573    struct stat st;
574
575#if defined(HAVE_MMAP) && !defined(NO_MMAP)
576    void *chunk;
577
578#ifndef MAP_FAILED
579#define MAP_FAILED (-1)
580#endif
581
582    if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
583	/*
584	 * mmap zero bytes has potential of loosing, don't do it.
585	 */
586	if (st.st_size == 0)
587	    return 0;
588	chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
589	if (chunk != (void *) MAP_FAILED) {
590	    int res;
591
592	    res = sec_write (fileno (to), chunk, st.st_size);
593	    if (munmap (chunk, st.st_size) < 0)
594		warn ("munmap");
595	    sec_fflush (to);
596	    return res;
597	}
598    }
599#endif
600
601    buf = alloc_buffer (buf, &bufsize,
602			fstat (fileno (from), &st) >= 0 ? &st : NULL);
603    if (buf == NULL)
604	return -1;
605
606    while ((n = read (fileno (from), buf, bufsize)) > 0) {
607	werr = sec_write (fileno (to), buf, n);
608	if (werr < 0)
609	    break;
610	bytes += werr;
611	while (hash && bytes > hashbytes) {
612	    putchar ('#');
613	    hashbytes += HASHBYTES;
614	}
615    }
616    sec_fflush (to);
617    if (n < 0)
618	warn ("local");
619
620    if (werr < 0) {
621	if (errno != EPIPE)
622	    warn ("netout");
623	bytes = -1;
624    }
625    return bytes;
626}
627
628void
629sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
630{
631    struct stat st;
632    struct timeval start, stop;
633    int c, d;
634    FILE *fin, *dout = 0;
635    int (*closefunc) (FILE *);
636    RETSIGTYPE (*oldintr)(int), (*oldintp)(int);
637    long bytes = 0, hashbytes = HASHBYTES;
638    char *rmode = "w";
639
640    if (verbose && printnames) {
641	if (local && strcmp (local, "-") != 0)
642	    printf ("local: %s ", local);
643	if (remote)
644	    printf ("remote: %s\n", remote);
645    }
646    if (proxy) {
647	proxtrans (cmd, local, remote);
648	return;
649    }
650    if (curtype != type)
651	changetype (type, 0);
652    closefunc = NULL;
653    oldintr = NULL;
654    oldintp = NULL;
655
656    if (setjmp (sendabort)) {
657	while (cpend) {
658	    getreply (0);
659	}
660	if (data >= 0) {
661	    close (data);
662	    data = -1;
663	}
664	if (oldintr)
665	    signal (SIGINT, oldintr);
666	if (oldintp)
667	    signal (SIGPIPE, oldintp);
668	code = -1;
669	return;
670    }
671    oldintr = signal (SIGINT, abortsend);
672    if (strcmp (local, "-") == 0)
673	fin = stdin;
674    else if (*local == '|') {
675	oldintp = signal (SIGPIPE, SIG_IGN);
676	fin = popen (local + 1, lmode);
677	if (fin == NULL) {
678	    warn ("%s", local + 1);
679	    signal (SIGINT, oldintr);
680	    signal (SIGPIPE, oldintp);
681	    code = -1;
682	    return;
683	}
684	closefunc = pclose;
685    } else {
686	fin = fopen (local, lmode);
687	if (fin == NULL) {
688	    warn ("local: %s", local);
689	    signal (SIGINT, oldintr);
690	    code = -1;
691	    return;
692	}
693	closefunc = fclose;
694	if (fstat (fileno (fin), &st) < 0 ||
695	    (st.st_mode & S_IFMT) != S_IFREG) {
696	    fprintf (stdout, "%s: not a plain file.\n", local);
697	    signal (SIGINT, oldintr);
698	    fclose (fin);
699	    code = -1;
700	    return;
701	}
702    }
703    if (initconn ()) {
704	signal (SIGINT, oldintr);
705	if (oldintp)
706	    signal (SIGPIPE, oldintp);
707	code = -1;
708	if (closefunc != NULL)
709	    (*closefunc) (fin);
710	return;
711    }
712    if (setjmp (sendabort))
713	goto abort;
714
715    if (restart_point &&
716	(strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
717	int rc;
718
719	switch (curtype) {
720	case TYPE_A:
721	    rc = fseek (fin, (long) restart_point, SEEK_SET);
722	    break;
723	case TYPE_I:
724	case TYPE_L:
725	    rc = lseek (fileno (fin), restart_point, SEEK_SET);
726	    break;
727	}
728	if (rc < 0) {
729	    warn ("local: %s", local);
730	    restart_point = 0;
731	    if (closefunc != NULL)
732		(*closefunc) (fin);
733	    return;
734	}
735	if (command ("REST %ld", (long) restart_point)
736	    != CONTINUE) {
737	    restart_point = 0;
738	    if (closefunc != NULL)
739		(*closefunc) (fin);
740	    return;
741	}
742	restart_point = 0;
743	rmode = "r+w";
744    }
745    if (remote) {
746	if (command ("%s %s", cmd, remote) != PRELIM) {
747	    signal (SIGINT, oldintr);
748	    if (oldintp)
749		signal (SIGPIPE, oldintp);
750	    if (closefunc != NULL)
751		(*closefunc) (fin);
752	    return;
753	}
754    } else if (command ("%s", cmd) != PRELIM) {
755	    signal(SIGINT, oldintr);
756	    if (oldintp)
757		signal(SIGPIPE, oldintp);
758	    if (closefunc != NULL)
759		(*closefunc)(fin);
760	    return;
761	}
762    dout = dataconn(rmode);
763    if (dout == NULL)
764	goto abort;
765    set_buffer_size (fileno (dout), 0);
766    gettimeofday (&start, (struct timezone *) 0);
767    oldintp = signal (SIGPIPE, SIG_IGN);
768    switch (curtype) {
769
770    case TYPE_I:
771    case TYPE_L:
772	errno = d = c = 0;
773	bytes = copy_stream (fin, dout);
774	break;
775
776    case TYPE_A:
777	while ((c = getc (fin)) != EOF) {
778	    if (c == '\n') {
779		while (hash && (bytes >= hashbytes)) {
780		    putchar ('#');
781		    fflush (stdout);
782		    hashbytes += HASHBYTES;
783		}
784		if (ferror (dout))
785		    break;
786		sec_putc ('\r', dout);
787		bytes++;
788	    }
789	    sec_putc (c, dout);
790	    bytes++;
791	}
792	sec_fflush (dout);
793	if (hash) {
794	    if (bytes < hashbytes)
795		putchar ('#');
796	    putchar ('\n');
797	    fflush (stdout);
798	}
799	if (ferror (fin))
800	    warn ("local: %s", local);
801	if (ferror (dout)) {
802	    if (errno != EPIPE)
803		warn ("netout");
804	    bytes = -1;
805	}
806	break;
807    }
808    if (closefunc != NULL)
809	(*closefunc) (fin);
810    fclose (dout);
811    gettimeofday (&stop, (struct timezone *) 0);
812    getreply (0);
813    signal (SIGINT, oldintr);
814    if (oldintp)
815	signal (SIGPIPE, oldintp);
816    if (bytes > 0)
817	ptransfer ("sent", bytes, &start, &stop);
818    return;
819abort:
820    signal (SIGINT, oldintr);
821    if (oldintp)
822	signal (SIGPIPE, oldintp);
823    if (!cpend) {
824	code = -1;
825	return;
826    }
827    if (data >= 0) {
828	close (data);
829	data = -1;
830    }
831    if (dout)
832	fclose (dout);
833    getreply (0);
834    code = -1;
835    if (closefunc != NULL && fin != NULL)
836	(*closefunc) (fin);
837    gettimeofday (&stop, (struct timezone *) 0);
838    if (bytes > 0)
839	ptransfer ("sent", bytes, &start, &stop);
840}
841
842jmp_buf recvabort;
843
844void
845abortrecv (int sig)
846{
847
848    mflag = 0;
849    abrtflag = 0;
850    printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
851    fflush (stdout);
852    longjmp (recvabort, 1);
853}
854
855void
856recvrequest (char *cmd, char *local, char *remote,
857	     char *lmode, int printnames, int local_given)
858{
859    FILE *fout, *din = 0;
860    int (*closefunc) (FILE *);
861    sighand oldintr, oldintp;
862    int c, d, is_retr, tcrflag, bare_lfs = 0;
863    static size_t bufsize;
864    static char *buf;
865    long bytes = 0, hashbytes = HASHBYTES;
866    struct timeval start, stop;
867    struct stat st;
868
869    is_retr = strcmp (cmd, "RETR") == 0;
870    if (is_retr && verbose && printnames) {
871	if (local && strcmp (local, "-") != 0)
872	    printf ("local: %s ", local);
873	if (remote)
874	    printf ("remote: %s\n", remote);
875    }
876    if (proxy && is_retr) {
877	proxtrans (cmd, local, remote);
878	return;
879    }
880    closefunc = NULL;
881    oldintr = NULL;
882    oldintp = NULL;
883    tcrflag = !crflag && is_retr;
884    if (setjmp (recvabort)) {
885	while (cpend) {
886	    getreply (0);
887	}
888	if (data >= 0) {
889	    close (data);
890	    data = -1;
891	}
892	if (oldintr)
893	    signal (SIGINT, oldintr);
894	code = -1;
895	return;
896    }
897    oldintr = signal (SIGINT, abortrecv);
898    if (!local_given || (strcmp (local, "-") && *local != '|')) {
899	if (access (local, 2) < 0) {
900	    char *dir = strrchr (local, '/');
901
902	    if (errno != ENOENT && errno != EACCES) {
903		warn ("local: %s", local);
904		signal (SIGINT, oldintr);
905		code = -1;
906		return;
907	    }
908	    if (dir != NULL)
909		*dir = 0;
910	    d = access (dir ? local : ".", 2);
911	    if (dir != NULL)
912		*dir = '/';
913	    if (d < 0) {
914		warn ("local: %s", local);
915		signal (SIGINT, oldintr);
916		code = -1;
917		return;
918	    }
919	    if (!runique && errno == EACCES &&
920		chmod (local, 0600) < 0) {
921		warn ("local: %s", local);
922		signal (SIGINT, oldintr);
923		signal (SIGINT, oldintr);
924		code = -1;
925		return;
926	    }
927	    if (runique && errno == EACCES &&
928		(local = gunique (local)) == NULL) {
929		signal (SIGINT, oldintr);
930		code = -1;
931		return;
932	    }
933	} else if (runique && (local = gunique (local)) == NULL) {
934	    signal(SIGINT, oldintr);
935	    code = -1;
936	    return;
937	}
938    }
939    if (!is_retr) {
940	if (curtype != TYPE_A)
941	    changetype (TYPE_A, 0);
942    } else if (curtype != type)
943	changetype (type, 0);
944    if (initconn ()) {
945	signal (SIGINT, oldintr);
946	code = -1;
947	return;
948    }
949    if (setjmp (recvabort))
950	goto abort;
951    if (is_retr && restart_point &&
952	command ("REST %ld", (long) restart_point) != CONTINUE)
953	return;
954    if (remote) {
955	if (command ("%s %s", cmd, remote) != PRELIM) {
956	    signal (SIGINT, oldintr);
957	    return;
958	}
959    } else {
960	if (command ("%s", cmd) != PRELIM) {
961	    signal (SIGINT, oldintr);
962	    return;
963	}
964    }
965    din = dataconn ("r");
966    if (din == NULL)
967	goto abort;
968    set_buffer_size (fileno (din), 1);
969    if (local_given && strcmp (local, "-") == 0)
970	fout = stdout;
971    else if (local_given && *local == '|') {
972	oldintp = signal (SIGPIPE, SIG_IGN);
973	fout = popen (local + 1, "w");
974	if (fout == NULL) {
975	    warn ("%s", local + 1);
976	    goto abort;
977	}
978	closefunc = pclose;
979    } else {
980	fout = fopen (local, lmode);
981	if (fout == NULL) {
982	    warn ("local: %s", local);
983	    goto abort;
984	}
985	closefunc = fclose;
986    }
987    buf = alloc_buffer (buf, &bufsize,
988			fstat (fileno (fout), &st) >= 0 ? &st : NULL);
989    if (buf == NULL)
990	goto abort;
991
992    gettimeofday (&start, (struct timezone *) 0);
993    switch (curtype) {
994
995    case TYPE_I:
996    case TYPE_L:
997	if (restart_point &&
998	    lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
999	    warn ("local: %s", local);
1000	    if (closefunc != NULL)
1001		(*closefunc) (fout);
1002	    return;
1003	}
1004	errno = d = 0;
1005	while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
1006	    if ((d = write (fileno (fout), buf, c)) != c)
1007		break;
1008	    bytes += c;
1009	    if (hash) {
1010		while (bytes >= hashbytes) {
1011		    putchar ('#');
1012		    hashbytes += HASHBYTES;
1013		}
1014		fflush (stdout);
1015	    }
1016	}
1017	if (hash && bytes > 0) {
1018	    if (bytes < HASHBYTES)
1019		putchar ('#');
1020	    putchar ('\n');
1021	    fflush (stdout);
1022	}
1023	if (c < 0) {
1024	    if (errno != EPIPE)
1025		warn ("netin");
1026	    bytes = -1;
1027	}
1028	if (d < c) {
1029	    if (d < 0)
1030		warn ("local: %s", local);
1031	    else
1032		warnx ("%s: short write", local);
1033	}
1034	break;
1035
1036    case TYPE_A:
1037	if (restart_point) {
1038	    int i, n, ch;
1039
1040	    if (fseek (fout, 0L, SEEK_SET) < 0)
1041		goto done;
1042	    n = restart_point;
1043	    for (i = 0; i++ < n;) {
1044		if ((ch = sec_getc (fout)) == EOF)
1045		    goto done;
1046		if (ch == '\n')
1047		    i++;
1048	    }
1049	    if (fseek (fout, 0L, SEEK_CUR) < 0) {
1050	done:
1051		warn ("local: %s", local);
1052		if (closefunc != NULL)
1053		    (*closefunc) (fout);
1054		return;
1055	    }
1056	}
1057	while ((c = sec_getc(din)) != EOF) {
1058	    if (c == '\n')
1059		bare_lfs++;
1060	    while (c == '\r') {
1061		while (hash && (bytes >= hashbytes)) {
1062		    putchar ('#');
1063		    fflush (stdout);
1064		    hashbytes += HASHBYTES;
1065		}
1066		bytes++;
1067		if ((c = sec_getc (din)) != '\n' || tcrflag) {
1068		    if (ferror (fout))
1069			goto break2;
1070		    putc ('\r', fout);
1071		    if (c == '\0') {
1072			bytes++;
1073			goto contin2;
1074		    }
1075		    if (c == EOF)
1076			goto contin2;
1077		}
1078	    }
1079	    putc (c, fout);
1080	    bytes++;
1081    contin2:;
1082	}
1083break2:
1084	if (bare_lfs) {
1085	    printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
1086		    bare_lfs);
1087	    printf ("File may not have transferred correctly.\n");
1088	}
1089	if (hash) {
1090	    if (bytes < hashbytes)
1091		putchar ('#');
1092	    putchar ('\n');
1093	    fflush (stdout);
1094	}
1095	if (ferror (din)) {
1096	    if (errno != EPIPE)
1097		warn ("netin");
1098	    bytes = -1;
1099	}
1100	if (ferror (fout))
1101	    warn ("local: %s", local);
1102	break;
1103    }
1104    if (closefunc != NULL)
1105	(*closefunc) (fout);
1106    signal (SIGINT, oldintr);
1107    if (oldintp)
1108	signal (SIGPIPE, oldintp);
1109    fclose (din);
1110    gettimeofday (&stop, (struct timezone *) 0);
1111    getreply (0);
1112    if (bytes > 0 && is_retr)
1113	ptransfer ("received", bytes, &start, &stop);
1114    return;
1115abort:
1116
1117    /* abort using RFC959 recommended IP,SYNC sequence  */
1118
1119    if (oldintp)
1120	signal (SIGPIPE, oldintr);
1121    signal (SIGINT, SIG_IGN);
1122    if (!cpend) {
1123	code = -1;
1124	signal (SIGINT, oldintr);
1125	return;
1126    }
1127    abort_remote(din);
1128    code = -1;
1129    if (data >= 0) {
1130	close (data);
1131	data = -1;
1132    }
1133    if (closefunc != NULL && fout != NULL)
1134	(*closefunc) (fout);
1135    if (din)
1136	fclose (din);
1137    gettimeofday (&stop, (struct timezone *) 0);
1138    if (bytes > 0)
1139	ptransfer ("received", bytes, &start, &stop);
1140    signal (SIGINT, oldintr);
1141}
1142
1143static int
1144parse_epsv (const char *str)
1145{
1146    char sep;
1147    char *end;
1148    int port;
1149
1150    if (*str == '\0')
1151	return -1;
1152    sep = *str++;
1153    if (sep != *str++)
1154	return -1;
1155    if (sep != *str++)
1156	return -1;
1157    port = strtol (str, &end, 0);
1158    if (str == end)
1159	return -1;
1160    if (end[0] != sep || end[1] != '\0')
1161	return -1;
1162    return htons(port);
1163}
1164
1165static int
1166parse_pasv (struct sockaddr_in *sin, const char *str)
1167{
1168    int a0, a1, a2, a3, p0, p1;
1169
1170    /*
1171     * What we've got at this point is a string of comma separated
1172     * one-byte unsigned integer values. The first four are the an IP
1173     * address. The fifth is the MSB of the port number, the sixth is the
1174     * LSB. From that we'll prepare a sockaddr_in.
1175     */
1176
1177    if (sscanf (str, "%d,%d,%d,%d,%d,%d",
1178		&a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1179	printf ("Passive mode address scan failure. "
1180		"Shouldn't happen!\n");
1181	return -1;
1182    }
1183    if (a0 < 0 || a0 > 255 ||
1184	a1 < 0 || a1 > 255 ||
1185	a2 < 0 || a2 > 255 ||
1186	a3 < 0 || a3 > 255 ||
1187	p0 < 0 || p0 > 255 ||
1188	p1 < 0 || p1 > 255) {
1189	printf ("Can't parse passive mode string.\n");
1190	return -1;
1191    }
1192    memset (sin, 0, sizeof(*sin));
1193    sin->sin_family      = AF_INET;
1194    sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
1195				  (a2 << 8) | a3);
1196    sin->sin_port = htons ((p0 << 8) | p1);
1197    return 0;
1198}
1199
1200static int
1201passive_mode (void)
1202{
1203    int port;
1204
1205    data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
1206    if (data < 0) {
1207	warn ("socket");
1208	return (1);
1209    }
1210    if (options & SO_DEBUG)
1211	socket_set_debug (data);
1212    if (command ("EPSV") != COMPLETE) {
1213	if (command ("PASV") != COMPLETE) {
1214	    printf ("Passive mode refused.\n");
1215	    goto bad;
1216	}
1217    }
1218
1219    /*
1220     * Parse the reply to EPSV or PASV
1221     */
1222
1223    port = parse_epsv (pasv);
1224    if (port > 0) {
1225	data_addr->sa_family = myctladdr->sa_family;
1226	socket_set_address_and_port (data_addr,
1227				     socket_get_address (hisctladdr),
1228				     port);
1229    } else {
1230	if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
1231	    goto bad;
1232    }
1233
1234    if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1235	warn ("connect");
1236	goto bad;
1237    }
1238#ifdef IPTOS_THROUGHPUT
1239    socket_set_tos (data, IPTOS_THROUGHPUT);
1240#endif
1241    return (0);
1242bad:
1243    close (data);
1244    data = -1;
1245    sendport = 1;
1246    return (1);
1247}
1248
1249
1250static int
1251active_mode (void)
1252{
1253    int tmpno = 0;
1254    socklen_t len;
1255    int result;
1256
1257noport:
1258    data_addr->sa_family = myctladdr->sa_family;
1259    socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
1260				 sendport ? 0 : socket_get_port (myctladdr));
1261
1262    if (data != -1)
1263	close (data);
1264    data = socket (data_addr->sa_family, SOCK_STREAM, 0);
1265    if (data < 0) {
1266	warn ("socket");
1267	if (tmpno)
1268	    sendport = 1;
1269	return (1);
1270    }
1271    if (!sendport)
1272	socket_set_reuseaddr (data, 1);
1273    if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1274	warn ("bind");
1275	goto bad;
1276    }
1277    if (options & SO_DEBUG)
1278	socket_set_debug (data);
1279    len = sizeof (data_addr_ss);
1280    if (getsockname (data, data_addr, &len) < 0) {
1281	warn ("getsockname");
1282	goto bad;
1283    }
1284    if (listen (data, 1) < 0)
1285	warn ("listen");
1286    if (sendport) {
1287	char addr_str[256];
1288	int inet_af;
1289	int overbose;
1290
1291	if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
1292		       addr_str, sizeof(addr_str)) == NULL)
1293	    errx (1, "inet_ntop failed");
1294	switch (data_addr->sa_family) {
1295	case AF_INET :
1296	    inet_af = 1;
1297	    break;
1298#ifdef HAVE_IPV6
1299	case AF_INET6 :
1300	    inet_af = 2;
1301	    break;
1302#endif
1303	default :
1304	    errx (1, "bad address family %d", data_addr->sa_family);
1305	}
1306
1307
1308	overbose = verbose;
1309	if (debug == 0)
1310	    verbose  = -1;
1311
1312	result = command ("EPRT |%d|%s|%d|",
1313			  inet_af, addr_str,
1314			  ntohs(socket_get_port (data_addr)));
1315	verbose = overbose;
1316
1317	if (result == ERROR) {
1318	    struct sockaddr_in *sin = (struct sockaddr_in *)data_addr;
1319
1320	    unsigned int a = ntohl(sin->sin_addr.s_addr);
1321	    unsigned int p = ntohs(sin->sin_port);
1322
1323	    if (data_addr->sa_family != AF_INET) {
1324		warnx ("remote server doesn't support EPRT");
1325		goto bad;
1326	    }
1327
1328	    result = command("PORT %d,%d,%d,%d,%d,%d",
1329			     (a >> 24) & 0xff,
1330			     (a >> 16) & 0xff,
1331			     (a >> 8) & 0xff,
1332			     a & 0xff,
1333			     (p >> 8) & 0xff,
1334			     p & 0xff);
1335	    if (result == ERROR && sendport == -1) {
1336		sendport = 0;
1337		tmpno = 1;
1338		goto noport;
1339	    }
1340	    return (result != COMPLETE);
1341	}
1342	return result != COMPLETE;
1343    }
1344    if (tmpno)
1345	sendport = 1;
1346
1347
1348#ifdef IPTOS_THROUGHPUT
1349    socket_set_tos (data, IPTOS_THROUGHPUT);
1350#endif
1351    return (0);
1352bad:
1353    close (data);
1354    data = -1;
1355    if (tmpno)
1356	sendport = 1;
1357    return (1);
1358}
1359
1360/*
1361 * Need to start a listen on the data channel before we send the command,
1362 * otherwise the server's connect may fail.
1363 */
1364int
1365initconn (void)
1366{
1367    if (passivemode)
1368	return passive_mode ();
1369    else
1370	return active_mode ();
1371}
1372
1373FILE *
1374dataconn (const char *lmode)
1375{
1376    struct sockaddr_storage from_ss;
1377    struct sockaddr *from = (struct sockaddr *)&from_ss;
1378    socklen_t fromlen = sizeof(from_ss);
1379    int s;
1380
1381    if (passivemode)
1382	return (fdopen (data, lmode));
1383
1384    s = accept (data, from, &fromlen);
1385    if (s < 0) {
1386	warn ("accept");
1387	close (data), data = -1;
1388	return (NULL);
1389    }
1390    close (data);
1391    data = s;
1392#ifdef IPTOS_THROUGHPUT
1393    socket_set_tos (s, IPTOS_THROUGHPUT);
1394#endif
1395    return (fdopen (data, lmode));
1396}
1397
1398void
1399ptransfer (char *direction, long int bytes,
1400	   struct timeval * t0, struct timeval * t1)
1401{
1402    struct timeval td;
1403    float s;
1404    float bs;
1405    int prec;
1406    char *unit;
1407
1408    if (verbose) {
1409	td.tv_sec = t1->tv_sec - t0->tv_sec;
1410	td.tv_usec = t1->tv_usec - t0->tv_usec;
1411	if (td.tv_usec < 0) {
1412	    td.tv_sec--;
1413	    td.tv_usec += 1000000;
1414	}
1415	s = td.tv_sec + (td.tv_usec / 1000000.);
1416	bs = bytes / (s ? s : 1);
1417	if (bs >= 1048576) {
1418	    bs /= 1048576;
1419	    unit = "M";
1420	    prec = 2;
1421	} else if (bs >= 1024) {
1422	    bs /= 1024;
1423	    unit = "k";
1424	    prec = 1;
1425	} else {
1426	    unit = "";
1427	    prec = 0;
1428	}
1429
1430	printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
1431		bytes, direction, s, prec, bs, unit);
1432    }
1433}
1434
1435void
1436psabort (int sig)
1437{
1438
1439    abrtflag++;
1440}
1441
1442void
1443pswitch (int flag)
1444{
1445    sighand oldintr;
1446    static struct comvars {
1447	int connect;
1448	char name[MaxHostNameLen];
1449	struct sockaddr_storage mctl;
1450	struct sockaddr_storage hctl;
1451	FILE *in;
1452	FILE *out;
1453	int tpe;
1454	int curtpe;
1455	int cpnd;
1456	int sunqe;
1457	int runqe;
1458	int mcse;
1459	int ntflg;
1460	char nti[17];
1461	char nto[17];
1462	int mapflg;
1463	char mi[MaxPathLen];
1464	char mo[MaxPathLen];
1465    } proxstruct, tmpstruct;
1466    struct comvars *ip, *op;
1467
1468    abrtflag = 0;
1469    oldintr = signal (SIGINT, psabort);
1470    if (flag) {
1471	if (proxy)
1472	    return;
1473	ip = &tmpstruct;
1474	op = &proxstruct;
1475	proxy++;
1476    } else {
1477	if (!proxy)
1478	    return;
1479	ip = &proxstruct;
1480	op = &tmpstruct;
1481	proxy = 0;
1482    }
1483    ip->connect = connected;
1484    connected = op->connect;
1485    if (hostname) {
1486	strlcpy (ip->name, hostname, sizeof (ip->name));
1487    } else
1488	ip->name[0] = 0;
1489    hostname = op->name;
1490    ip->hctl = hisctladdr_ss;
1491    hisctladdr_ss = op->hctl;
1492    ip->mctl = myctladdr_ss;
1493    myctladdr_ss = op->mctl;
1494    ip->in = cin;
1495    cin = op->in;
1496    ip->out = cout;
1497    cout = op->out;
1498    ip->tpe = type;
1499    type = op->tpe;
1500    ip->curtpe = curtype;
1501    curtype = op->curtpe;
1502    ip->cpnd = cpend;
1503    cpend = op->cpnd;
1504    ip->sunqe = sunique;
1505    sunique = op->sunqe;
1506    ip->runqe = runique;
1507    runique = op->runqe;
1508    ip->mcse = mcase;
1509    mcase = op->mcse;
1510    ip->ntflg = ntflag;
1511    ntflag = op->ntflg;
1512    strlcpy (ip->nti, ntin, sizeof (ip->nti));
1513    strlcpy (ntin, op->nti, 17);
1514    strlcpy (ip->nto, ntout, sizeof (ip->nto));
1515    strlcpy (ntout, op->nto, 17);
1516    ip->mapflg = mapflag;
1517    mapflag = op->mapflg;
1518    strlcpy (ip->mi, mapin, MaxPathLen);
1519    strlcpy (mapin, op->mi, MaxPathLen);
1520    strlcpy (ip->mo, mapout, MaxPathLen);
1521    strlcpy (mapout, op->mo, MaxPathLen);
1522    signal(SIGINT, oldintr);
1523    if (abrtflag) {
1524	abrtflag = 0;
1525	(*oldintr) (SIGINT);
1526    }
1527}
1528
1529void
1530abortpt (int sig)
1531{
1532
1533    printf ("\n");
1534    fflush (stdout);
1535    ptabflg++;
1536    mflag = 0;
1537    abrtflag = 0;
1538    longjmp (ptabort, 1);
1539}
1540
1541void
1542proxtrans (char *cmd, char *local, char *remote)
1543{
1544    sighand oldintr;
1545    int secndflag = 0, prox_type, nfnd;
1546    char *cmd2;
1547    fd_set mask;
1548
1549    if (strcmp (cmd, "RETR"))
1550	cmd2 = "RETR";
1551    else
1552	cmd2 = runique ? "STOU" : "STOR";
1553    if ((prox_type = type) == 0) {
1554	if (unix_server && unix_proxy)
1555	    prox_type = TYPE_I;
1556	else
1557	    prox_type = TYPE_A;
1558    }
1559    if (curtype != prox_type)
1560	changetype (prox_type, 1);
1561    if (command ("PASV") != COMPLETE) {
1562	printf ("proxy server does not support third party transfers.\n");
1563	return;
1564    }
1565    pswitch (0);
1566    if (!connected) {
1567	printf ("No primary connection\n");
1568	pswitch (1);
1569	code = -1;
1570	return;
1571    }
1572    if (curtype != prox_type)
1573	changetype (prox_type, 1);
1574    if (command ("PORT %s", pasv) != COMPLETE) {
1575	pswitch (1);
1576	return;
1577    }
1578    if (setjmp (ptabort))
1579	goto abort;
1580    oldintr = signal (SIGINT, abortpt);
1581    if (command ("%s %s", cmd, remote) != PRELIM) {
1582	signal (SIGINT, oldintr);
1583	pswitch (1);
1584	return;
1585    }
1586    sleep (2);
1587    pswitch (1);
1588    secndflag++;
1589    if (command ("%s %s", cmd2, local) != PRELIM)
1590	goto abort;
1591    ptflag++;
1592    getreply (0);
1593    pswitch (0);
1594    getreply (0);
1595    signal (SIGINT, oldintr);
1596    pswitch (1);
1597    ptflag = 0;
1598    printf ("local: %s remote: %s\n", local, remote);
1599    return;
1600abort:
1601    signal (SIGINT, SIG_IGN);
1602    ptflag = 0;
1603    if (strcmp (cmd, "RETR") && !proxy)
1604	pswitch (1);
1605    else if (!strcmp (cmd, "RETR") && proxy)
1606	pswitch (0);
1607    if (!cpend && !secndflag) {	/* only here if cmd = "STOR" (proxy=1) */
1608	if (command ("%s %s", cmd2, local) != PRELIM) {
1609	    pswitch (0);
1610	    if (cpend)
1611		abort_remote ((FILE *) NULL);
1612	}
1613	pswitch (1);
1614	if (ptabflg)
1615	    code = -1;
1616	signal (SIGINT, oldintr);
1617	return;
1618    }
1619    if (cpend)
1620	abort_remote ((FILE *) NULL);
1621    pswitch (!proxy);
1622    if (!cpend && !secndflag) {	/* only if cmd = "RETR" (proxy=1) */
1623	if (command ("%s %s", cmd2, local) != PRELIM) {
1624	    pswitch (0);
1625	    if (cpend)
1626		abort_remote ((FILE *) NULL);
1627	    pswitch (1);
1628	    if (ptabflg)
1629		code = -1;
1630	    signal (SIGINT, oldintr);
1631	    return;
1632	}
1633    }
1634    if (cpend)
1635	abort_remote ((FILE *) NULL);
1636    pswitch (!proxy);
1637    if (cpend) {
1638	FD_ZERO (&mask);
1639	if (fileno(cin) >= FD_SETSIZE)
1640	    errx (1, "fd too large");
1641	FD_SET (fileno (cin), &mask);
1642	if ((nfnd = empty (&mask, 10)) <= 0) {
1643	    if (nfnd < 0) {
1644		warn ("abort");
1645	    }
1646	    if (ptabflg)
1647		code = -1;
1648	    lostpeer (0);
1649	}
1650	getreply (0);
1651	getreply (0);
1652    }
1653    if (proxy)
1654	pswitch (0);
1655    pswitch (1);
1656    if (ptabflg)
1657	code = -1;
1658    signal (SIGINT, oldintr);
1659}
1660
1661void
1662reset (int argc, char **argv)
1663{
1664    fd_set mask;
1665    int nfnd = 1;
1666
1667    FD_ZERO (&mask);
1668    while (nfnd > 0) {
1669	if (fileno (cin) >= FD_SETSIZE)
1670	    errx (1, "fd too large");
1671	FD_SET (fileno (cin), &mask);
1672	if ((nfnd = empty (&mask, 0)) < 0) {
1673	    warn ("reset");
1674	    code = -1;
1675	    lostpeer(0);
1676	} else if (nfnd) {
1677	    getreply(0);
1678	}
1679    }
1680}
1681
1682char *
1683gunique (char *local)
1684{
1685    static char new[MaxPathLen];
1686    char *cp = strrchr (local, '/');
1687    int d, count = 0;
1688    char ext = '1';
1689
1690    if (cp)
1691	*cp = '\0';
1692    d = access (cp ? local : ".", 2);
1693    if (cp)
1694	*cp = '/';
1695    if (d < 0) {
1696	warn ("local: %s", local);
1697	return NULL;
1698    }
1699    strlcpy (new, local, sizeof(new));
1700    cp = new + strlen(new);
1701    *cp++ = '.';
1702    while (!d) {
1703	if (++count == 100) {
1704	    printf ("runique: can't find unique file name.\n");
1705	    return NULL;
1706	}
1707	*cp++ = ext;
1708	*cp = '\0';
1709	if (ext == '9')
1710	    ext = '0';
1711	else
1712	    ext++;
1713	if ((d = access (new, 0)) < 0)
1714	    break;
1715	if (ext != '0')
1716	    cp--;
1717	else if (*(cp - 2) == '.')
1718	    *(cp - 1) = '1';
1719	else {
1720	    *(cp - 2) = *(cp - 2) + 1;
1721	    cp--;
1722	}
1723    }
1724    return (new);
1725}
1726
1727void
1728abort_remote (FILE * din)
1729{
1730    char buf[BUFSIZ];
1731    int nfnd;
1732    fd_set mask;
1733
1734    /*
1735     * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1736     * after urgent byte rather than before as is protocol now
1737     */
1738    snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC);
1739    if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
1740	warn ("abort");
1741    fprintf (cout, "%cABOR\r\n", DM);
1742    fflush (cout);
1743    FD_ZERO (&mask);
1744    if (fileno (cin) >= FD_SETSIZE)
1745	errx (1, "fd too large");
1746    FD_SET (fileno (cin), &mask);
1747    if (din) {
1748    if (fileno (din) >= FD_SETSIZE)
1749	errx (1, "fd too large");
1750	FD_SET (fileno (din), &mask);
1751    }
1752    if ((nfnd = empty (&mask, 10)) <= 0) {
1753	if (nfnd < 0) {
1754	    warn ("abort");
1755	}
1756	if (ptabflg)
1757	    code = -1;
1758	lostpeer (0);
1759    }
1760    if (din && FD_ISSET (fileno (din), &mask)) {
1761	while (read (fileno (din), buf, BUFSIZ) > 0)
1762	     /* LOOP */ ;
1763    }
1764    if (getreply (0) == ERROR && code == 552) {
1765	/* 552 needed for nic style abort */
1766	getreply (0);
1767    }
1768    getreply (0);
1769}
1770