xref: /freebsd/crypto/heimdal/appl/ftp/ftp/ftp.c (revision 61e21613)
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"
35 RCSID ("$Id$");
36 
37 struct sockaddr_storage hisctladdr_ss;
38 struct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss;
39 struct sockaddr_storage data_addr_ss;
40 struct sockaddr *data_addr  = (struct sockaddr *)&data_addr_ss;
41 struct sockaddr_storage myctladdr_ss;
42 struct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss;
43 int data = -1;
44 int abrtflag = 0;
45 jmp_buf ptabort;
46 int ptabflg;
47 int ptflag = 0;
48 off_t restart_point = 0;
49 
50 
51 FILE *cin, *cout;
52 
53 typedef void (*sighand) (int);
54 
55 char *
56 hookup (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);
159 bad:
160     close (s);
161     return NULL;
162 }
163 
164 int
165 login (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 
271 void
272 cmdabort (int sig)
273 {
274 
275     printf ("\n");
276     fflush (stdout);
277     abrtflag++;
278     if (ptflag)
279 	longjmp (ptabort, 1);
280 }
281 
282 int
283 command (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 
323 char reply_string[BUFSIZ];	/* last line of previous reply */
324 
325 int
326 getreply (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
446 int
447 getreply (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 
558 int
559 empty (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 
568 jmp_buf sendabort;
569 
570 static RETSIGTYPE
571 abortsend (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 
583 static int
584 copy_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     }
638 try_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 
668 void
669 sendrequest (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;
860 abort:
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 
883 jmp_buf recvabort;
884 
885 void
886 abortrecv (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 
896 void
897 recvrequest (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 	}
1124 break2:
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;
1156 abort:
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 
1184 static int
1185 parse_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 
1206 static int
1207 parse_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 
1241 static int
1242 passive_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);
1283 bad:
1284     close (data);
1285     data = -1;
1286     sendport = 1;
1287     return (1);
1288 }
1289 
1290 
1291 static int
1292 active_mode (void)
1293 {
1294     int tmpno = 0;
1295     socklen_t len;
1296     int result;
1297 
1298 noport:
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);
1393 bad:
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  */
1405 int
1406 initconn (void)
1407 {
1408     if (passivemode)
1409 	return passive_mode ();
1410     else
1411 	return active_mode ();
1412 }
1413 
1414 FILE *
1415 dataconn (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 
1439 void
1440 ptransfer (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 
1476 void
1477 psabort (int sig)
1478 {
1479 
1480     abrtflag++;
1481 }
1482 
1483 void
1484 pswitch (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 
1570 void
1571 abortpt (int sig)
1572 {
1573 
1574     printf ("\n");
1575     fflush (stdout);
1576     ptabflg++;
1577     mflag = 0;
1578     abrtflag = 0;
1579     longjmp (ptabort, 1);
1580 }
1581 
1582 void
1583 proxtrans (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;
1641 abort:
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 
1703 void
1704 reset (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 
1724 char *
1725 gunique (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 
1769 void
1770 abort_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