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