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