ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor-crypto/heimdal/dist/appl/ftp/ftp/ftp.c
Revision: 7130
Committed: Fri Jul 24 20:10:10 2015 UTC (8 years, 9 months ago) by laffer1
Content type: text/plain
File size: 39155 byte(s)
Log Message:
Update to heimdal 1.5.2

File Contents

# Content
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 }