|
|
1.1 root 1: #include <sys/param.h>
2: #include <sys/types.h>
3: #include <sys/stat.h>
4: #include <sys/ioctl.h>
5: #include <stdio.h>
6: #include <signal.h>
7: #include <sys/timeb.h>
8: #include <errno.h>
9: #include <sys/inet/tcp_user.h>
10: #include <libc.h>
11: #include "ftp.h"
12: #include "ftp_var.h"
13:
14: in_addr myaddr;
15: tcp_port myctlport;
16: in_addr hisaddr;
17: tcp_port dataport;
18: int data = -1;
19: int connected;
20:
21: FILE *cin, *cout;
22: FILE *dataconn();
23:
24: char *
25: hookup(host, port)
26: char *host;
27: int port;
28: {
29: int s;
30: struct tcpuser tu;
31: extern in_addr in_address();
32: extern char *in_host();
33:
34: hisaddr = in_address(host);
35: if (hisaddr == 0) {
36: perror("ftp: host unknown");
37: return (0);
38: }
39: hostname = in_host(hisaddr);
40: if ((s = tcp_sock()) < 0) {
41: perror("ftp: socket");
42: return (0);
43: }
44: tu.laddr = 0;
45: tu.lport = 0;
46: tu.faddr = hisaddr;
47: tu.fport = port;
48: tu.param = 0;
49: if (tcp_connect(s, &tu) < 0) {
50: perror("ftp: tcp_connect");
51: goto bad;
52: }
53: myaddr = tu.laddr;
54: myctlport = tu.lport;
55: cin = fdopen(s, "r");
56: cout = fdopen(s, "w");
57: if (cin == NULL || cout == NULL) {
58: fprintf(stderr, "ftp: fdopen failed.\n");
59: if (cin)
60: fclose(cin);
61: if (cout)
62: fclose(cout);
63: goto bad;
64: }
65: if (verbose)
66: printf("Connected to %s.\n", hostname);
67: (void) getreply(0); /* read startup message from server */
68: return (hostname);
69: bad:
70: close(s);
71: return ((char *)0);
72: }
73:
74: login(hp)
75: char *hp;
76: {
77: char acct[80];
78: char user[80], passwd[80];
79: int n;
80: struct sgttyb sbuf;
81: int oldflags;
82:
83: getresponse("login: ", user, sizeof(user));
84: ioctl(fileno(stdin), TIOCGETP, &sbuf);
85: oldflags = sbuf.sg_flags;
86: sbuf.sg_flags = oldflags & ~ECHO;
87: ioctl(fileno(stdin), TIOCSETP, &sbuf);
88: getresponse("password: ", passwd, sizeof(passwd));
89: sbuf.sg_flags = oldflags;
90: ioctl(fileno(stdin), TIOCSETP, &sbuf);
91: printf("\n"); (void) fflush(stdout);
92: n = command("USER %s", user);
93: if (n == CONTINUE)
94: n = command("PASS %s", passwd);
95: if (n == CONTINUE) {
96: getresponse("ACCOUNT: ", acct, sizeof(acct));
97: n = command("ACCT %s", acct);
98: }
99: if (n != COMPLETE) {
100: fprintf(stderr, "Login failed.\n");
101: return (0);
102: }
103: return (1);
104: }
105:
106: getresponse(prompt, cp, len)
107: char *prompt;
108: char *cp;
109: int len;
110: {
111: int c;
112: char *p = cp;
113:
114: printf(prompt); (void) fflush(stdout);
115: while(c = getchar())
116: if (c != ' ' && c != '\t')
117: break;
118: while(c != '\n' && c != EOF) {
119: if ((cp + len - 1) > p)
120: *p++ = c;
121: c = getchar();
122: }
123: *p = '\0';
124: }
125:
126:
127:
128: /*VARARGS 1*/
129: command(fmt, args)
130: char *fmt;
131: {
132:
133: if (debug) {
134: printf("---> ");
135: _doprnt(fmt, &args, stdout);
136: printf("\n");
137: (void) fflush(stdout);
138: }
139: if (cout == NULL) {
140: perror ("No control connection for command");
141: return (0);
142: }
143: _doprnt(fmt, &args, cout);
144: fprintf(cout, "\r\n");
145: (void) fflush(cout);
146: return (getreply(!strcmp(fmt, "QUIT")));
147: }
148:
149: #include <ctype.h>
150:
151: getreply(expecteof)
152: int expecteof;
153: {
154: register int c, n;
155: register int code, dig;
156: int originalcode = 0, continuation = 0;
157:
158: for (;;) {
159: dig = n = code = 0;
160: while ((c = getc(cin)) != '\n') {
161: dig++;
162: if (c == EOF) {
163: if (expecteof)
164: return (0);
165: lostpeer();
166: exit(1);
167: }
168: if (verbose && c != '\r' ||
169: (n == '5' && dig > 4))
170: putchar(c);
171: if (dig < 4 && isdigit(c))
172: code = code * 10 + (c - '0');
173: if (dig == 4 && c == '-')
174: continuation++;
175: if (n == 0)
176: n = c;
177: }
178: if (verbose || n == '5')
179: putchar(c);
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: int mask;
194:
195: if (f->_cnt > 0)
196: return (0);
197: mask = (1 << fileno(f));
198: (void) select(20, &mask, 0, 0);
199: return (mask == 0);
200: }
201:
202: jmp_buf sendabort;
203:
204: abortsend()
205: {
206:
207: longjmp(sendabort, 1);
208: }
209:
210: sendrequest(cmd, local, remote)
211: char *cmd, *local, *remote;
212: {
213: FILE *fin, *dout, *popen();
214: int (*closefunc)(), pclose(), fclose(), (*oldintr)();
215: char buf[BUFSIZ];
216: register int bytes = 0, c;
217: struct stat st;
218: struct timeb start, stop;
219: extern int errno;
220:
221: closefunc = NULL;
222: if (setjmp(sendabort))
223: goto bad;
224: oldintr = signal(SIGINT, abortsend);
225: if (strcmp(local, "-") == 0)
226: fin = stdin;
227: else if (*local == '|') {
228: fin = popen(local + 1, "r");
229: if (fin == NULL) {
230: perror(local + 1);
231: goto bad;
232: }
233: closefunc = pclose;
234: } else {
235: fin = fopen(local, "r");
236: if (fin == NULL) {
237: perror(local);
238: goto bad;
239: }
240: closefunc = fclose;
241: if (fstat(fileno(fin), &st) < 0 ||
242: (st.st_mode&S_IFMT) != S_IFREG) {
243: fprintf(stderr, "%s: not a plain file.", local);
244: goto bad;
245: }
246: }
247: if (initconn())
248: goto bad;
249: if (remote) {
250: if (command("%s %s", cmd, remote) != PRELIM)
251: goto bad;
252: } else
253: if (command("%s", cmd) != PRELIM)
254: goto bad;
255: dout = dataconn("w");
256: if (dout == NULL)
257: goto bad;
258: ftime(&start);
259: switch (type) {
260:
261: case TYPE_I:
262: case TYPE_L:
263: errno = 0;
264: while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
265: if (write(fileno (dout), buf, c) < 0)
266: break;
267: bytes += c;
268: }
269: if (c < 0)
270: perror(local);
271: else if (errno)
272: perror("netout");
273: break;
274:
275: case TYPE_A:
276: while ((c = getc(fin)) != EOF) {
277: if (c == '\n') {
278: if (ferror(dout))
279: break;
280: putc('\r', dout);
281: bytes++;
282: }
283: putc(c, dout);
284: bytes++;
285: if (c == '\r') {
286: putc('\0', dout);
287: bytes++;
288: }
289: }
290: if (ferror(fin))
291: perror(local);
292: else if (ferror(dout))
293: perror("netout");
294: break;
295: }
296: ftime(&stop);
297: if (closefunc != NULL)
298: (*closefunc)(fin);
299: (void) fclose(dout);
300: (void) getreply(0);
301: done:
302: signal(SIGINT, oldintr);
303: if (bytes > 0 && verbose)
304: ptransfer("sent", bytes, &start, &stop);
305: return;
306: bad:
307: if (data >= 0)
308: (void) close(data), data = -1;
309: if (closefunc != NULL && fin != NULL)
310: (*closefunc)(fin);
311: goto done;
312: }
313:
314: jmp_buf recvabort;
315:
316: abortrecv()
317: {
318:
319: longjmp(recvabort, 1);
320: }
321:
322: recvrequest(cmd, local, remote)
323: char *cmd, *local, *remote;
324: {
325: FILE *fout, *din, *popen();
326: char buf[BUFSIZ];
327: int (*closefunc)(), pclose(), fclose(), (*oldintr)(), c;
328: register int bytes = 0;
329: struct timeb start, stop;
330: extern int errno;
331:
332: closefunc = NULL;
333: if (setjmp(recvabort))
334: goto bad;
335: oldintr = signal(SIGINT, abortrecv);
336: if (strcmp(local, "-") && *local != '|')
337: if (access(local, 2) < 0) {
338: char *dir = strrchr(local, '/');
339:
340: if (dir != NULL)
341: *dir = 0;
342: if (access(dir ? dir : ".", 2) < 0) {
343: perror(local);
344: goto bad;
345: }
346: if (dir != NULL)
347: *dir = '/';
348: }
349: if (initconn())
350: goto bad;
351: if (remote) {
352: if (command("%s %s", cmd, remote) != PRELIM)
353: goto bad;
354: } else
355: if (command("%s", cmd) != PRELIM)
356: goto bad;
357: if (strcmp(local, "-") == 0)
358: fout = stdout;
359: else if (*local == '|') {
360: fout = popen(local + 1, "w");
361: closefunc = pclose;
362: } else {
363: fout = fopen(local, "w");
364: closefunc = fclose;
365: }
366: if (fout == NULL) {
367: perror(local + 1);
368: goto bad;
369: }
370: din = dataconn("r");
371: if (din == NULL)
372: goto bad;
373: ftime(&start);
374: switch (type) {
375:
376: case TYPE_I:
377: case TYPE_L:
378: errno = 0;
379: while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
380: if (write(fileno(fout), buf, c) < 0)
381: break;
382: bytes += c;
383: }
384: if (c < 0)
385: perror("netin");
386: if (errno)
387: perror(local);
388: break;
389:
390: case TYPE_A:
391: while ((c = getc(din)) != EOF) {
392: if (c == '\r') {
393: bytes++;
394: if ((c = getc(din)) != '\n') {
395: if (ferror (fout))
396: break;
397: putc ('\r', fout);
398: }
399: if (c == '\0') {
400: bytes++;
401: continue;
402: }
403: }
404: putc (c, fout);
405: bytes++;
406: }
407: if (ferror (din))
408: perror ("netin");
409: if (ferror (fout))
410: perror (local);
411: break;
412: }
413: ftime(&stop);
414: (void) fclose(din);
415: if (closefunc != NULL)
416: (*closefunc)(fout);
417: (void) getreply(0);
418: done:
419: signal(SIGINT, oldintr);
420: if (bytes > 0 && verbose)
421: ptransfer("received", bytes, &start, &stop);
422: return;
423: bad:
424: if (data >= 0)
425: (void) close(data), data = -1;
426: if (closefunc != NULL && fout != NULL)
427: (*closefunc)(fout);
428: goto done;
429: }
430:
431: /*
432: * Need to start a listen on the data channel
433: * before we send the command, otherwise the
434: * server's connect may fail.
435: */
436: initconn()
437: {
438: int result;
439: char *a, *p;
440: in_addr hostorderaddr;
441: tcp_port hostorderport;
442: struct tcpuser tu;
443:
444: data = tcp_sock();
445: if (data < 0) {
446: perror("ftp: tcp_sock");
447: return (1);
448: }
449: tu.lport = tu.fport = 0;
450: tu.laddr = tu.faddr = 0;
451: tu.param = 0;
452: if (tcp_listen(data, &tu) < 0) {
453: perror("ftp: tcp_listen");
454: goto bad;
455: }
456: dataport = tu.lport;
457: hostorderport = htons(dataport);
458: hostorderaddr = htonl(myaddr);
459: p = (char *)&hostorderport;
460: a = (char *)&hostorderaddr;
461: #define UC(b) (((int)b)&0xff)
462: result =
463: command("PORT %d,%d,%d,%d,%d,%d",
464: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
465: UC(p[0]), UC(p[1]));
466: return (result != COMPLETE);
467: bad:
468: (void) close(data), data = -1;
469: return (1);
470: }
471:
472: FILE *
473: dataconn(mode)
474: char *mode;
475: {
476: in_addr from_addr;
477: tcp_port from_port;
478: struct tcpuser tu;
479: int s;
480:
481: tu.lport = tu.fport = 0;
482: tu.laddr = tu.faddr = 0;
483: tu.param = 0;
484: s = tcp_accept(data, &tu);
485: if (s < 0) {
486: perror("ftp: accept");
487: (void) close(data), data = -1;
488: return (NULL);
489: }
490: (void) close(data);
491: data = s;
492: return (fdopen(data, mode));
493: }
494:
495: ptransfer(direction, bytes, t0, t1)
496: char *direction;
497: int bytes;
498: struct timeb *t0, *t1;
499: {
500: struct timeb td;
501: double ms, bs;
502:
503: tvsub(&td, t1, t0);
504: ms = (td.time * 1000) + td.millitm;
505: ms += 0.05;
506: bs = bytes * 1000;
507: bs = bs/(ms*1024.0);
508: printf("%d bytes %s in %.3f seconds (%.2f Kbytes/s)\n",
509: bytes, direction, ms/1000.0, bs);
510: }
511:
512: tvadd(tsum, t0)
513: struct timeb *tsum, *t0;
514: {
515:
516: tsum->time += t0->time;
517: tsum->millitm += t0->millitm;
518: if (tsum->time > 1000)
519: tsum->time++, tsum->millitm -= 1000;
520: }
521:
522: tvsub(tdiff, t1, t0)
523: struct timeb *tdiff, *t1, *t0;
524: {
525:
526: tdiff->time = t1->time - t0->time;
527: tdiff->millitm = t1->millitm - t0->millitm;
528: if (tdiff->millitm < 0)
529: tdiff->time--, tdiff->millitm += 1000;
530: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.