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