Annotation of src/usr.bin/ftp/ftp.c, Revision 1.53
1.53 ! millert 1: /* $OpenBSD: ftp.c,v 1.52 2003/04/05 17:19:47 deraadt Exp $ */
1.22 millert 2: /* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */
1.1 deraadt 3:
4: /*
1.34 itojun 5: * Copyright (C) 1997 and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
1.1 deraadt 34: * Copyright (c) 1985, 1989, 1993, 1994
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
1.53 ! millert 45: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: */
61:
62: #ifndef lint
63: #if 0
64: static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
65: #else
1.53 ! millert 66: static char rcsid[] = "$OpenBSD: ftp.c,v 1.52 2003/04/05 17:19:47 deraadt Exp $";
1.1 deraadt 67: #endif
68: #endif /* not lint */
69:
1.10 millert 70: #include <sys/types.h>
1.1 deraadt 71: #include <sys/stat.h>
72: #include <sys/socket.h>
73:
74: #include <netinet/in.h>
75: #include <netinet/in_systm.h>
76: #include <netinet/ip.h>
77: #include <arpa/inet.h>
78: #include <arpa/ftp.h>
79: #include <arpa/telnet.h>
80:
81: #include <ctype.h>
82: #include <err.h>
83: #include <errno.h>
84: #include <netdb.h>
85: #include <stdio.h>
86: #include <stdlib.h>
87: #include <string.h>
88: #include <unistd.h>
1.12 millert 89: #include <utime.h>
1.13 millert 90: #include <stdarg.h>
1.1 deraadt 91:
92: #include "ftp_var.h"
93:
1.34 itojun 94: union sockunion {
95: struct sockinet {
96: u_char si_len;
97: u_char si_family;
98: u_short si_port;
99: } su_si;
100: struct sockaddr_in su_sin;
101: struct sockaddr_in6 su_sin6;
102: };
103: #define su_len su_si.si_len
104: #define su_family su_si.si_family
105: #define su_port su_si.si_port
106:
107: union sockunion myctladdr, hisctladdr, data_addr;
108:
109: union sockunion hisctladdr;
110: union sockunion data_addr;
1.1 deraadt 111: int data = -1;
112: int abrtflag = 0;
113: jmp_buf ptabort;
114: int ptabflg;
115: int ptflag = 0;
1.34 itojun 116: union sockunion myctladdr;
1.1 deraadt 117: off_t restart_point = 0;
118:
119:
120: FILE *cin, *cout;
121:
122: char *
123: hookup(host, port)
1.34 itojun 124: char *host;
125: char *port;
1.1 deraadt 126: {
1.34 itojun 127: int s, len, tos, error;
1.10 millert 128: static char hostnamebuf[MAXHOSTNAMELEN];
1.34 itojun 129: struct addrinfo hints, *res, *res0;
1.51 itojun 130: char hbuf[NI_MAXHOST];
1.34 itojun 131: char *cause = "unknown";
132:
1.36 itojun 133: epsv4bad = 0;
134:
1.34 itojun 135: memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
136: memset(&hints, 0, sizeof(hints));
137: hints.ai_flags = AI_CANONNAME;
1.45 deraadt 138: hints.ai_family = family;
1.34 itojun 139: hints.ai_socktype = SOCK_STREAM;
140: hints.ai_protocol = 0;
141: error = getaddrinfo(host, port, &hints, &res0);
1.35 deraadt 142: if (error == EAI_SERVICE) {
143: /*
144: * If the services file is corrupt/missing, fall back
145: * on our hard-coded defines.
146: */
147: char pbuf[NI_MAXSERV];
148:
149: pbuf[0] = '\0';
150: if (strcmp(port, "ftp") == 0)
151: snprintf(pbuf, sizeof(pbuf), "%d", FTP_PORT);
152: else if (strcmp(port, "ftpgate") == 0)
153: snprintf(pbuf, sizeof(pbuf), "%d", GATE_PORT);
154: else if (strcmp(port, "http") == 0)
155: snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT);
156: if (pbuf[0])
157: error = getaddrinfo(host, pbuf, &hints, &res0);
158: }
1.34 itojun 159: if (error) {
1.39 itojun 160: if (error == EAI_SERVICE)
161: warnx("%s: bad port number `%s'", host, port);
162: else
163: warnx("%s: %s", host, gai_strerror(error));
1.1 deraadt 164: code = -1;
165: return (0);
166: }
1.34 itojun 167:
168: if (res0->ai_canonname)
1.41 lebel 169: strlcpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf));
1.34 itojun 170: else
1.41 lebel 171: strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
1.34 itojun 172: hostname = hostnamebuf;
173:
174: s = -1;
175: for (res = res0; res; res = res->ai_next) {
176: #if 0 /*old behavior*/
177: if (res != res0) /* not on the first address */
178: #else
179: if (res0->ai_next) /* if we have multiple possibilities */
180: #endif
181: {
1.50 itojun 182: if (getnameinfo(res->ai_addr, res->ai_addrlen,
183: hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
184: strlcpy(hbuf, "unknown", sizeof(hbuf));
1.34 itojun 185: fprintf(ttyout, "Trying %s...\n", hbuf);
186: }
187: s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
188: if (s < 0) {
189: cause = "socket";
1.27 deraadt 190: continue;
1.34 itojun 191: }
192: while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
193: && errno == EINTR) {
194: ;
195: }
196: if (error) {
197: /* this "if" clause is to prevent print warning twice */
198: if (res->ai_next) {
1.50 itojun 199: if (getnameinfo(res->ai_addr, res->ai_addrlen,
200: hbuf, sizeof(hbuf), NULL, 0,
201: NI_NUMERICHOST) != 0)
202: strlcpy(hbuf, "(unknown)",
203: sizeof(hbuf));
1.34 itojun 204: warn("connect to address %s", hbuf);
1.1 deraadt 205: }
1.34 itojun 206: cause = "connect";
207: close(s);
208: s = -1;
1.1 deraadt 209: continue;
210: }
1.34 itojun 211:
212: /* finally we got one */
213: break;
214: }
215: if (s < 0) {
1.38 millert 216: warn("%s", cause);
1.1 deraadt 217: code = -1;
1.34 itojun 218: freeaddrinfo(res0);
219: return 0;
1.1 deraadt 220: }
1.34 itojun 221: memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
222: len = res->ai_addrlen;
223: freeaddrinfo(res0);
224: res0 = res = NULL;
1.1 deraadt 225: if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
226: warn("getsockname");
227: code = -1;
228: goto bad;
229: }
1.34 itojun 230: #if defined(IPPROTO_IP) && defined(IP_TOS)
231: if (hisctladdr.su_family == AF_INET) {
232: tos = IPTOS_LOWDELAY;
233: if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
234: warn("setsockopt TOS (ignored)");
235: }
1.1 deraadt 236: #endif
237: cin = fdopen(s, "r");
238: cout = fdopen(s, "w");
239: if (cin == NULL || cout == NULL) {
240: warnx("fdopen failed.");
241: if (cin)
1.11 millert 242: (void)fclose(cin);
1.1 deraadt 243: if (cout)
1.11 millert 244: (void)fclose(cout);
1.1 deraadt 245: code = -1;
246: goto bad;
247: }
248: if (verbose)
1.18 deraadt 249: fprintf(ttyout, "Connected to %s.\n", hostname);
1.1 deraadt 250: if (getreply(0) > 2) { /* read startup message from server */
251: if (cin)
1.11 millert 252: (void)fclose(cin);
1.1 deraadt 253: if (cout)
1.11 millert 254: (void)fclose(cout);
1.1 deraadt 255: code = -1;
256: goto bad;
257: }
258: #ifdef SO_OOBINLINE
259: {
260: int on = 1;
261:
262: if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
263: < 0 && debug) {
264: warn("setsockopt");
265: }
266: }
267: #endif /* SO_OOBINLINE */
268:
269: return (hostname);
270: bad:
1.11 millert 271: (void)close(s);
1.1 deraadt 272: return ((char *)0);
273: }
274:
275: void
1.12 millert 276: cmdabort(notused)
277: int notused;
1.1 deraadt 278: {
279:
1.10 millert 280: alarmtimer(0);
1.18 deraadt 281: putc('\n', ttyout);
282: (void)fflush(ttyout);
1.1 deraadt 283: abrtflag++;
284: if (ptflag)
1.10 millert 285: longjmp(ptabort, 1);
1.1 deraadt 286: }
287:
288: /*VARARGS*/
289: int
1.13 millert 290: command(const char *fmt, ...)
1.1 deraadt 291: {
292: va_list ap;
293: int r;
294: sig_t oldintr;
295:
296: abrtflag = 0;
297: if (debug) {
1.18 deraadt 298: fputs("---> ", ttyout);
1.13 millert 299: va_start(ap, fmt);
1.1 deraadt 300: if (strncmp("PASS ", fmt, 5) == 0)
1.18 deraadt 301: fputs("PASS XXXX", ttyout);
1.10 millert 302: else if (strncmp("ACCT ", fmt, 5) == 0)
1.18 deraadt 303: fputs("ACCT XXXX", ttyout);
1.10 millert 304: else
1.28 millert 305: vfprintf(ttyout, fmt, ap);
1.1 deraadt 306: va_end(ap);
1.18 deraadt 307: putc('\n', ttyout);
308: (void)fflush(ttyout);
1.1 deraadt 309: }
310: if (cout == NULL) {
1.13 millert 311: warnx("No control connection for command.");
1.1 deraadt 312: code = -1;
313: return (0);
314: }
315: oldintr = signal(SIGINT, cmdabort);
1.13 millert 316: va_start(ap, fmt);
1.1 deraadt 317: vfprintf(cout, fmt, ap);
318: va_end(ap);
1.11 millert 319: fputs("\r\n", cout);
320: (void)fflush(cout);
1.1 deraadt 321: cpend = 1;
322: r = getreply(!strcmp(fmt, "QUIT"));
323: if (abrtflag && oldintr != SIG_IGN)
324: (*oldintr)(SIGINT);
1.11 millert 325: (void)signal(SIGINT, oldintr);
1.1 deraadt 326: return (r);
327: }
328:
1.10 millert 329: char reply_string[BUFSIZ]; /* first line of previous reply */
1.1 deraadt 330:
331: int
332: getreply(expecteof)
333: int expecteof;
334: {
1.10 millert 335: char current_line[BUFSIZ]; /* last line of previous reply */
336: int c, n, line;
1.1 deraadt 337: int dig;
338: int originalcode = 0, continuation = 0;
339: sig_t oldintr;
340: int pflag = 0;
341: char *cp, *pt = pasv;
342:
1.25 weingart 343: memset(current_line, 0, sizeof(current_line));
1.1 deraadt 344: oldintr = signal(SIGINT, cmdabort);
1.10 millert 345: for (line = 0 ;; line++) {
1.1 deraadt 346: dig = n = code = 0;
1.10 millert 347: cp = current_line;
1.23 millert 348: while ((c = fgetc(cin)) != '\n') {
1.1 deraadt 349: if (c == IAC) { /* handle telnet commands */
1.23 millert 350: switch (c = fgetc(cin)) {
1.1 deraadt 351: case WILL:
352: case WONT:
1.23 millert 353: c = fgetc(cin);
1.1 deraadt 354: fprintf(cout, "%c%c%c", IAC, DONT, c);
1.11 millert 355: (void)fflush(cout);
1.1 deraadt 356: break;
357: case DO:
358: case DONT:
1.23 millert 359: c = fgetc(cin);
1.1 deraadt 360: fprintf(cout, "%c%c%c", IAC, WONT, c);
1.11 millert 361: (void)fflush(cout);
1.1 deraadt 362: break;
363: default:
364: break;
365: }
366: continue;
367: }
368: dig++;
369: if (c == EOF) {
370: if (expecteof) {
1.11 millert 371: (void)signal(SIGINT, oldintr);
1.1 deraadt 372: code = 221;
373: return (0);
374: }
375: lostpeer();
376: if (verbose) {
1.18 deraadt 377: fputs(
378: "421 Service not available, remote server has closed connection.\n", ttyout);
379: (void)fflush(ttyout);
1.1 deraadt 380: }
381: code = 421;
382: return (4);
383: }
1.10 millert 384: if (c != '\r' && (verbose > 0 ||
1.21 mickey 385: ((verbose > -1 && n == '5' && dig > 4)) &&
386: (((!n && c < '5') || (n && n < '5'))
387: || !retry_connect))) {
1.1 deraadt 388: if (proxflag &&
1.10 millert 389: (dig == 1 || (dig == 5 && verbose == 0)))
1.18 deraadt 390: fprintf(ttyout, "%s:", hostname);
391: (void)putc(c, ttyout);
1.1 deraadt 392: }
393: if (dig < 4 && isdigit(c))
394: code = code * 10 + (c - '0');
1.34 itojun 395: if (!pflag && (code == 227 || code == 228))
1.1 deraadt 396: pflag = 1;
1.34 itojun 397: else if (!pflag && code == 229)
398: pflag = 100;
1.1 deraadt 399: if (dig > 4 && pflag == 1 && isdigit(c))
400: pflag = 2;
401: if (pflag == 2) {
1.44 itojun 402: if (c != '\r' && c != ')') {
403: if (pt < &pasv[sizeof(pasv) - 1])
404: *pt++ = c;
405: } else {
1.1 deraadt 406: *pt = '\0';
407: pflag = 3;
408: }
409: }
1.34 itojun 410: if (pflag == 100 && c == '(')
411: pflag = 2;
1.1 deraadt 412: if (dig == 4 && c == '-') {
413: if (continuation)
414: code = 0;
415: continuation++;
416: }
1.10 millert 417: if (n == 0)
418: n = c;
419: if (cp < ¤t_line[sizeof(current_line) - 1])
1.1 deraadt 420: *cp++ = c;
421: }
1.11 millert 422: if (verbose > 0 || ((verbose > -1 && n == '5') &&
423: (n < '5' || !retry_connect))) {
1.18 deraadt 424: (void)putc(c, ttyout);
425: (void)fflush (ttyout);
1.1 deraadt 426: }
1.10 millert 427: if (line == 0) {
428: size_t len = cp - current_line;
429:
430: if (len > sizeof(reply_string))
431: len = sizeof(reply_string);
432:
1.48 itojun 433: (void)strlcpy(reply_string, current_line, len);
1.10 millert 434: }
1.1 deraadt 435: if (continuation && code != originalcode) {
436: if (originalcode == 0)
437: originalcode = code;
438: continue;
439: }
440: *cp = '\0';
441: if (n != '1')
442: cpend = 0;
1.11 millert 443: (void)signal(SIGINT, oldintr);
1.1 deraadt 444: if (code == 421 || originalcode == 421)
445: lostpeer();
446: if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
447: (*oldintr)(SIGINT);
448: return (n - '0');
449: }
450: }
451:
452: int
453: empty(mask, sec)
1.29 art 454: fd_set *mask;
1.1 deraadt 455: int sec;
456: {
457: struct timeval t;
458:
459: t.tv_sec = (long) sec;
460: t.tv_usec = 0;
1.29 art 461: return (select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
1.1 deraadt 462: }
463:
464: jmp_buf sendabort;
465:
466: void
1.12 millert 467: abortsend(notused)
468: int notused;
1.1 deraadt 469: {
470:
1.10 millert 471: alarmtimer(0);
1.1 deraadt 472: mflag = 0;
473: abrtflag = 0;
1.18 deraadt 474: fputs("\nsend aborted\nwaiting for remote to finish abort.\n", ttyout);
475: (void)fflush(ttyout);
1.1 deraadt 476: longjmp(sendabort, 1);
477: }
478:
479: void
480: sendrequest(cmd, local, remote, printnames)
1.10 millert 481: const char *cmd, *local, *remote;
1.1 deraadt 482: int printnames;
483: {
484: struct stat st;
485: int c, d;
1.40 millert 486: FILE * volatile fin, * volatile dout;
1.42 millert 487: int (* volatile closefunc)(FILE *);
1.40 millert 488: volatile sig_t oldinti, oldintr, oldintp;
1.20 millert 489: volatile off_t hashbytes;
1.40 millert 490: char * volatile lmode;
491: char buf[BUFSIZ], *bufp;
1.13 millert 492: int oprogress;
1.1 deraadt 493:
1.10 millert 494: hashbytes = mark;
495: direction = "sent";
1.20 millert 496: dout = NULL;
1.10 millert 497: bytes = 0;
498: filesize = -1;
1.13 millert 499: oprogress = progress;
1.1 deraadt 500: if (verbose && printnames) {
501: if (local && *local != '-')
1.18 deraadt 502: fprintf(ttyout, "local: %s ", local);
1.1 deraadt 503: if (remote)
1.18 deraadt 504: fprintf(ttyout, "remote: %s\n", remote);
1.1 deraadt 505: }
506: if (proxy) {
507: proxtrans(cmd, local, remote);
508: return;
509: }
510: if (curtype != type)
511: changetype(type, 0);
512: closefunc = NULL;
513: oldintr = NULL;
514: oldintp = NULL;
1.10 millert 515: oldinti = NULL;
1.1 deraadt 516: lmode = "w";
517: if (setjmp(sendabort)) {
518: while (cpend) {
1.11 millert 519: (void)getreply(0);
1.1 deraadt 520: }
521: if (data >= 0) {
1.11 millert 522: (void)close(data);
1.1 deraadt 523: data = -1;
524: }
525: if (oldintr)
1.11 millert 526: (void)signal(SIGINT, oldintr);
1.1 deraadt 527: if (oldintp)
1.11 millert 528: (void)signal(SIGPIPE, oldintp);
1.10 millert 529: if (oldinti)
1.11 millert 530: (void)signal(SIGINFO, oldinti);
1.13 millert 531: progress = oprogress;
1.1 deraadt 532: code = -1;
533: return;
534: }
535: oldintr = signal(SIGINT, abortsend);
1.10 millert 536: oldinti = signal(SIGINFO, psummary);
1.13 millert 537: if (strcmp(local, "-") == 0) {
1.1 deraadt 538: fin = stdin;
1.31 millert 539: if (progress == 1)
540: progress = 0;
1.13 millert 541: } else if (*local == '|') {
1.10 millert 542: oldintp = signal(SIGPIPE, SIG_IGN);
1.1 deraadt 543: fin = popen(local + 1, "r");
544: if (fin == NULL) {
545: warn("%s", local + 1);
1.11 millert 546: (void)signal(SIGINT, oldintr);
547: (void)signal(SIGPIPE, oldintp);
548: (void)signal(SIGINFO, oldinti);
1.1 deraadt 549: code = -1;
550: return;
551: }
1.31 millert 552: if (progress == 1)
553: progress = 0;
1.1 deraadt 554: closefunc = pclose;
555: } else {
556: fin = fopen(local, "r");
557: if (fin == NULL) {
558: warn("local: %s", local);
1.11 millert 559: (void)signal(SIGINT, oldintr);
560: (void)signal(SIGINFO, oldinti);
1.1 deraadt 561: code = -1;
562: return;
563: }
564: closefunc = fclose;
565: if (fstat(fileno(fin), &st) < 0 ||
1.14 millert 566: (st.st_mode & S_IFMT) != S_IFREG) {
1.18 deraadt 567: fprintf(ttyout, "%s: not a plain file.\n", local);
1.11 millert 568: (void)signal(SIGINT, oldintr);
569: (void)signal(SIGINFO, oldinti);
1.1 deraadt 570: fclose(fin);
571: code = -1;
572: return;
573: }
1.10 millert 574: filesize = st.st_size;
1.1 deraadt 575: }
576: if (initconn()) {
1.11 millert 577: (void)signal(SIGINT, oldintr);
578: (void)signal(SIGINFO, oldinti);
1.1 deraadt 579: if (oldintp)
1.11 millert 580: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 581: code = -1;
1.13 millert 582: progress = oprogress;
1.1 deraadt 583: if (closefunc != NULL)
584: (*closefunc)(fin);
585: return;
586: }
587: if (setjmp(sendabort))
588: goto abort;
589:
590: if (restart_point &&
591: (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
592: int rc;
593:
1.10 millert 594: rc = -1;
1.1 deraadt 595: switch (curtype) {
596: case TYPE_A:
597: rc = fseek(fin, (long) restart_point, SEEK_SET);
598: break;
599: case TYPE_I:
600: case TYPE_L:
601: rc = lseek(fileno(fin), restart_point, SEEK_SET);
602: break;
603: }
604: if (rc < 0) {
605: warn("local: %s", local);
606: restart_point = 0;
1.13 millert 607: progress = oprogress;
1.1 deraadt 608: if (closefunc != NULL)
609: (*closefunc)(fin);
610: return;
611: }
612: if (command("REST %ld", (long) restart_point)
613: != CONTINUE) {
614: restart_point = 0;
1.13 millert 615: progress = oprogress;
1.1 deraadt 616: if (closefunc != NULL)
617: (*closefunc)(fin);
618: return;
619: }
620: restart_point = 0;
621: lmode = "r+w";
622: }
623: if (remote) {
624: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 625: (void)signal(SIGINT, oldintr);
626: (void)signal(SIGINFO, oldinti);
1.13 millert 627: progress = oprogress;
1.1 deraadt 628: if (oldintp)
1.11 millert 629: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 630: if (closefunc != NULL)
631: (*closefunc)(fin);
632: return;
633: }
634: } else
635: if (command("%s", cmd) != PRELIM) {
1.11 millert 636: (void)signal(SIGINT, oldintr);
637: (void)signal(SIGINFO, oldinti);
1.13 millert 638: progress = oprogress;
1.1 deraadt 639: if (oldintp)
1.11 millert 640: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 641: if (closefunc != NULL)
642: (*closefunc)(fin);
643: return;
644: }
645: dout = dataconn(lmode);
646: if (dout == NULL)
647: goto abort;
1.10 millert 648: progressmeter(-1);
1.1 deraadt 649: oldintp = signal(SIGPIPE, SIG_IGN);
650: switch (curtype) {
651:
652: case TYPE_I:
653: case TYPE_L:
654: errno = d = 0;
1.11 millert 655: while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
1.1 deraadt 656: bytes += c;
657: for (bufp = buf; c > 0; c -= d, bufp += d)
1.20 millert 658: if ((d = write(fileno(dout), bufp, (size_t)c))
659: <= 0)
1.1 deraadt 660: break;
1.10 millert 661: if (hash && (!progress || filesize < 0) ) {
1.1 deraadt 662: while (bytes >= hashbytes) {
1.18 deraadt 663: (void)putc('#', ttyout);
1.7 kstailey 664: hashbytes += mark;
1.1 deraadt 665: }
1.18 deraadt 666: (void)fflush(ttyout);
1.1 deraadt 667: }
668: }
1.10 millert 669: if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7 kstailey 670: if (bytes < mark)
1.18 deraadt 671: (void)putc('#', ttyout);
672: (void)putc('\n', ttyout);
673: (void)fflush(ttyout);
1.1 deraadt 674: }
675: if (c < 0)
676: warn("local: %s", local);
677: if (d < 0) {
1.10 millert 678: if (errno != EPIPE)
1.1 deraadt 679: warn("netout");
680: bytes = -1;
681: }
682: break;
683:
684: case TYPE_A:
1.23 millert 685: while ((c = fgetc(fin)) != EOF) {
1.1 deraadt 686: if (c == '\n') {
1.10 millert 687: while (hash && (!progress || filesize < 0) &&
688: (bytes >= hashbytes)) {
1.18 deraadt 689: (void)putc('#', ttyout);
690: (void)fflush(ttyout);
1.7 kstailey 691: hashbytes += mark;
1.1 deraadt 692: }
693: if (ferror(dout))
694: break;
1.11 millert 695: (void)putc('\r', dout);
1.1 deraadt 696: bytes++;
697: }
1.11 millert 698: (void)putc(c, dout);
1.1 deraadt 699: bytes++;
1.10 millert 700: #if 0 /* this violates RFC */
701: if (c == '\r') {
702: (void)putc('\0', dout);
703: bytes++;
704: }
705: #endif
1.1 deraadt 706: }
1.10 millert 707: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 708: if (bytes < hashbytes)
1.18 deraadt 709: (void)putc('#', ttyout);
710: (void)putc('\n', ttyout);
711: (void)fflush(ttyout);
1.1 deraadt 712: }
713: if (ferror(fin))
714: warn("local: %s", local);
715: if (ferror(dout)) {
716: if (errno != EPIPE)
717: warn("netout");
718: bytes = -1;
719: }
720: break;
721: }
1.10 millert 722: progressmeter(1);
1.13 millert 723: progress = oprogress;
1.1 deraadt 724: if (closefunc != NULL)
725: (*closefunc)(fin);
1.11 millert 726: (void)fclose(dout);
727: (void)getreply(0);
728: (void)signal(SIGINT, oldintr);
729: (void)signal(SIGINFO, oldinti);
1.1 deraadt 730: if (oldintp)
1.11 millert 731: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 732: if (bytes > 0)
1.10 millert 733: ptransfer(0);
1.1 deraadt 734: return;
735: abort:
1.11 millert 736: (void)signal(SIGINT, oldintr);
737: (void)signal(SIGINFO, oldinti);
1.13 millert 738: progress = oprogress;
1.1 deraadt 739: if (oldintp)
1.11 millert 740: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 741: if (!cpend) {
742: code = -1;
743: return;
744: }
745: if (data >= 0) {
1.11 millert 746: (void)close(data);
1.1 deraadt 747: data = -1;
748: }
749: if (dout)
1.11 millert 750: (void)fclose(dout);
751: (void)getreply(0);
1.1 deraadt 752: code = -1;
753: if (closefunc != NULL && fin != NULL)
754: (*closefunc)(fin);
755: if (bytes > 0)
1.10 millert 756: ptransfer(0);
1.1 deraadt 757: }
758:
759: jmp_buf recvabort;
760:
761: void
1.12 millert 762: abortrecv(notused)
763: int notused;
1.1 deraadt 764: {
765:
1.10 millert 766: alarmtimer(0);
1.1 deraadt 767: mflag = 0;
768: abrtflag = 0;
1.18 deraadt 769: fputs("\nreceive aborted\nwaiting for remote to finish abort.\n", ttyout);
770: (void)fflush(ttyout);
1.1 deraadt 771: longjmp(recvabort, 1);
772: }
773:
774: void
1.22 millert 775: recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
1.40 millert 776: const char *cmd, * volatile local, *remote, *lmode;
1.22 millert 777: int printnames, ignorespecial;
1.1 deraadt 778: {
1.40 millert 779: FILE * volatile fout, * volatile din;
1.42 millert 780: int (* volatile closefunc)(FILE *);
1.40 millert 781: volatile sig_t oldinti, oldintr, oldintp;
1.20 millert 782: int c, d;
783: volatile int is_retr, tcrflag, bare_lfs;
784: static size_t bufsize;
1.1 deraadt 785: static char *buf;
1.20 millert 786: volatile off_t hashbytes;
1.1 deraadt 787: struct stat st;
1.10 millert 788: time_t mtime;
1.13 millert 789: int oprogress;
1.16 millert 790: int opreserve;
1.1 deraadt 791:
1.20 millert 792: fout = NULL;
793: din = NULL;
794: oldinti = NULL;
1.10 millert 795: hashbytes = mark;
796: direction = "received";
797: bytes = 0;
1.20 millert 798: bare_lfs = 0;
1.10 millert 799: filesize = -1;
1.13 millert 800: oprogress = progress;
1.16 millert 801: opreserve = preserve;
1.1 deraadt 802: is_retr = strcmp(cmd, "RETR") == 0;
803: if (is_retr && verbose && printnames) {
1.22 millert 804: if (local && (ignorespecial || *local != '-'))
1.18 deraadt 805: fprintf(ttyout, "local: %s ", local);
1.1 deraadt 806: if (remote)
1.18 deraadt 807: fprintf(ttyout, "remote: %s\n", remote);
1.1 deraadt 808: }
809: if (proxy && is_retr) {
810: proxtrans(cmd, local, remote);
811: return;
812: }
813: closefunc = NULL;
814: oldintr = NULL;
815: oldintp = NULL;
816: tcrflag = !crflag && is_retr;
817: if (setjmp(recvabort)) {
818: while (cpend) {
1.11 millert 819: (void)getreply(0);
1.1 deraadt 820: }
821: if (data >= 0) {
1.11 millert 822: (void)close(data);
1.1 deraadt 823: data = -1;
824: }
825: if (oldintr)
1.11 millert 826: (void)signal(SIGINT, oldintr);
1.10 millert 827: if (oldinti)
1.11 millert 828: (void)signal(SIGINFO, oldinti);
1.15 millert 829: progress = oprogress;
1.16 millert 830: preserve = opreserve;
1.1 deraadt 831: code = -1;
832: return;
833: }
834: oldintr = signal(SIGINT, abortrecv);
1.10 millert 835: oldinti = signal(SIGINFO, psummary);
1.22 millert 836: if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
837: if (access(local, W_OK) < 0) {
1.1 deraadt 838: char *dir = strrchr(local, '/');
839:
840: if (errno != ENOENT && errno != EACCES) {
841: warn("local: %s", local);
1.11 millert 842: (void)signal(SIGINT, oldintr);
843: (void)signal(SIGINFO, oldinti);
1.1 deraadt 844: code = -1;
845: return;
846: }
847: if (dir != NULL)
848: *dir = 0;
1.22 millert 849: d = access(dir == local ? "/" : dir ? local : ".", W_OK);
1.1 deraadt 850: if (dir != NULL)
851: *dir = '/';
852: if (d < 0) {
853: warn("local: %s", local);
1.11 millert 854: (void)signal(SIGINT, oldintr);
855: (void)signal(SIGINFO, oldinti);
1.1 deraadt 856: code = -1;
857: return;
858: }
859: if (!runique && errno == EACCES &&
1.20 millert 860: chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
1.1 deraadt 861: warn("local: %s", local);
1.11 millert 862: (void)signal(SIGINT, oldintr);
863: (void)signal(SIGINFO, oldinti);
1.1 deraadt 864: code = -1;
865: return;
866: }
867: if (runique && errno == EACCES &&
868: (local = gunique(local)) == NULL) {
1.11 millert 869: (void)signal(SIGINT, oldintr);
870: (void)signal(SIGINFO, oldinti);
1.1 deraadt 871: code = -1;
872: return;
873: }
874: }
875: else if (runique && (local = gunique(local)) == NULL) {
1.11 millert 876: (void)signal(SIGINT, oldintr);
877: (void)signal(SIGINFO, oldinti);
1.1 deraadt 878: code = -1;
879: return;
880: }
881: }
882: if (!is_retr) {
883: if (curtype != TYPE_A)
884: changetype(TYPE_A, 0);
1.10 millert 885: } else {
886: if (curtype != type)
887: changetype(type, 0);
888: filesize = remotesize(remote, 0);
889: }
1.1 deraadt 890: if (initconn()) {
1.11 millert 891: (void)signal(SIGINT, oldintr);
892: (void)signal(SIGINFO, oldinti);
1.1 deraadt 893: code = -1;
894: return;
895: }
896: if (setjmp(recvabort))
897: goto abort;
898: if (is_retr && restart_point &&
899: command("REST %ld", (long) restart_point) != CONTINUE)
900: return;
901: if (remote) {
902: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 903: (void)signal(SIGINT, oldintr);
904: (void)signal(SIGINFO, oldinti);
1.1 deraadt 905: return;
906: }
907: } else {
908: if (command("%s", cmd) != PRELIM) {
1.11 millert 909: (void)signal(SIGINT, oldintr);
910: (void)signal(SIGINFO, oldinti);
1.1 deraadt 911: return;
912: }
913: }
914: din = dataconn("r");
915: if (din == NULL)
916: goto abort;
1.22 millert 917: if (!ignorespecial && strcmp(local, "-") == 0) {
1.1 deraadt 918: fout = stdout;
1.16 millert 919: preserve = 0;
1.22 millert 920: } else if (!ignorespecial && *local == '|') {
1.1 deraadt 921: oldintp = signal(SIGPIPE, SIG_IGN);
922: fout = popen(local + 1, "w");
923: if (fout == NULL) {
924: warn("%s", local+1);
925: goto abort;
926: }
1.31 millert 927: if (progress == 1)
928: progress = 0;
1.16 millert 929: preserve = 0;
1.1 deraadt 930: closefunc = pclose;
931: } else {
932: fout = fopen(local, lmode);
933: if (fout == NULL) {
934: warn("local: %s", local);
935: goto abort;
936: }
937: closefunc = fclose;
938: }
939: if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
940: st.st_blksize = BUFSIZ;
941: if (st.st_blksize > bufsize) {
942: if (buf)
1.11 millert 943: (void)free(buf);
1.1 deraadt 944: buf = malloc((unsigned)st.st_blksize);
945: if (buf == NULL) {
946: warn("malloc");
947: bufsize = 0;
948: goto abort;
949: }
950: bufsize = st.st_blksize;
951: }
1.14 millert 952: if ((st.st_mode & S_IFMT) != S_IFREG) {
1.31 millert 953: if (progress == 1)
954: progress = 0;
1.13 millert 955: preserve = 0;
956: }
1.10 millert 957: progressmeter(-1);
1.1 deraadt 958: switch (curtype) {
959:
960: case TYPE_I:
961: case TYPE_L:
962: if (restart_point &&
963: lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
964: warn("local: %s", local);
1.13 millert 965: progress = oprogress;
1.16 millert 966: preserve = opreserve;
1.1 deraadt 967: if (closefunc != NULL)
968: (*closefunc)(fout);
969: return;
970: }
971: errno = d = 0;
972: while ((c = read(fileno(din), buf, bufsize)) > 0) {
1.32 deraadt 973: size_t wr;
974: size_t rd = c;
975:
976: d = 0;
977: do {
978: wr = write(fileno(fout), buf + d, rd);
979: if (wr == -1 && errno == EPIPE)
980: break;
981: d += wr;
982: rd -= wr;
983: } while (d < c);
984: if (rd != 0)
1.1 deraadt 985: break;
986: bytes += c;
1.10 millert 987: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 988: while (bytes >= hashbytes) {
1.18 deraadt 989: (void)putc('#', ttyout);
1.7 kstailey 990: hashbytes += mark;
1.1 deraadt 991: }
1.18 deraadt 992: (void)fflush(ttyout);
1.1 deraadt 993: }
994: }
1.10 millert 995: if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7 kstailey 996: if (bytes < mark)
1.18 deraadt 997: (void)putc('#', ttyout);
998: (void)putc('\n', ttyout);
999: (void)fflush(ttyout);
1.1 deraadt 1000: }
1001: if (c < 0) {
1002: if (errno != EPIPE)
1003: warn("netin");
1004: bytes = -1;
1005: }
1006: if (d < c) {
1007: if (d < 0)
1008: warn("local: %s", local);
1009: else
1010: warnx("%s: short write", local);
1011: }
1012: break;
1013:
1014: case TYPE_A:
1015: if (restart_point) {
1016: int i, n, ch;
1017:
1018: if (fseek(fout, 0L, SEEK_SET) < 0)
1019: goto done;
1020: n = restart_point;
1021: for (i = 0; i++ < n;) {
1.23 millert 1022: if ((ch = fgetc(fout)) == EOF)
1.1 deraadt 1023: goto done;
1024: if (ch == '\n')
1025: i++;
1026: }
1027: if (fseek(fout, 0L, SEEK_CUR) < 0) {
1028: done:
1029: warn("local: %s", local);
1.13 millert 1030: progress = oprogress;
1.16 millert 1031: preserve = opreserve;
1.1 deraadt 1032: if (closefunc != NULL)
1033: (*closefunc)(fout);
1034: return;
1035: }
1036: }
1.23 millert 1037: while ((c = fgetc(din)) != EOF) {
1.1 deraadt 1038: if (c == '\n')
1039: bare_lfs++;
1040: while (c == '\r') {
1.10 millert 1041: while (hash && (!progress || filesize < 0) &&
1042: (bytes >= hashbytes)) {
1.18 deraadt 1043: (void)putc('#', ttyout);
1044: (void)fflush(ttyout);
1.7 kstailey 1045: hashbytes += mark;
1.1 deraadt 1046: }
1047: bytes++;
1.23 millert 1048: if ((c = fgetc(din)) != '\n' || tcrflag) {
1.1 deraadt 1049: if (ferror(fout))
1050: goto break2;
1.11 millert 1051: (void)putc('\r', fout);
1.1 deraadt 1052: if (c == '\0') {
1053: bytes++;
1054: goto contin2;
1055: }
1056: if (c == EOF)
1057: goto contin2;
1058: }
1059: }
1.11 millert 1060: (void)putc(c, fout);
1.1 deraadt 1061: bytes++;
1062: contin2: ;
1063: }
1064: break2:
1065: if (bare_lfs) {
1.22 millert 1066: fprintf(ttyout,
1.13 millert 1067: "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1.22 millert 1068: fputs("File may not have transferred correctly.\n",
1069: ttyout);
1.1 deraadt 1070: }
1.10 millert 1071: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 1072: if (bytes < hashbytes)
1.18 deraadt 1073: (void)putc('#', ttyout);
1074: (void)putc('\n', ttyout);
1075: (void)fflush(ttyout);
1.1 deraadt 1076: }
1077: if (ferror(din)) {
1078: if (errno != EPIPE)
1079: warn("netin");
1080: bytes = -1;
1081: }
1082: if (ferror(fout))
1083: warn("local: %s", local);
1084: break;
1085: }
1.10 millert 1086: progressmeter(1);
1.13 millert 1087: progress = oprogress;
1.16 millert 1088: preserve = opreserve;
1.1 deraadt 1089: if (closefunc != NULL)
1090: (*closefunc)(fout);
1.11 millert 1091: (void)signal(SIGINT, oldintr);
1092: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1093: if (oldintp)
1.11 millert 1094: (void)signal(SIGPIPE, oldintp);
1095: (void)fclose(din);
1096: (void)getreply(0);
1.10 millert 1097: if (bytes >= 0 && is_retr) {
1098: if (bytes > 0)
1099: ptransfer(0);
1100: if (preserve && (closefunc == fclose)) {
1101: mtime = remotemodtime(remote, 0);
1102: if (mtime != -1) {
1.12 millert 1103: struct utimbuf ut;
1104:
1105: ut.actime = time(NULL);
1106: ut.modtime = mtime;
1107: if (utime(local, &ut) == -1)
1.22 millert 1108: fprintf(ttyout,
1.13 millert 1109: "Can't change modification time on %s to %s",
1.11 millert 1110: local, asctime(localtime(&mtime)));
1.10 millert 1111: }
1112: }
1113: }
1.1 deraadt 1114: return;
1.13 millert 1115:
1.1 deraadt 1116: abort:
1117:
1.10 millert 1118: /* abort using RFC959 recommended IP,SYNC sequence */
1.1 deraadt 1119:
1.13 millert 1120: progress = oprogress;
1.16 millert 1121: preserve = opreserve;
1.1 deraadt 1122: if (oldintp)
1.11 millert 1123: (void)signal(SIGPIPE, oldintp);
1124: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1125: if (!cpend) {
1126: code = -1;
1.11 millert 1127: (void)signal(SIGINT, oldintr);
1128: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1129: return;
1130: }
1131:
1132: abort_remote(din);
1133: code = -1;
1134: if (data >= 0) {
1.11 millert 1135: (void)close(data);
1.1 deraadt 1136: data = -1;
1137: }
1138: if (closefunc != NULL && fout != NULL)
1139: (*closefunc)(fout);
1140: if (din)
1.11 millert 1141: (void)fclose(din);
1.1 deraadt 1142: if (bytes > 0)
1.10 millert 1143: ptransfer(0);
1.11 millert 1144: (void)signal(SIGINT, oldintr);
1145: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1146: }
1147:
1148: /*
1149: * Need to start a listen on the data channel before we send the command,
1150: * otherwise the server's connect may fail.
1151: */
1152: int
1153: initconn()
1154: {
1155: char *p, *a;
1.37 fgsch 1156: int result = ERROR, len, tmpno = 0;
1.1 deraadt 1157: int on = 1;
1.34 itojun 1158: int error;
1159: u_int addr[16], port[2];
1160: u_int af, hal, pal;
1161: char *pasvcmd = NULL;
1162:
1163: if (myctladdr.su_family == AF_INET6
1164: && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
1165: || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
1166: warnx("use of scoped address can be troublesome");
1167: }
1.24 millert 1168: reinit:
1.1 deraadt 1169: if (passivemode) {
1.34 itojun 1170: data_addr = myctladdr;
1171: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1172: if (data < 0) {
1.10 millert 1173: warn("socket");
1174: return (1);
1.1 deraadt 1175: }
1176: if ((options & SO_DEBUG) &&
1177: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1178: sizeof(on)) < 0)
1.10 millert 1179: warn("setsockopt (ignored)");
1.34 itojun 1180: switch (data_addr.su_family) {
1181: case AF_INET:
1.36 itojun 1182: if (epsv4 && !epsv4bad) {
1183: result = command(pasvcmd = "EPSV");
1184: if (code / 10 == 22 && code != 229) {
1185: fputs(
1.34 itojun 1186: "wrong server: return code must be 229\n",
1.36 itojun 1187: ttyout);
1188: result = COMPLETE + 1;
1189: }
1190: if (result != COMPLETE) {
1191: epsv4bad = 1;
1192: if (debug) {
1193: fputs(
1194: "disabling epsv4 for this connection\n",
1195: ttyout);
1196: }
1197: }
1.34 itojun 1198: }
1199: if (result != COMPLETE)
1200: result = command(pasvcmd = "PASV");
1201: break;
1202: case AF_INET6:
1203: result = command(pasvcmd = "EPSV");
1204: if (code / 10 == 22 && code != 229) {
1205: fputs(
1206: "wrong server: return code must be 229\n",
1207: ttyout);
1208: result = COMPLETE + 1;
1209: }
1210: if (result != COMPLETE)
1211: result = command(pasvcmd = "LPSV");
1212: break;
1213: default:
1214: result = COMPLETE + 1;
1215: break;
1216: }
1217: if (result != COMPLETE) {
1.24 millert 1218: if (activefallback) {
1219: (void)close(data);
1220: data = -1;
1221: passivemode = 0;
1222: activefallback = 0;
1223: goto reinit;
1224: }
1.18 deraadt 1225: fputs("Passive mode refused.\n", ttyout);
1.1 deraadt 1226: goto bad;
1227: }
1228:
1.34 itojun 1229: #define pack2(var, off) \
1230: (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1231: #define pack4(var, off) \
1232: (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1233: ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1234:
1.1 deraadt 1235: /*
1.34 itojun 1236: * What we've got at this point is a string of comma separated
1237: * one-byte unsigned integer values, separated by commas.
1.1 deraadt 1238: */
1.38 millert 1239: if (!pasvcmd)
1240: goto bad;
1.34 itojun 1241: if (strcmp(pasvcmd, "PASV") == 0) {
1242: if (data_addr.su_family != AF_INET) {
1243: fputs(
1244: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1245: error = 1;
1246: goto bad;
1247: }
1248: if (code / 10 == 22 && code != 227) {
1249: fputs("wrong server: return code must be 227\n",
1250: ttyout);
1251: error = 1;
1252: goto bad;
1253: }
1254: error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1255: &addr[0], &addr[1], &addr[2], &addr[3],
1256: &port[0], &port[1]);
1257: if (error != 6) {
1258: fputs(
1259: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1260: error = 1;
1261: goto bad;
1262: }
1263: error = 0;
1264: memset(&data_addr, 0, sizeof(data_addr));
1265: data_addr.su_family = AF_INET;
1266: data_addr.su_len = sizeof(struct sockaddr_in);
1267: data_addr.su_sin.sin_addr.s_addr =
1268: htonl(pack4(addr, 0));
1269: data_addr.su_port = htons(pack2(port, 0));
1270: } else if (strcmp(pasvcmd, "LPSV") == 0) {
1271: if (code / 10 == 22 && code != 228) {
1272: fputs("wrong server: return code must be 228\n",
1273: ttyout);
1274: error = 1;
1275: goto bad;
1276: }
1277: switch (data_addr.su_family) {
1278: case AF_INET:
1279: error = sscanf(pasv,
1280: "%u,%u,%u,%u,%u,%u,%u,%u,%u",
1281: &af, &hal,
1282: &addr[0], &addr[1], &addr[2], &addr[3],
1283: &pal, &port[0], &port[1]);
1284: if (error != 9) {
1285: fputs(
1286: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1287: error = 1;
1288: goto bad;
1289: }
1290: if (af != 4 || hal != 4 || pal != 2) {
1291: fputs(
1292: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1293: error = 1;
1294: goto bad;
1295: }
1.1 deraadt 1296:
1.34 itojun 1297: error = 0;
1298: memset(&data_addr, 0, sizeof(data_addr));
1299: data_addr.su_family = AF_INET;
1300: data_addr.su_len = sizeof(struct sockaddr_in);
1301: data_addr.su_sin.sin_addr.s_addr =
1302: htonl(pack4(addr, 0));
1303: data_addr.su_port = htons(pack2(port, 0));
1304: break;
1305: case AF_INET6:
1306: error = sscanf(pasv,
1307: "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1308: &af, &hal,
1309: &addr[0], &addr[1], &addr[2], &addr[3],
1310: &addr[4], &addr[5], &addr[6], &addr[7],
1311: &addr[8], &addr[9], &addr[10],
1312: &addr[11], &addr[12], &addr[13],
1313: &addr[14], &addr[15],
1314: &pal, &port[0], &port[1]);
1315: if (error != 21) {
1316: fputs(
1.18 deraadt 1317: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1.34 itojun 1318: error = 1;
1319: goto bad;
1320: }
1321: if (af != 6 || hal != 16 || pal != 2) {
1322: fputs(
1323: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1324: error = 1;
1325: goto bad;
1326: }
1327:
1328: error = 0;
1329: memset(&data_addr, 0, sizeof(data_addr));
1330: data_addr.su_family = AF_INET6;
1331: data_addr.su_len = sizeof(struct sockaddr_in6);
1332: {
1333: u_int32_t *p32;
1334: p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
1335: p32[0] = htonl(pack4(addr, 0));
1336: p32[1] = htonl(pack4(addr, 4));
1337: p32[2] = htonl(pack4(addr, 8));
1338: p32[3] = htonl(pack4(addr, 12));
1339: }
1340: data_addr.su_port = htons(pack2(port, 0));
1341: break;
1342: default:
1343: error = 1;
1344: }
1345: } else if (strcmp(pasvcmd, "EPSV") == 0) {
1346: char delim[4];
1347:
1348: port[0] = 0;
1349: if (code / 10 == 22 && code != 229) {
1350: fputs("wrong server: return code must be 229\n",
1351: ttyout);
1352: error = 1;
1353: goto bad;
1354: }
1355: if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1356: &delim[1], &delim[2], &port[1],
1357: &delim[3]) != 5) {
1358: fputs("parse error!\n", ttyout);
1359: error = 1;
1360: goto bad;
1361: }
1362: if (delim[0] != delim[1] || delim[0] != delim[2]
1363: || delim[0] != delim[3]) {
1364: fputs("parse error!\n", ttyout);
1365: error = 1;
1366: goto bad;
1367: }
1368: data_addr = hisctladdr;
1369: data_addr.su_port = htons(port[1]);
1370: } else
1.1 deraadt 1371: goto bad;
1372:
1.27 deraadt 1373: while (connect(data, (struct sockaddr *)&data_addr,
1.34 itojun 1374: data_addr.su_len) < 0) {
1.27 deraadt 1375: if (errno == EINTR)
1376: continue;
1.33 millert 1377: if (activefallback) {
1378: (void)close(data);
1379: data = -1;
1380: passivemode = 0;
1381: activefallback = 0;
1382: goto reinit;
1383: }
1.10 millert 1384: warn("connect");
1.1 deraadt 1385: goto bad;
1386: }
1.34 itojun 1387: #if defined(IPPROTO_IP) && defined(IP_TOS)
1388: if (data_addr.su_family == AF_INET) {
1389: on = IPTOS_THROUGHPUT;
1390: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1391: sizeof(int)) < 0)
1392: warn("setsockopt TOS (ignored)");
1393: }
1.1 deraadt 1394: #endif
1.10 millert 1395: return (0);
1.1 deraadt 1396: }
1397:
1398: noport:
1399: data_addr = myctladdr;
1400: if (sendport)
1.34 itojun 1401: data_addr.su_port = 0; /* let system pick one */
1.1 deraadt 1402: if (data != -1)
1.11 millert 1403: (void)close(data);
1.34 itojun 1404: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1405: if (data < 0) {
1406: warn("socket");
1407: if (tmpno)
1408: sendport = 1;
1409: return (1);
1410: }
1411: if (!sendport)
1.10 millert 1412: if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1.11 millert 1413: sizeof(on)) < 0) {
1.1 deraadt 1414: warn("setsockopt (reuse address)");
1415: goto bad;
1416: }
1.49 jakob 1417: switch (data_addr.su_family) {
1418: case AF_INET:
1419: on = IP_PORTRANGE_HIGH;
1420: if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE,
1421: (char *)&on, sizeof(on)) < 0)
1422: warn("setsockopt IP_PORTRANGE (ignored)");
1423: break;
1424: case AF_INET6:
1425: on = IPV6_PORTRANGE_HIGH;
1426: if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
1427: (char *)&on, sizeof(on)) < 0)
1428: warn("setsockopt IPV6_PORTRANGE (ignored)");
1429: break;
1430: }
1.34 itojun 1431: if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
1.1 deraadt 1432: warn("bind");
1433: goto bad;
1434: }
1435: if (options & SO_DEBUG &&
1.10 millert 1436: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1437: sizeof(on)) < 0)
1.1 deraadt 1438: warn("setsockopt (ignored)");
1.11 millert 1439: len = sizeof(data_addr);
1.1 deraadt 1440: if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1441: warn("getsockname");
1442: goto bad;
1443: }
1444: if (listen(data, 1) < 0)
1445: warn("listen");
1.34 itojun 1446:
1447: #define UC(b) (((int)b)&0xff)
1448:
1.1 deraadt 1449: if (sendport) {
1.47 itojun 1450: char hname[NI_MAXHOST], pbuf[NI_MAXSERV];
1.34 itojun 1451: int af;
1.47 itojun 1452: union sockunion tmp;
1.34 itojun 1453:
1.47 itojun 1454: tmp = data_addr;
1455: switch (tmp.su_family) {
1.34 itojun 1456: case AF_INET:
1.36 itojun 1457: if (!epsv4 || epsv4bad) {
1458: result = COMPLETE +1;
1459: break;
1460: }
1461: /*FALLTHROUGH*/
1.34 itojun 1462: case AF_INET6:
1.47 itojun 1463: if (tmp.su_family == AF_INET6)
1464: tmp.su_sin6.sin6_scope_id = 0;
1465: af = (tmp.su_family == AF_INET) ? 1 : 2;
1466: if (getnameinfo((struct sockaddr *)&tmp,
1467: tmp.su_len, hname, sizeof(hname),
1468: pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
1.34 itojun 1469: result = ERROR;
1470: } else {
1.47 itojun 1471: result = command("EPRT |%d|%s|%s|",
1472: af, hname, pbuf);
1.36 itojun 1473: if (result != COMPLETE) {
1474: epsv4bad = 1;
1475: if (debug) {
1476: fputs(
1477: "disabling epsv4 for this connection\n",
1478: ttyout);
1479: }
1480: }
1.34 itojun 1481: }
1482: break;
1483: default:
1484: result = COMPLETE + 1;
1485: break;
1486: }
1487: if (result == COMPLETE)
1488: goto skip_port;
1489:
1490: switch (data_addr.su_family) {
1491: case AF_INET:
1492: a = (char *)&data_addr.su_sin.sin_addr;
1493: p = (char *)&data_addr.su_port;
1494: result = command("PORT %d,%d,%d,%d,%d,%d",
1495: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1496: UC(p[0]), UC(p[1]));
1497: break;
1498: case AF_INET6:
1499: a = (char *)&data_addr.su_sin6.sin6_addr;
1500: p = (char *)&data_addr.su_port;
1501: result = command(
1502: "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1503: 6, 16,
1504: UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1505: UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1506: UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1507: UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1508: 2, UC(p[0]), UC(p[1]));
1509: break;
1510: default:
1511: result = COMPLETE + 1; /* xxx */
1512: }
1513: skip_port:
1514:
1.1 deraadt 1515: if (result == ERROR && sendport == -1) {
1516: sendport = 0;
1517: tmpno = 1;
1518: goto noport;
1519: }
1520: return (result != COMPLETE);
1521: }
1522: if (tmpno)
1523: sendport = 1;
1.34 itojun 1524: #if defined(IPPROTO_IP) && defined(IP_TOS)
1525: if (data_addr.su_family == AF_INET) {
1526: on = IPTOS_THROUGHPUT;
1527: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1528: sizeof(int)) < 0)
1529: warn("setsockopt TOS (ignored)");
1530: }
1.1 deraadt 1531: #endif
1532: return (0);
1533: bad:
1.11 millert 1534: (void)close(data), data = -1;
1.1 deraadt 1535: if (tmpno)
1536: sendport = 1;
1537: return (1);
1538: }
1539:
1540: FILE *
1541: dataconn(lmode)
1.10 millert 1542: const char *lmode;
1.1 deraadt 1543: {
1.34 itojun 1544: union sockunion from;
1545: int s, fromlen = myctladdr.su_len;
1.1 deraadt 1546:
1547: if (passivemode)
1548: return (fdopen(data, lmode));
1549:
1550: s = accept(data, (struct sockaddr *) &from, &fromlen);
1551: if (s < 0) {
1552: warn("accept");
1.11 millert 1553: (void)close(data), data = -1;
1.1 deraadt 1554: return (NULL);
1555: }
1.11 millert 1556: (void)close(data);
1.1 deraadt 1557: data = s;
1.34 itojun 1558: #if defined(IPPROTO_IP) && defined(IP_TOS)
1559: if (from.su_family == AF_INET) {
1560: int tos = IPTOS_THROUGHPUT;
1561: if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1562: sizeof(int)) < 0) {
1563: warn("setsockopt TOS (ignored)");
1564: }
1565: }
1.1 deraadt 1566: #endif
1567: return (fdopen(data, lmode));
1568: }
1569:
1570: void
1.10 millert 1571: psummary(notused)
1572: int notused;
1.1 deraadt 1573: {
1.26 deraadt 1574: int save_errno = errno;
1.10 millert 1575:
1576: if (bytes > 0)
1577: ptransfer(1);
1.26 deraadt 1578: errno = save_errno;
1.1 deraadt 1579: }
1580:
1581: void
1.12 millert 1582: psabort(notused)
1583: int notused;
1.1 deraadt 1584: {
1585:
1.10 millert 1586: alarmtimer(0);
1.1 deraadt 1587: abrtflag++;
1588: }
1589:
1590: void
1591: pswitch(flag)
1592: int flag;
1593: {
1594: sig_t oldintr;
1595: static struct comvars {
1596: int connect;
1597: char name[MAXHOSTNAMELEN];
1.34 itojun 1598: union sockunion mctl;
1599: union sockunion hctl;
1.1 deraadt 1600: FILE *in;
1601: FILE *out;
1602: int tpe;
1603: int curtpe;
1604: int cpnd;
1605: int sunqe;
1606: int runqe;
1607: int mcse;
1608: int ntflg;
1609: char nti[17];
1610: char nto[17];
1611: int mapflg;
1612: char mi[MAXPATHLEN];
1613: char mo[MAXPATHLEN];
1614: } proxstruct, tmpstruct;
1615: struct comvars *ip, *op;
1616:
1617: abrtflag = 0;
1618: oldintr = signal(SIGINT, psabort);
1619: if (flag) {
1620: if (proxy)
1621: return;
1622: ip = &tmpstruct;
1623: op = &proxstruct;
1624: proxy++;
1625: } else {
1626: if (!proxy)
1627: return;
1628: ip = &proxstruct;
1629: op = &tmpstruct;
1630: proxy = 0;
1631: }
1632: ip->connect = connected;
1633: connected = op->connect;
1634: if (hostname) {
1.41 lebel 1635: (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1.1 deraadt 1636: } else
1.11 millert 1637: ip->name[0] = '\0';
1.1 deraadt 1638: hostname = op->name;
1639: ip->hctl = hisctladdr;
1640: hisctladdr = op->hctl;
1641: ip->mctl = myctladdr;
1642: myctladdr = op->mctl;
1643: ip->in = cin;
1644: cin = op->in;
1645: ip->out = cout;
1646: cout = op->out;
1647: ip->tpe = type;
1648: type = op->tpe;
1649: ip->curtpe = curtype;
1650: curtype = op->curtpe;
1651: ip->cpnd = cpend;
1652: cpend = op->cpnd;
1653: ip->sunqe = sunique;
1654: sunique = op->sunqe;
1655: ip->runqe = runique;
1656: runique = op->runqe;
1657: ip->mcse = mcase;
1658: mcase = op->mcse;
1659: ip->ntflg = ntflag;
1660: ntflag = op->ntflg;
1.41 lebel 1661: (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1.52 deraadt 1662: (void)strlcpy(ntin, op->nti, sizeof ntin);
1.41 lebel 1663: (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1.52 deraadt 1664: (void)strlcpy(ntout, op->nto, sizeof ntout);
1.1 deraadt 1665: ip->mapflg = mapflag;
1666: mapflag = op->mapflg;
1.41 lebel 1667: (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1.52 deraadt 1668: (void)strlcpy(mapin, op->mi, sizeof mapin);
1.41 lebel 1669: (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1.52 deraadt 1670: (void)strlcpy(mapout, op->mo, sizeof mapout);
1.11 millert 1671: (void)signal(SIGINT, oldintr);
1.1 deraadt 1672: if (abrtflag) {
1673: abrtflag = 0;
1674: (*oldintr)(SIGINT);
1675: }
1676: }
1677:
1678: void
1.12 millert 1679: abortpt(notused)
1680: int notused;
1.1 deraadt 1681: {
1682:
1.10 millert 1683: alarmtimer(0);
1.18 deraadt 1684: putc('\n', ttyout);
1685: (void)fflush(ttyout);
1.1 deraadt 1686: ptabflg++;
1687: mflag = 0;
1688: abrtflag = 0;
1689: longjmp(ptabort, 1);
1690: }
1691:
1692: void
1693: proxtrans(cmd, local, remote)
1.10 millert 1694: const char *cmd, *local, *remote;
1.1 deraadt 1695: {
1.40 millert 1696: volatile sig_t oldintr;
1.20 millert 1697: int prox_type, nfnd;
1698: volatile int secndflag;
1.40 millert 1699: char * volatile cmd2;
1.29 art 1700: fd_set mask;
1.20 millert 1701:
1702: oldintr = NULL;
1703: secndflag = 0;
1.1 deraadt 1704: if (strcmp(cmd, "RETR"))
1705: cmd2 = "RETR";
1706: else
1707: cmd2 = runique ? "STOU" : "STOR";
1708: if ((prox_type = type) == 0) {
1709: if (unix_server && unix_proxy)
1710: prox_type = TYPE_I;
1711: else
1712: prox_type = TYPE_A;
1713: }
1714: if (curtype != prox_type)
1715: changetype(prox_type, 1);
1716: if (command("PASV") != COMPLETE) {
1.18 deraadt 1717: fputs("proxy server does not support third party transfers.\n",
1718: ttyout);
1.1 deraadt 1719: return;
1720: }
1721: pswitch(0);
1722: if (!connected) {
1.18 deraadt 1723: fputs("No primary connection.\n", ttyout);
1.1 deraadt 1724: pswitch(1);
1725: code = -1;
1726: return;
1727: }
1728: if (curtype != prox_type)
1729: changetype(prox_type, 1);
1730: if (command("PORT %s", pasv) != COMPLETE) {
1731: pswitch(1);
1732: return;
1733: }
1734: if (setjmp(ptabort))
1735: goto abort;
1736: oldintr = signal(SIGINT, abortpt);
1737: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 1738: (void)signal(SIGINT, oldintr);
1.1 deraadt 1739: pswitch(1);
1740: return;
1741: }
1742: sleep(2);
1743: pswitch(1);
1744: secndflag++;
1745: if (command("%s %s", cmd2, local) != PRELIM)
1746: goto abort;
1747: ptflag++;
1.11 millert 1748: (void)getreply(0);
1.1 deraadt 1749: pswitch(0);
1.11 millert 1750: (void)getreply(0);
1751: (void)signal(SIGINT, oldintr);
1.1 deraadt 1752: pswitch(1);
1753: ptflag = 0;
1.18 deraadt 1754: fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1.1 deraadt 1755: return;
1756: abort:
1.11 millert 1757: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1758: ptflag = 0;
1759: if (strcmp(cmd, "RETR") && !proxy)
1760: pswitch(1);
1761: else if (!strcmp(cmd, "RETR") && proxy)
1762: pswitch(0);
1763: if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1764: if (command("%s %s", cmd2, local) != PRELIM) {
1765: pswitch(0);
1766: if (cpend)
1.19 kstailey 1767: abort_remote(NULL);
1.1 deraadt 1768: }
1769: pswitch(1);
1770: if (ptabflg)
1771: code = -1;
1.11 millert 1772: (void)signal(SIGINT, oldintr);
1.1 deraadt 1773: return;
1774: }
1775: if (cpend)
1.19 kstailey 1776: abort_remote(NULL);
1.1 deraadt 1777: pswitch(!proxy);
1778: if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1779: if (command("%s %s", cmd2, local) != PRELIM) {
1780: pswitch(0);
1781: if (cpend)
1.19 kstailey 1782: abort_remote(NULL);
1.1 deraadt 1783: pswitch(1);
1784: if (ptabflg)
1785: code = -1;
1.11 millert 1786: (void)signal(SIGINT, oldintr);
1.1 deraadt 1787: return;
1788: }
1789: }
1790: if (cpend)
1.19 kstailey 1791: abort_remote(NULL);
1.1 deraadt 1792: pswitch(!proxy);
1793: if (cpend) {
1794: FD_ZERO(&mask);
1795: FD_SET(fileno(cin), &mask);
1796: if ((nfnd = empty(&mask, 10)) <= 0) {
1797: if (nfnd < 0) {
1798: warn("abort");
1799: }
1800: if (ptabflg)
1801: code = -1;
1802: lostpeer();
1803: }
1.11 millert 1804: (void)getreply(0);
1805: (void)getreply(0);
1.1 deraadt 1806: }
1807: if (proxy)
1808: pswitch(0);
1809: pswitch(1);
1810: if (ptabflg)
1811: code = -1;
1.11 millert 1812: (void)signal(SIGINT, oldintr);
1.1 deraadt 1813: }
1814:
1815: void
1816: reset(argc, argv)
1817: int argc;
1818: char *argv[];
1819: {
1.29 art 1820: fd_set mask;
1.1 deraadt 1821: int nfnd = 1;
1822:
1823: FD_ZERO(&mask);
1824: while (nfnd > 0) {
1825: FD_SET(fileno(cin), &mask);
1.10 millert 1826: if ((nfnd = empty(&mask, 0)) < 0) {
1.1 deraadt 1827: warn("reset");
1828: code = -1;
1829: lostpeer();
1830: }
1831: else if (nfnd) {
1.11 millert 1832: (void)getreply(0);
1.1 deraadt 1833: }
1834: }
1835: }
1836:
1837: char *
1838: gunique(local)
1.10 millert 1839: const char *local;
1.1 deraadt 1840: {
1841: static char new[MAXPATHLEN];
1842: char *cp = strrchr(local, '/');
1843: int d, count=0;
1844: char ext = '1';
1845:
1846: if (cp)
1847: *cp = '\0';
1.22 millert 1848: d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1.1 deraadt 1849: if (cp)
1850: *cp = '/';
1851: if (d < 0) {
1852: warn("local: %s", local);
1853: return ((char *) 0);
1854: }
1.52 deraadt 1855: (void)strlcpy(new, local, sizeof new);
1.1 deraadt 1856: cp = new + strlen(new);
1857: *cp++ = '.';
1858: while (!d) {
1859: if (++count == 100) {
1.18 deraadt 1860: fputs("runique: can't find unique file name.\n", ttyout);
1.1 deraadt 1861: return ((char *) 0);
1862: }
1863: *cp++ = ext;
1864: *cp = '\0';
1865: if (ext == '9')
1866: ext = '0';
1867: else
1868: ext++;
1.22 millert 1869: if ((d = access(new, F_OK)) < 0)
1.1 deraadt 1870: break;
1871: if (ext != '0')
1872: cp--;
1873: else if (*(cp - 2) == '.')
1874: *(cp - 1) = '1';
1875: else {
1876: *(cp - 2) = *(cp - 2) + 1;
1877: cp--;
1878: }
1879: }
1880: return (new);
1881: }
1882:
1883: void
1884: abort_remote(din)
1885: FILE *din;
1886: {
1887: char buf[BUFSIZ];
1888: int nfnd;
1.29 art 1889: fd_set mask;
1.13 millert 1890:
1891: if (cout == NULL) {
1892: warnx("Lost control connection for abort.");
1893: if (ptabflg)
1894: code = -1;
1895: lostpeer();
1896: return;
1897: }
1.1 deraadt 1898:
1899: /*
1900: * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1901: * after urgent byte rather than before as is protocol now
1902: */
1.46 deraadt 1903: snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC);
1.1 deraadt 1904: if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1905: warn("abort");
1.10 millert 1906: fprintf(cout, "%cABOR\r\n", DM);
1.11 millert 1907: (void)fflush(cout);
1.1 deraadt 1908: FD_ZERO(&mask);
1909: FD_SET(fileno(cin), &mask);
1.10 millert 1910: if (din) {
1.1 deraadt 1911: FD_SET(fileno(din), &mask);
1912: }
1913: if ((nfnd = empty(&mask, 10)) <= 0) {
1914: if (nfnd < 0) {
1915: warn("abort");
1916: }
1917: if (ptabflg)
1918: code = -1;
1919: lostpeer();
1920: }
1921: if (din && FD_ISSET(fileno(din), &mask)) {
1922: while (read(fileno(din), buf, BUFSIZ) > 0)
1923: /* LOOP */;
1924: }
1925: if (getreply(0) == ERROR && code == 552) {
1926: /* 552 needed for nic style abort */
1.11 millert 1927: (void)getreply(0);
1.1 deraadt 1928: }
1.11 millert 1929: (void)getreply(0);
1.1 deraadt 1930: }