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