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