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