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