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