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