|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ftp.c 4.11 (Berkeley) 7/26/83";
3: #endif
4:
5: #include <sys/param.h>
6: #include <sys/stat.h>
7: #include <sys/ioctl.h>
8: #include <sys/socket.h>
9: #include <sys/time.h>
10:
11: #include <netinet/in.h>
12: #include <arpa/ftp.h>
13:
14: #include <stdio.h>
15: #include <signal.h>
16: #include <errno.h>
17: #include <netdb.h>
18:
19: #include "ftp_var.h"
20:
21: struct sockaddr_in hisctladdr;
22: struct sockaddr_in data_addr;
23: int data = -1;
24: int connected;
25: struct sockaddr_in myctladdr;
26:
27: FILE *cin, *cout;
28: FILE *dataconn();
29:
30: struct hostent *
31: hookup(host, port)
32: char *host;
33: int port;
34: {
35: register struct hostent *hp;
36: int s, len;
37:
38: bzero((char *)&hisctladdr, sizeof (hisctladdr));
39: hp = gethostbyname(host);
40: if (hp == NULL) {
41: static struct hostent def;
42: static struct in_addr defaddr;
43: static char namebuf[128];
44: int inet_addr();
45:
46: defaddr.s_addr = inet_addr(host);
47: if (defaddr.s_addr == -1) {
48: fprintf(stderr, "%s: Unknown host.\n", host);
49: return (0);
50: }
51: strcpy(namebuf, host);
52: def.h_name = namebuf;
53: hostname = namebuf;
54: def.h_addr = (char *)&defaddr;
55: def.h_length = sizeof (struct in_addr);
56: def.h_addrtype = AF_INET;
57: def.h_aliases = 0;
58: hp = &def;
59: }
60: hostname = hp->h_name;
61: hisctladdr.sin_family = hp->h_addrtype;
62: s = socket(hp->h_addrtype, SOCK_STREAM, 0, 0);
63: if (s < 0) {
64: perror("ftp: socket");
65: return (0);
66: }
67: if (bind(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
68: perror("ftp: bind");
69: goto bad;
70: }
71: bcopy(hp->h_addr, (char *)&hisctladdr.sin_addr, hp->h_length);
72: hisctladdr.sin_port = port;
73: if (connect(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
74: perror("ftp: connect");
75: goto bad;
76: }
77: len = sizeof (myctladdr);
78: if (getsockname(s, (char *)&myctladdr, &len) < 0) {
79: perror("ftp: getsockname");
80: goto bad;
81: }
82: cin = fdopen(s, "r");
83: cout = fdopen(s, "w");
84: if (cin == NULL || cout == NULL) {
85: fprintf(stderr, "ftp: fdopen failed.\n");
86: if (cin)
87: fclose(cin);
88: if (cout)
89: fclose(cout);
90: goto bad;
91: }
92: if (verbose)
93: printf("Connected to %s.\n", hp->h_name);
94: (void) getreply(0); /* read startup message from server */
95: return (hp);
96: bad:
97: close(s);
98: return ((struct hostent *)0);
99: }
100:
101: login(hp)
102: struct hostent *hp;
103: {
104: char acct[80];
105: char *user, *pass;
106: int n;
107:
108: user = pass = 0;
109: ruserpass(hp->h_name, &user, &pass);
110: n = command("USER %s", user);
111: if (n == CONTINUE)
112: n = command("PASS %s", pass);
113: if (n == CONTINUE) {
114: printf("Account: "); (void) fflush(stdout);
115: (void) fgets(acct, sizeof(acct) - 1, stdin);
116: acct[strlen(acct) - 1] = '\0';
117: n = command("ACCT %s", acct);
118: }
119: if (n != COMPLETE) {
120: fprintf(stderr, "Login failed.\n");
121: return (0);
122: }
123: return (1);
124: }
125:
126: /*VARARGS 1*/
127: command(fmt, args)
128: char *fmt;
129: {
130:
131: if (debug) {
132: printf("---> ");
133: _doprnt(fmt, &args, stdout);
134: printf("\n");
135: (void) fflush(stdout);
136: }
137: if (cout == NULL) {
138: perror ("No control connection for command");
139: return (0);
140: }
141: _doprnt(fmt, &args, cout);
142: fprintf(cout, "\r\n");
143: (void) fflush(cout);
144: return (getreply(!strcmp(fmt, "QUIT")));
145: }
146:
147: #include <ctype.h>
148:
149: getreply(expecteof)
150: int expecteof;
151: {
152: register int c, n;
153: register int code, dig;
154: int originalcode = 0, continuation = 0;
155:
156: for (;;) {
157: dig = n = code = 0;
158: while ((c = getc(cin)) != '\n') {
159: dig++;
160: if (c == EOF) {
161: if (expecteof)
162: return (0);
163: lostpeer();
164: exit(1);
165: }
166: if (verbose && c != '\r' ||
167: (n == '5' && dig > 4))
168: putchar(c);
169: if (dig < 4 && isdigit(c))
170: code = code * 10 + (c - '0');
171: if (dig == 4 && c == '-')
172: continuation++;
173: if (n == 0)
174: n = c;
175: }
176: if (verbose || n == '5') {
177: putchar(c);
178: (void) fflush (stdout);
179: }
180: if (continuation && code != originalcode) {
181: if (originalcode == 0)
182: originalcode = code;
183: continue;
184: }
185: if (expecteof || empty(cin))
186: return (n - '0');
187: }
188: }
189:
190: empty(f)
191: FILE *f;
192: {
193: long mask;
194: struct timeval t;
195:
196: if (f->_cnt > 0)
197: return (0);
198: mask = (1 << fileno(f));
199: t.tv_sec = t.tv_usec = 0;
200: (void) select(20, &mask, 0, 0, &t);
201: return (mask == 0);
202: }
203:
204: jmp_buf sendabort;
205:
206: abortsend()
207: {
208:
209: longjmp(sendabort, 1);
210: }
211:
212: sendrequest(cmd, local, remote)
213: char *cmd, *local, *remote;
214: {
215: FILE *fin, *dout, *popen();
216: int (*closefunc)(), pclose(), fclose(), (*oldintr)();
217: char buf[BUFSIZ];
218: long bytes = 0, hashbytes = sizeof (buf);
219: register int c, d;
220: struct stat st;
221: struct timeval start, stop;
222:
223: closefunc = NULL;
224: if (setjmp(sendabort))
225: goto bad;
226: oldintr = signal(SIGINT, abortsend);
227: if (strcmp(local, "-") == 0)
228: fin = stdin;
229: else if (*local == '|') {
230: fin = popen(local + 1, "r");
231: if (fin == NULL) {
232: perror(local + 1);
233: goto bad;
234: }
235: closefunc = pclose;
236: } else {
237: fin = fopen(local, "r");
238: if (fin == NULL) {
239: perror(local);
240: goto bad;
241: }
242: closefunc = fclose;
243: if (fstat(fileno(fin), &st) < 0 ||
244: (st.st_mode&S_IFMT) != S_IFREG) {
245: fprintf(stderr, "%s: not a plain file.", local);
246: goto bad;
247: }
248: }
249: if (initconn())
250: goto bad;
251: if (remote) {
252: if (command("%s %s", cmd, remote) != PRELIM)
253: goto bad;
254: } else
255: if (command("%s", cmd) != PRELIM)
256: goto bad;
257: dout = dataconn("w");
258: if (dout == NULL)
259: goto bad;
260: gettimeofday(&start, (struct timezone *)0);
261: switch (type) {
262:
263: case TYPE_I:
264: case TYPE_L:
265: errno = d = 0;
266: while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
267: if ((d = write(fileno (dout), buf, c)) < 0)
268: break;
269: bytes += c;
270: if (hash) {
271: putchar('#');
272: fflush(stdout);
273: }
274: }
275: if (hash && bytes > 0) {
276: putchar('\n');
277: fflush(stdout);
278: }
279: if (c < 0)
280: perror(local);
281: if (d < 0)
282: perror("netout");
283: break;
284:
285: case TYPE_A:
286: while ((c = getc(fin)) != EOF) {
287: if (c == '\n') {
288: while (hash && (bytes >= hashbytes)) {
289: putchar('#');
290: fflush(stdout);
291: hashbytes += sizeof (buf);
292: }
293: if (ferror(dout))
294: break;
295: putc('\r', dout);
296: bytes++;
297: }
298: putc(c, dout);
299: bytes++;
300: if (c == '\r') {
301: putc('\0', dout);
302: bytes++;
303: }
304: }
305: if (hash) {
306: if (bytes < hashbytes)
307: putchar('#');
308: putchar('\n');
309: fflush(stdout);
310: }
311: if (ferror(fin))
312: perror(local);
313: if (ferror(dout))
314: perror("netout");
315: break;
316: }
317: gettimeofday(&stop, (struct timezone *)0);
318: if (closefunc != NULL)
319: (*closefunc)(fin);
320: (void) fclose(dout);
321: (void) getreply(0);
322: done:
323: signal(SIGINT, oldintr);
324: if (bytes > 0 && verbose)
325: ptransfer("sent", bytes, &start, &stop);
326: return;
327: bad:
328: if (data >= 0)
329: (void) close(data), data = -1;
330: if (closefunc != NULL && fin != NULL)
331: (*closefunc)(fin);
332: goto done;
333: }
334:
335: jmp_buf recvabort;
336:
337: abortrecv()
338: {
339:
340: longjmp(recvabort, 1);
341: }
342:
343: recvrequest(cmd, local, remote, mode)
344: char *cmd, *local, *remote, *mode;
345: {
346: FILE *fout, *din, *popen();
347: int (*closefunc)(), pclose(), fclose(), (*oldintr)();
348: char buf[BUFSIZ];
349: long bytes = 0, hashbytes = sizeof (buf);
350: register int c, d;
351: struct timeval start, stop;
352:
353: closefunc = NULL;
354: if (setjmp(recvabort))
355: goto bad;
356: oldintr = signal(SIGINT, abortrecv);
357: if (strcmp(local, "-") && *local != '|')
358: if (access(local, 2) < 0) {
359: char *dir = rindex(local, '/');
360:
361: if (dir != NULL)
362: *dir = 0;
363: if (access(dir ? dir : ".", 2) < 0) {
364: perror(local);
365: goto bad;
366: }
367: if (dir != NULL)
368: *dir = '/';
369: }
370: if (initconn())
371: goto bad;
372: if (remote) {
373: if (command("%s %s", cmd, remote) != PRELIM)
374: goto bad;
375: } else
376: if (command("%s", cmd) != PRELIM)
377: goto bad;
378: if (strcmp(local, "-") == 0)
379: fout = stdout;
380: else if (*local == '|') {
381: fout = popen(local + 1, "w");
382: closefunc = pclose;
383: } else {
384: fout = fopen(local, mode);
385: closefunc = fclose;
386: }
387: if (fout == NULL) {
388: perror(local + 1);
389: goto bad;
390: }
391: din = dataconn("r");
392: if (din == NULL)
393: goto bad;
394: gettimeofday(&start, (struct timezone *)0);
395: switch (type) {
396:
397: case TYPE_I:
398: case TYPE_L:
399: errno = d = 0;
400: while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
401: if ((d = write(fileno(fout), buf, c)) < 0)
402: break;
403: bytes += c;
404: if (hash) {
405: putchar('#');
406: fflush(stdout);
407: }
408: }
409: if (hash && bytes > 0) {
410: putchar('\n');
411: fflush(stdout);
412: }
413: if (c < 0)
414: perror("netin");
415: if (d < 0)
416: perror(local);
417: break;
418:
419: case TYPE_A:
420: while ((c = getc(din)) != EOF) {
421: if (c == '\r') {
422: while (hash && (bytes >= hashbytes)) {
423: putchar('#');
424: fflush(stdout);
425: hashbytes += sizeof (buf);
426: }
427: bytes++;
428: if ((c = getc(din)) != '\n') {
429: if (ferror (fout))
430: break;
431: putc ('\r', fout);
432: }
433: if (c == '\0') {
434: bytes++;
435: continue;
436: }
437: }
438: putc (c, fout);
439: bytes++;
440: }
441: if (hash) {
442: if (bytes < hashbytes)
443: putchar('#');
444: putchar('\n');
445: fflush(stdout);
446: }
447: if (ferror (din))
448: perror ("netin");
449: if (ferror (fout))
450: perror (local);
451: break;
452: }
453: gettimeofday(&stop, (struct timezone *)0);
454: (void) fclose(din);
455: if (closefunc != NULL)
456: (*closefunc)(fout);
457: (void) getreply(0);
458: done:
459: signal(SIGINT, oldintr);
460: if (bytes > 0 && verbose)
461: ptransfer("received", bytes, &start, &stop);
462: return;
463: bad:
464: if (data >= 0)
465: (void) close(data), data = -1;
466: if (closefunc != NULL && fout != NULL)
467: (*closefunc)(fout);
468: goto done;
469: }
470:
471: /*
472: * Need to start a listen on the data channel
473: * before we send the command, otherwise the
474: * server's connect may fail.
475: */
476: static int sendport = -1;
477:
478: initconn()
479: {
480: register char *p, *a;
481: int result, len;
482:
483: noport:
484: data_addr = myctladdr;
485: if (sendport)
486: data_addr.sin_port = 0; /* let system pick one */
487: if (data != -1)
488: (void) close (data);
489: data = socket(AF_INET, SOCK_STREAM, 0, 0);
490: if (data < 0) {
491: perror("ftp: socket");
492: return (1);
493: }
494: if (!sendport)
495: if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) {
496: perror("ftp: setsockopt (resuse address)");
497: goto bad;
498: }
499: if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) {
500: perror("ftp: bind");
501: goto bad;
502: }
503: if (options & SO_DEBUG &&
504: setsockopt(data, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
505: perror("ftp: setsockopt (ignored)");
506: len = sizeof (data_addr);
507: if (getsockname(data, (char *)&data_addr, &len) < 0) {
508: perror("ftp: getsockname");
509: goto bad;
510: }
511: if (listen(data, 1) < 0) {
512: perror("ftp: listen");
513: goto bad;
514: }
515: if (sendport) {
516: a = (char *)&data_addr.sin_addr;
517: p = (char *)&data_addr.sin_port;
518: #define UC(b) (((int)b)&0xff)
519: result =
520: command("PORT %d,%d,%d,%d,%d,%d",
521: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
522: UC(p[0]), UC(p[1]));
523: if (result == ERROR && sendport == -1) {
524: sendport = 0;
525: goto noport;
526: }
527: return (result != COMPLETE);
528: }
529: return (0);
530: bad:
531: (void) close(data), data = -1;
532: return (1);
533: }
534:
535: FILE *
536: dataconn(mode)
537: char *mode;
538: {
539: struct sockaddr_in from;
540: int s, fromlen = sizeof (from);
541:
542: s = accept(data, &from, &fromlen, 0);
543: if (s < 0) {
544: perror("ftp: accept");
545: (void) close(data), data = -1;
546: return (NULL);
547: }
548: (void) close(data);
549: data = s;
550: return (fdopen(data, mode));
551: }
552:
553: ptransfer(direction, bytes, t0, t1)
554: char *direction;
555: long bytes;
556: struct timeval *t0, *t1;
557: {
558: struct timeval td;
559: long ms;
560: float bs;
561:
562: tvsub(&td, t1, t0);
563: ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
564: #define nz(x) ((x) == 0 ? 1 : (x))
565: bs = ((bytes * NBBY * 1000) / (float) nz(ms)) / NBBY;
566: printf("%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
567: bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.);
568: }
569:
570: tvadd(tsum, t0)
571: struct timeval *tsum, *t0;
572: {
573:
574: tsum->tv_sec += t0->tv_sec;
575: tsum->tv_usec += t0->tv_usec;
576: if (tsum->tv_usec > 1000000)
577: tsum->tv_sec++, tsum->tv_usec -= 1000000;
578: }
579:
580: tvsub(tdiff, t1, t0)
581: struct timeval *tdiff, *t1, *t0;
582: {
583:
584: tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
585: tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
586: if (tdiff->tv_usec < 0)
587: tdiff->tv_sec--, tdiff->tv_usec += 1000000;
588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.