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