|
|
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.