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