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