1: /* 2: * Copyright (c) 1985 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)ftp.c 5.14 (Berkeley) 5/22/86"; 9: #endif not lint 10: 11: #include "ftp_var.h" 12: 13: #include <sys/stat.h> 14: #include <sys/ioctl.h> 15: #include <sys/socket.h> 16: #include <sys/time.h> 17: #include <sys/param.h> 18: 19: #include <netinet/in.h> 20: #include <arpa/ftp.h> 21: #include <arpa/telnet.h> 22: 23: #include <stdio.h> 24: #include <signal.h> 25: #include <errno.h> 26: #include <netdb.h> 27: #include <fcntl.h> 28: #include <pwd.h> 29: 30: struct sockaddr_in hisctladdr; 31: struct sockaddr_in data_addr; 32: int data = -1; 33: int abrtflag = 0; 34: int ptflag = 0; 35: int connected; 36: struct sockaddr_in myctladdr; 37: uid_t getuid(); 38: 39: FILE *cin, *cout; 40: FILE *dataconn(); 41: 42: char * 43: hookup(host, port) 44: char *host; 45: int port; 46: { 47: register struct hostent *hp = 0; 48: int s,len; 49: static char hostnamebuf[80]; 50: 51: bzero((char *)&hisctladdr, sizeof (hisctladdr)); 52: hisctladdr.sin_addr.s_addr = inet_addr(host); 53: if (hisctladdr.sin_addr.s_addr != -1) { 54: hisctladdr.sin_family = AF_INET; 55: (void) strcpy(hostnamebuf, host); 56: } 57: else { 58: hp = gethostbyname(host); 59: if (hp == NULL) { 60: printf("%s: unknown host\n", host); 61: code = -1; 62: return((char *) 0); 63: } 64: hisctladdr.sin_family = hp->h_addrtype; 65: bcopy(hp->h_addr_list[0], 66: (caddr_t)&hisctladdr.sin_addr, hp->h_length); 67: (void) strcpy(hostnamebuf, hp->h_name); 68: } 69: hostname = hostnamebuf; 70: s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 71: if (s < 0) { 72: perror("ftp: socket"); 73: code = -1; 74: return (0); 75: } 76: hisctladdr.sin_port = port; 77: while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 78: if (hp && hp->h_addr_list[1]) { 79: int oerrno = errno; 80: 81: fprintf(stderr, "ftp: connect to address %s: ", 82: inet_ntoa(hisctladdr.sin_addr)); 83: errno = oerrno; 84: perror((char *) 0); 85: hp->h_addr_list++; 86: bcopy(hp->h_addr_list[0], 87: (caddr_t)&hisctladdr.sin_addr, hp->h_length); 88: fprintf(stdout, "Trying %s...\n", 89: inet_ntoa(hisctladdr.sin_addr)); 90: (void) close(s); 91: s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 92: if (s < 0) { 93: perror("ftp: socket"); 94: code = -1; 95: return (0); 96: } 97: continue; 98: } 99: perror("ftp: connect"); 100: code = -1; 101: goto bad; 102: } 103: len = sizeof (myctladdr); 104: if (getsockname(s, (char *)&myctladdr, &len) < 0) { 105: perror("ftp: getsockname"); 106: code = -1; 107: goto bad; 108: } 109: cin = fdopen(s, "r"); 110: cout = fdopen(s, "w"); 111: if (cin == NULL || cout == NULL) { 112: fprintf(stderr, "ftp: fdopen failed.\n"); 113: if (cin) 114: (void) fclose(cin); 115: if (cout) 116: (void) fclose(cout); 117: code = -1; 118: goto bad; 119: } 120: if (verbose) 121: printf("Connected to %s.\n", hostname); 122: if (getreply(0) > 2) { /* read startup message from server */ 123: if (cin) 124: (void) fclose(cin); 125: if (cout) 126: (void) fclose(cout); 127: code = -1; 128: goto bad; 129: } 130: #ifdef SO_OOBINLINE 131: { 132: int on = 1; 133: 134: if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 135: < 0 && debug) { 136: perror("ftp: setsockopt"); 137: } 138: } 139: #endif SO_OOBINLINE 140: 141: return (hostname); 142: bad: 143: (void) close(s); 144: return ((char *)0); 145: } 146: 147: login(host) 148: char *host; 149: { 150: char tmp[80]; 151: char *user, *pass, *acct, *getlogin(), *mygetpass(); 152: int n, aflag = 0; 153: 154: user = pass = acct = 0; 155: if (ruserpass(host, &user, &pass, &acct) < 0) { 156: disconnect(); 157: code = -1; 158: return(0); 159: } 160: if (user == NULL) { 161: char *myname = getlogin(); 162: 163: if (myname == NULL) { 164: struct passwd *pp = getpwuid(getuid()); 165: 166: if (pp != NULL) 167: myname = pp->pw_name; 168: } 169: printf("Name (%s:%s): ", host, myname); 170: (void) fgets(tmp, sizeof(tmp) - 1, stdin); 171: tmp[strlen(tmp) - 1] = '\0'; 172: if (*tmp == '\0') 173: user = myname; 174: else 175: user = tmp; 176: } 177: n = command("USER %s", user); 178: if (n == CONTINUE) { 179: if (pass == NULL) 180: pass = mygetpass("Password:"); 181: n = command("PASS %s", pass); 182: } 183: if (n == CONTINUE) { 184: aflag++; 185: acct = mygetpass("Account:"); 186: n = command("ACCT %s", acct); 187: } 188: if (n != COMPLETE) { 189: fprintf(stderr, "Login failed.\n"); 190: return (0); 191: } 192: if (!aflag && acct != NULL) 193: (void) command("ACCT %s", acct); 194: if (proxy) 195: return(1); 196: for (n = 0; n < macnum; ++n) { 197: if (!strcmp("init", macros[n].mac_name)) { 198: (void) strcpy(line, "$init"); 199: makeargv(); 200: domacro(margc, margv); 201: break; 202: } 203: } 204: return (1); 205: } 206: 207: cmdabort() 208: { 209: extern jmp_buf ptabort; 210: 211: printf("\n"); 212: (void) fflush(stdout); 213: abrtflag++; 214: if (ptflag) 215: longjmp(ptabort,1); 216: } 217: 218: /*VARARGS1*/ 219: command(fmt, args) 220: char *fmt; 221: { 222: int r, (*oldintr)(), cmdabort(); 223: 224: abrtflag = 0; 225: if (debug) { 226: printf("---> "); 227: _doprnt(fmt, &args, stdout); 228: printf("\n"); 229: (void) fflush(stdout); 230: } 231: if (cout == NULL) { 232: perror ("No control connection for command"); 233: code = -1; 234: return (0); 235: } 236: oldintr = signal(SIGINT,cmdabort); 237: _doprnt(fmt, &args, cout); 238: fprintf(cout, "\r\n"); 239: (void) fflush(cout); 240: cpend = 1; 241: r = getreply(!strcmp(fmt, "QUIT")); 242: if (abrtflag && oldintr != SIG_IGN) 243: (*oldintr)(); 244: (void) signal(SIGINT, oldintr); 245: return(r); 246: } 247: 248: #include <ctype.h> 249: 250: getreply(expecteof) 251: int expecteof; 252: { 253: register int c, n; 254: register int dig; 255: int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 256: int pflag = 0; 257: char *pt = pasv; 258: 259: oldintr = signal(SIGINT,cmdabort); 260: for (;;) { 261: dig = n = code = 0; 262: while ((c = getc(cin)) != '\n') { 263: if (c == IAC) { /* handle telnet commands */ 264: switch (c = getc(cin)) { 265: case WILL: 266: case WONT: 267: c = getc(cin); 268: fprintf(cout, "%c%c%c",IAC,WONT,c); 269: (void) fflush(cout); 270: break; 271: case DO: 272: case DONT: 273: c = getc(cin); 274: fprintf(cout, "%c%c%c",IAC,DONT,c); 275: (void) fflush(cout); 276: break; 277: default: 278: break; 279: } 280: continue; 281: } 282: dig++; 283: if (c == EOF) { 284: if (expecteof) { 285: (void) signal(SIGINT,oldintr); 286: code = 221; 287: return (0); 288: } 289: lostpeer(); 290: if (verbose) { 291: printf("421 Service not available, remote server has closed connection\n"); 292: (void) fflush(stdout); 293: code = 421; 294: return(4); 295: } 296: } 297: if (c != '\r' && (verbose > 0 || 298: (verbose > -1 && n == '5' && dig > 4))) { 299: if (proxflag && 300: (dig == 1 || dig == 5 && verbose == 0)) 301: printf("%s:",hostname); 302: (void) putchar(c); 303: } 304: if (dig < 4 && isdigit(c)) 305: code = code * 10 + (c - '0'); 306: if (!pflag && code == 227) 307: pflag = 1; 308: if (dig > 4 && pflag == 1 && isdigit(c)) 309: pflag = 2; 310: if (pflag == 2) { 311: if (c != '\r' && c != ')') 312: *pt++ = c; 313: else { 314: *pt = '\0'; 315: pflag = 3; 316: } 317: } 318: if (dig == 4 && c == '-') { 319: if (continuation) 320: code = 0; 321: continuation++; 322: } 323: if (n == 0) 324: n = c; 325: } 326: if (verbose > 0 || verbose > -1 && n == '5') { 327: (void) putchar(c); 328: (void) fflush (stdout); 329: } 330: if (continuation && code != originalcode) { 331: if (originalcode == 0) 332: originalcode = code; 333: continue; 334: } 335: if (n != '1') 336: cpend = 0; 337: (void) signal(SIGINT,oldintr); 338: if (code == 421 || originalcode == 421) 339: lostpeer(); 340: if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 341: (*oldintr)(); 342: return (n - '0'); 343: } 344: } 345: 346: empty(mask, sec) 347: struct fd_set *mask; 348: int sec; 349: { 350: struct timeval t; 351: 352: t.tv_sec = (long) sec; 353: t.tv_usec = 0; 354: return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 355: } 356: 357: jmp_buf sendabort; 358: 359: abortsend() 360: { 361: 362: mflag = 0; 363: abrtflag = 0; 364: printf("\nsend aborted\n"); 365: (void) fflush(stdout); 366: longjmp(sendabort, 1); 367: } 368: 369: sendrequest(cmd, local, remote) 370: char *cmd, *local, *remote; 371: { 372: FILE *fin, *dout = 0, *mypopen(); 373: int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 374: int abortsend(); 375: char buf[BUFSIZ]; 376: long bytes = 0, hashbytes = sizeof (buf); 377: register int c, d; 378: struct stat st; 379: struct timeval start, stop; 380: 381: if (proxy) { 382: proxtrans(cmd, local, remote); 383: return; 384: } 385: closefunc = NULL; 386: oldintr = NULL; 387: oldintp = NULL; 388: if (setjmp(sendabort)) { 389: while (cpend) { 390: (void) getreply(0); 391: } 392: if (data >= 0) { 393: (void) close(data); 394: data = -1; 395: } 396: if (oldintr) 397: (void) signal(SIGINT,oldintr); 398: if (oldintp) 399: (void) signal(SIGPIPE,oldintp); 400: code = -1; 401: return; 402: } 403: oldintr = signal(SIGINT, abortsend); 404: if (strcmp(local, "-") == 0) 405: fin = stdin; 406: else if (*local == '|') { 407: oldintp = signal(SIGPIPE,SIG_IGN); 408: fin = mypopen(local + 1, "r"); 409: if (fin == NULL) { 410: perror(local + 1); 411: (void) signal(SIGINT, oldintr); 412: (void) signal(SIGPIPE, oldintp); 413: code = -1; 414: return; 415: } 416: closefunc = mypclose; 417: } else { 418: fin = fopen(local, "r"); 419: if (fin == NULL) { 420: perror(local); 421: (void) signal(SIGINT, oldintr); 422: code = -1; 423: return; 424: } 425: closefunc = fclose; 426: if (fstat(fileno(fin), &st) < 0 || 427: (st.st_mode&S_IFMT) != S_IFREG) { 428: fprintf(stdout, "%s: not a plain file.\n", local); 429: (void) signal(SIGINT, oldintr); 430: code = -1; 431: return; 432: } 433: } 434: if (initconn()) { 435: (void) signal(SIGINT, oldintr); 436: if (oldintp) 437: (void) signal(SIGPIPE, oldintp); 438: code = -1; 439: return; 440: } 441: if (setjmp(sendabort)) 442: goto abort; 443: if (remote) { 444: if (command("%s %s", cmd, remote) != PRELIM) { 445: (void) signal(SIGINT, oldintr); 446: if (oldintp) 447: (void) signal(SIGPIPE, oldintp); 448: return; 449: } 450: } else 451: if (command("%s", cmd) != PRELIM) { 452: (void) signal(SIGINT, oldintr); 453: if (oldintp) 454: (void) signal(SIGPIPE, oldintp); 455: return; 456: } 457: dout = dataconn("w"); 458: if (dout == NULL) 459: goto abort; 460: (void) gettimeofday(&start, (struct timezone *)0); 461: switch (type) { 462: 463: case TYPE_I: 464: case TYPE_L: 465: errno = d = 0; 466: while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 467: if ((d = write(fileno (dout), buf, c)) < 0) 468: break; 469: bytes += c; 470: if (hash) { 471: (void) putchar('#'); 472: (void) fflush(stdout); 473: } 474: } 475: if (hash && bytes > 0) { 476: (void) putchar('\n'); 477: (void) fflush(stdout); 478: } 479: if (c < 0) 480: perror(local); 481: if (d < 0) 482: perror("netout"); 483: break; 484: 485: case TYPE_A: 486: while ((c = getc(fin)) != EOF) { 487: if (c == '\n') { 488: while (hash && (bytes >= hashbytes)) { 489: (void) putchar('#'); 490: (void) fflush(stdout); 491: hashbytes += sizeof (buf); 492: } 493: if (ferror(dout)) 494: break; 495: (void) putc('\r', dout); 496: bytes++; 497: } 498: (void) putc(c, dout); 499: bytes++; 500: /* if (c == '\r') { */ 501: /* (void) putc('\0', dout); /* this violates rfc */ 502: /* bytes++; */ 503: /* } */ 504: } 505: if (hash) { 506: if (bytes < hashbytes) 507: (void) putchar('#'); 508: (void) putchar('\n'); 509: (void) fflush(stdout); 510: } 511: if (ferror(fin)) 512: perror(local); 513: if (ferror(dout)) 514: perror("netout"); 515: break; 516: } 517: (void) gettimeofday(&stop, (struct timezone *)0); 518: if (closefunc != NULL) 519: (*closefunc)(fin); 520: (void) fclose(dout); 521: (void) getreply(0); 522: (void) signal(SIGINT, oldintr); 523: if (bytes > 0 && verbose) 524: ptransfer("sent", bytes, &start, &stop, local, remote); 525: return; 526: abort: 527: (void) gettimeofday(&stop, (struct timezone *)0); 528: (void) signal(SIGINT, oldintr); 529: if (oldintp) 530: (void) signal(SIGPIPE, oldintp); 531: if (!cpend) { 532: code = -1; 533: return; 534: } 535: if (data >= 0) { 536: (void) close(data); 537: data = -1; 538: } 539: if (dout) 540: (void) fclose(dout); 541: (void) getreply(0); 542: code = -1; 543: if (closefunc != NULL && fin != NULL) 544: (*closefunc)(fin); 545: if (bytes > 0 && verbose) 546: ptransfer("sent", bytes, &start, &stop, local, remote); 547: } 548: 549: jmp_buf recvabort; 550: 551: abortrecv() 552: { 553: 554: mflag = 0; 555: abrtflag = 0; 556: printf("\n"); 557: (void) fflush(stdout); 558: longjmp(recvabort, 1); 559: } 560: 561: recvrequest(cmd, local, remote, mode) 562: char *cmd, *local, *remote, *mode; 563: { 564: FILE *fout, *din = 0, *mypopen(); 565: int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 566: int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; 567: char buf[BUFSIZ], *gunique(), msg; 568: long bytes = 0, hashbytes = sizeof (buf); 569: struct fd_set mask; 570: register int c, d; 571: struct timeval start, stop; 572: 573: if (proxy && strcmp(cmd,"RETR") == 0) { 574: proxtrans(cmd, local, remote); 575: return; 576: } 577: closefunc = NULL; 578: oldintr = NULL; 579: oldintp = NULL; 580: tcrflag = !crflag && !strcmp(cmd, "RETR"); 581: if (setjmp(recvabort)) { 582: while (cpend) { 583: (void) getreply(0); 584: } 585: if (data >= 0) { 586: (void) close(data); 587: data = -1; 588: } 589: if (oldintr) 590: (void) signal(SIGINT, oldintr); 591: code = -1; 592: return; 593: } 594: oldintr = signal(SIGINT, abortrecv); 595: if (strcmp(local, "-") && *local != '|') { 596: if (access(local, 2) < 0) { 597: char *dir = rindex(local, '/'); 598: 599: if (errno != ENOENT && errno != EACCES) { 600: perror(local); 601: (void) signal(SIGINT, oldintr); 602: code = -1; 603: return; 604: } 605: if (dir != NULL) 606: *dir = 0; 607: d = access(dir ? local : ".", 2); 608: if (dir != NULL) 609: *dir = '/'; 610: if (d < 0) { 611: perror(local); 612: (void) signal(SIGINT, oldintr); 613: code = -1; 614: return; 615: } 616: if (!runique && errno == EACCES && 617: chmod(local,0600) < 0) { 618: perror(local); 619: (void) signal(SIGINT, oldintr); 620: code = -1; 621: return; 622: } 623: if (runique && errno == EACCES && 624: (local = gunique(local)) == NULL) { 625: (void) signal(SIGINT, oldintr); 626: code = -1; 627: return; 628: } 629: } 630: else if (runique && (local = gunique(local)) == NULL) { 631: (void) signal(SIGINT, oldintr); 632: code = -1; 633: return; 634: } 635: } 636: if (initconn()) { 637: (void) signal(SIGINT, oldintr); 638: code = -1; 639: return; 640: } 641: if (setjmp(recvabort)) 642: goto abort; 643: if (strcmp(cmd, "RETR") && type != TYPE_A) { 644: oldtype = type; 645: oldverbose = verbose; 646: if (!debug) 647: verbose = 0; 648: setascii(); 649: verbose = oldverbose; 650: } 651: if (remote) { 652: if (command("%s %s", cmd, remote) != PRELIM) { 653: (void) signal(SIGINT, oldintr); 654: if (oldtype) { 655: if (!debug) 656: verbose = 0; 657: switch (oldtype) { 658: case TYPE_I: 659: setbinary(); 660: break; 661: case TYPE_E: 662: setebcdic(); 663: break; 664: case TYPE_L: 665: settenex(); 666: break; 667: } 668: verbose = oldverbose; 669: } 670: return; 671: } 672: } else { 673: if (command("%s", cmd) != PRELIM) { 674: (void) signal(SIGINT, oldintr); 675: if (oldtype) { 676: if (!debug) 677: verbose = 0; 678: switch (oldtype) { 679: case TYPE_I: 680: setbinary(); 681: break; 682: case TYPE_E: 683: setebcdic(); 684: break; 685: case TYPE_L: 686: settenex(); 687: break; 688: } 689: verbose = oldverbose; 690: } 691: return; 692: } 693: } 694: din = dataconn("r"); 695: if (din == NULL) 696: goto abort; 697: if (strcmp(local, "-") == 0) 698: fout = stdout; 699: else if (*local == '|') { 700: oldintp = signal(SIGPIPE, SIG_IGN); 701: fout = mypopen(local + 1, "w"); 702: if (fout == NULL) { 703: perror(local+1); 704: goto abort; 705: } 706: closefunc = mypclose; 707: } 708: else { 709: fout = fopen(local, mode); 710: if (fout == NULL) { 711: perror(local); 712: goto abort; 713: } 714: closefunc = fclose; 715: } 716: (void) gettimeofday(&start, (struct timezone *)0); 717: switch (type) { 718: 719: case TYPE_I: 720: case TYPE_L: 721: errno = d = 0; 722: while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 723: if ((d = write(fileno(fout), buf, c)) < 0) 724: break; 725: bytes += c; 726: if (hash) { 727: (void) putchar('#'); 728: (void) fflush(stdout); 729: } 730: } 731: if (hash && bytes > 0) { 732: (void) putchar('\n'); 733: (void) fflush(stdout); 734: } 735: if (c < 0) 736: perror("netin"); 737: if (d < 0) 738: perror(local); 739: break; 740: 741: case TYPE_A: 742: while ((c = getc(din)) != EOF) { 743: while (c == '\r') { 744: while (hash && (bytes >= hashbytes)) { 745: (void) putchar('#'); 746: (void) fflush(stdout); 747: hashbytes += sizeof (buf); 748: } 749: bytes++; 750: if ((c = getc(din)) != '\n' || tcrflag) { 751: if (ferror (fout)) 752: break; 753: (void) putc ('\r', fout); 754: } 755: /*if (c == '\0') { 756: bytes++; 757: continue; 758: }*/ 759: } 760: (void) putc (c, fout); 761: bytes++; 762: } 763: if (hash) { 764: if (bytes < hashbytes) 765: (void) putchar('#'); 766: (void) putchar('\n'); 767: (void) fflush(stdout); 768: } 769: if (ferror (din)) 770: perror ("netin"); 771: if (ferror (fout)) 772: perror (local); 773: break; 774: } 775: if (closefunc != NULL) 776: (*closefunc)(fout); 777: (void) signal(SIGINT, oldintr); 778: if (oldintp) 779: (void) signal(SIGPIPE, oldintp); 780: (void) gettimeofday(&stop, (struct timezone *)0); 781: (void) fclose(din); 782: (void) getreply(0); 783: if (bytes > 0 && verbose) 784: ptransfer("received", bytes, &start, &stop, local, remote); 785: if (oldtype) { 786: if (!debug) 787: verbose = 0; 788: switch (oldtype) { 789: case TYPE_I: 790: setbinary(); 791: break; 792: case TYPE_E: 793: setebcdic(); 794: break; 795: case TYPE_L: 796: settenex(); 797: break; 798: } 799: verbose = oldverbose; 800: } 801: return; 802: abort: 803: 804: /* abort using RFC959 recommended IP,SYNC sequence */ 805: 806: (void) gettimeofday(&stop, (struct timezone *)0); 807: if (oldintp) 808: (void) signal(SIGPIPE, oldintr); 809: (void) signal(SIGINT,SIG_IGN); 810: if (oldtype) { 811: if (!debug) 812: verbose = 0; 813: switch (oldtype) { 814: case TYPE_I: 815: setbinary(); 816: break; 817: case TYPE_E: 818: setebcdic(); 819: break; 820: case TYPE_L: 821: settenex(); 822: break; 823: } 824: verbose = oldverbose; 825: } 826: if (!cpend) { 827: code = -1; 828: (void) signal(SIGINT,oldintr); 829: return; 830: } 831: 832: fprintf(cout,"%c%c",IAC,IP); 833: (void) fflush(cout); 834: msg = IAC; 835: /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 836: /* after urgent byte rather than before as now is protocol */ 837: if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 838: perror("abort"); 839: } 840: fprintf(cout,"%cABOR\r\n",DM); 841: (void) fflush(cout); 842: FD_ZERO(&mask); 843: FD_SET(fileno(cin), &mask); 844: if (din) { 845: FD_SET(fileno(din), &mask); 846: } 847: if ((nfnd = empty(&mask,10)) <= 0) { 848: if (nfnd < 0) { 849: perror("abort"); 850: } 851: code = -1; 852: lostpeer(); 853: } 854: if (din && FD_ISSET(fileno(din), &mask)) { 855: while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 856: ; 857: } 858: if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 859: if (data >= 0) { 860: (void) close(data); 861: data = -1; 862: } 863: (void) getreply(0); 864: } 865: (void) getreply(0); 866: code = -1; 867: if (data >= 0) { 868: (void) close(data); 869: data = -1; 870: } 871: if (closefunc != NULL && fout != NULL) 872: (*closefunc)(fout); 873: if (din) 874: (void) fclose(din); 875: if (bytes > 0 && verbose) 876: ptransfer("received", bytes, &start, &stop, local, remote); 877: (void) signal(SIGINT,oldintr); 878: } 879: 880: /* 881: * Need to start a listen on the data channel 882: * before we send the command, otherwise the 883: * server's connect may fail. 884: */ 885: static int sendport = -1; 886: 887: initconn() 888: { 889: register char *p, *a; 890: int result, len, tmpno = 0; 891: int on = 1; 892: 893: noport: 894: data_addr = myctladdr; 895: if (sendport) 896: data_addr.sin_port = 0; /* let system pick one */ 897: if (data != -1) 898: (void) close (data); 899: data = socket(AF_INET, SOCK_STREAM, 0); 900: if (data < 0) { 901: perror("ftp: socket"); 902: if (tmpno) 903: sendport = 1; 904: return (1); 905: } 906: if (!sendport) 907: if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 908: perror("ftp: setsockopt (resuse address)"); 909: goto bad; 910: } 911: if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 912: perror("ftp: bind"); 913: goto bad; 914: } 915: if (options & SO_DEBUG && 916: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 917: perror("ftp: setsockopt (ignored)"); 918: len = sizeof (data_addr); 919: if (getsockname(data, (char *)&data_addr, &len) < 0) { 920: perror("ftp: getsockname"); 921: goto bad; 922: } 923: if (listen(data, 1) < 0) 924: perror("ftp: listen"); 925: if (sendport) { 926: a = (char *)&data_addr.sin_addr; 927: p = (char *)&data_addr.sin_port; 928: #define UC(b) (((int)b)&0xff) 929: result = 930: command("PORT %d,%d,%d,%d,%d,%d", 931: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 932: UC(p[0]), UC(p[1])); 933: if (result == ERROR && sendport == -1) { 934: sendport = 0; 935: tmpno = 1; 936: goto noport; 937: } 938: return (result != COMPLETE); 939: } 940: if (tmpno) 941: sendport = 1; 942: return (0); 943: bad: 944: (void) close(data), data = -1; 945: if (tmpno) 946: sendport = 1; 947: return (1); 948: } 949: 950: FILE * 951: dataconn(mode) 952: char *mode; 953: { 954: struct sockaddr_in from; 955: int s, fromlen = sizeof (from); 956: 957: s = accept(data, (struct sockaddr *) &from, &fromlen); 958: if (s < 0) { 959: perror("ftp: accept"); 960: (void) close(data), data = -1; 961: return (NULL); 962: } 963: (void) close(data); 964: data = s; 965: return (fdopen(data, mode)); 966: } 967: 968: ptransfer(direction, bytes, t0, t1, local, remote) 969: char *direction, *local, *remote; 970: long bytes; 971: struct timeval *t0, *t1; 972: { 973: struct timeval td; 974: float s, bs; 975: 976: tvsub(&td, t1, t0); 977: s = td.tv_sec + (td.tv_usec / 1000000.); 978: #define nz(x) ((x) == 0 ? 1 : (x)) 979: bs = bytes / nz(s); 980: if (local && *local != '-') 981: printf("local: %s ", local); 982: if (remote) 983: printf("remote: %s\n", remote); 984: printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 985: bytes, direction, s, bs / 1024.); 986: } 987: 988: /*tvadd(tsum, t0) 989: struct timeval *tsum, *t0; 990: { 991: 992: tsum->tv_sec += t0->tv_sec; 993: tsum->tv_usec += t0->tv_usec; 994: if (tsum->tv_usec > 1000000) 995: tsum->tv_sec++, tsum->tv_usec -= 1000000; 996: } */ 997: 998: tvsub(tdiff, t1, t0) 999: struct timeval *tdiff, *t1, *t0; 1000: { 1001: 1002: tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 1003: tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 1004: if (tdiff->tv_usec < 0) 1005: tdiff->tv_sec--, tdiff->tv_usec += 1000000; 1006: } 1007: 1008: psabort() 1009: { 1010: extern int abrtflag; 1011: 1012: abrtflag++; 1013: } 1014: 1015: pswitch(flag) 1016: int flag; 1017: { 1018: extern int proxy, abrtflag; 1019: int (*oldintr)(); 1020: static struct comvars { 1021: int connect; 1022: char name[MAXHOSTNAMELEN]; 1023: struct sockaddr_in mctl; 1024: struct sockaddr_in hctl; 1025: FILE *in; 1026: FILE *out; 1027: int tpe; 1028: int cpnd; 1029: int sunqe; 1030: int runqe; 1031: int mcse; 1032: int ntflg; 1033: char nti[17]; 1034: char nto[17]; 1035: int mapflg; 1036: char mi[MAXPATHLEN]; 1037: char mo[MAXPATHLEN]; 1038: } proxstruct, tmpstruct; 1039: struct comvars *ip, *op; 1040: 1041: abrtflag = 0; 1042: oldintr = signal(SIGINT, psabort); 1043: if (flag) { 1044: if (proxy) 1045: return; 1046: ip = &tmpstruct; 1047: op = &proxstruct; 1048: proxy++; 1049: } 1050: else { 1051: if (!proxy) 1052: return; 1053: ip = &proxstruct; 1054: op = &tmpstruct; 1055: proxy = 0; 1056: } 1057: ip->connect = connected; 1058: connected = op->connect; 1059: if (hostname) { 1060: (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1061: ip->name[strlen(ip->name)] = '\0'; 1062: } else 1063: ip->name[0] = 0; 1064: hostname = op->name; 1065: ip->hctl = hisctladdr; 1066: hisctladdr = op->hctl; 1067: ip->mctl = myctladdr; 1068: myctladdr = op->mctl; 1069: ip->in = cin; 1070: cin = op->in; 1071: ip->out = cout; 1072: cout = op->out; 1073: ip->tpe = type; 1074: type = op->tpe; 1075: if (!type) 1076: type = 1; 1077: ip->cpnd = cpend; 1078: cpend = op->cpnd; 1079: ip->sunqe = sunique; 1080: sunique = op->sunqe; 1081: ip->runqe = runique; 1082: runique = op->runqe; 1083: ip->mcse = mcase; 1084: mcase = op->mcse; 1085: ip->ntflg = ntflag; 1086: ntflag = op->ntflg; 1087: (void) strncpy(ip->nti, ntin, 16); 1088: (ip->nti)[strlen(ip->nti)] = '\0'; 1089: (void) strcpy(ntin, op->nti); 1090: (void) strncpy(ip->nto, ntout, 16); 1091: (ip->nto)[strlen(ip->nto)] = '\0'; 1092: (void) strcpy(ntout, op->nto); 1093: ip->mapflg = mapflag; 1094: mapflag = op->mapflg; 1095: (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1096: (ip->mi)[strlen(ip->mi)] = '\0'; 1097: (void) strcpy(mapin, op->mi); 1098: (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1099: (ip->mo)[strlen(ip->mo)] = '\0'; 1100: (void) strcpy(mapout, op->mo); 1101: (void) signal(SIGINT, oldintr); 1102: if (abrtflag) { 1103: abrtflag = 0; 1104: (*oldintr)(); 1105: } 1106: } 1107: 1108: jmp_buf ptabort; 1109: int ptabflg; 1110: 1111: abortpt() 1112: { 1113: printf("\n"); 1114: (void) fflush(stdout); 1115: ptabflg++; 1116: mflag = 0; 1117: abrtflag = 0; 1118: longjmp(ptabort, 1); 1119: } 1120: 1121: proxtrans(cmd, local, remote) 1122: char *cmd, *local, *remote; 1123: { 1124: int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 1125: extern jmp_buf ptabort; 1126: char *cmd2; 1127: struct fd_set mask; 1128: 1129: if (strcmp(cmd, "RETR")) 1130: cmd2 = "RETR"; 1131: else 1132: cmd2 = runique ? "STOU" : "STOR"; 1133: if (command("PASV") != COMPLETE) { 1134: printf("proxy server does not support third part transfers.\n"); 1135: return; 1136: } 1137: tmptype = type; 1138: pswitch(0); 1139: if (!connected) { 1140: printf("No primary connection\n"); 1141: pswitch(1); 1142: code = -1; 1143: return; 1144: } 1145: if (type != tmptype) { 1146: oldtype = type; 1147: switch (tmptype) { 1148: case TYPE_A: 1149: setascii(); 1150: break; 1151: case TYPE_I: 1152: setbinary(); 1153: break; 1154: case TYPE_E: 1155: setebcdic(); 1156: break; 1157: case TYPE_L: 1158: settenex(); 1159: break; 1160: } 1161: } 1162: if (command("PORT %s", pasv) != COMPLETE) { 1163: switch (oldtype) { 1164: case 0: 1165: break; 1166: case TYPE_A: 1167: setascii(); 1168: break; 1169: case TYPE_I: 1170: setbinary(); 1171: break; 1172: case TYPE_E: 1173: setebcdic(); 1174: break; 1175: case TYPE_L: 1176: settenex(); 1177: break; 1178: } 1179: pswitch(1); 1180: return; 1181: } 1182: if (setjmp(ptabort)) 1183: goto abort; 1184: oldintr = signal(SIGINT, abortpt); 1185: if (command("%s %s", cmd, remote) != PRELIM) { 1186: (void) signal(SIGINT, oldintr); 1187: switch (oldtype) { 1188: case 0: 1189: break; 1190: case TYPE_A: 1191: setascii(); 1192: break; 1193: case TYPE_I: 1194: setbinary(); 1195: break; 1196: case TYPE_E: 1197: setebcdic(); 1198: break; 1199: case TYPE_L: 1200: settenex(); 1201: break; 1202: } 1203: pswitch(1); 1204: return; 1205: } 1206: sleep(2); 1207: pswitch(1); 1208: secndflag++; 1209: if (command("%s %s", cmd2, local) != PRELIM) 1210: goto abort; 1211: ptflag++; 1212: (void) getreply(0); 1213: pswitch(0); 1214: (void) getreply(0); 1215: (void) signal(SIGINT, oldintr); 1216: switch (oldtype) { 1217: case 0: 1218: break; 1219: case TYPE_A: 1220: setascii(); 1221: break; 1222: case TYPE_I: 1223: setbinary(); 1224: break; 1225: case TYPE_E: 1226: setebcdic(); 1227: break; 1228: case TYPE_L: 1229: settenex(); 1230: break; 1231: } 1232: pswitch(1); 1233: ptflag = 0; 1234: printf("local: %s remote: %s\n", local, remote); 1235: return; 1236: abort: 1237: (void) signal(SIGINT, SIG_IGN); 1238: ptflag = 0; 1239: if (strcmp(cmd, "RETR") && !proxy) 1240: pswitch(1); 1241: else if (!strcmp(cmd, "RETR") && proxy) 1242: pswitch(0); 1243: if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1244: if (command("%s %s", cmd2, local) != PRELIM) { 1245: pswitch(0); 1246: switch (oldtype) { 1247: case 0: 1248: break; 1249: case TYPE_A: 1250: setascii(); 1251: break; 1252: case TYPE_I: 1253: setbinary(); 1254: break; 1255: case TYPE_E: 1256: setebcdic(); 1257: break; 1258: case TYPE_L: 1259: settenex(); 1260: break; 1261: } 1262: if (cpend) { 1263: char msg[2]; 1264: 1265: fprintf(cout,"%c%c",IAC,IP); 1266: (void) fflush(cout); 1267: *msg = IAC; 1268: *(msg+1) = DM; 1269: if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1270: perror("abort"); 1271: fprintf(cout,"ABOR\r\n"); 1272: (void) fflush(cout); 1273: FD_ZERO(&mask); 1274: FD_SET(fileno(cin), &mask); 1275: if ((nfnd = empty(&mask,10)) <= 0) { 1276: if (nfnd < 0) { 1277: perror("abort"); 1278: } 1279: if (ptabflg) 1280: code = -1; 1281: lostpeer(); 1282: } 1283: (void) getreply(0); 1284: (void) getreply(0); 1285: } 1286: } 1287: pswitch(1); 1288: if (ptabflg) 1289: code = -1; 1290: (void) signal(SIGINT, oldintr); 1291: return; 1292: } 1293: if (cpend) { 1294: char msg[2]; 1295: 1296: fprintf(cout,"%c%c",IAC,IP); 1297: (void) fflush(cout); 1298: *msg = IAC; 1299: *(msg+1) = DM; 1300: if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1301: perror("abort"); 1302: fprintf(cout,"ABOR\r\n"); 1303: (void) fflush(cout); 1304: FD_ZERO(&mask); 1305: FD_SET(fileno(cin), &mask); 1306: if ((nfnd = empty(&mask,10)) <= 0) { 1307: if (nfnd < 0) { 1308: perror("abort"); 1309: } 1310: if (ptabflg) 1311: code = -1; 1312: lostpeer(); 1313: } 1314: (void) getreply(0); 1315: (void) getreply(0); 1316: } 1317: pswitch(!proxy); 1318: if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1319: if (command("%s %s", cmd2, local) != PRELIM) { 1320: pswitch(0); 1321: switch (oldtype) { 1322: case 0: 1323: break; 1324: case TYPE_A: 1325: setascii(); 1326: break; 1327: case TYPE_I: 1328: setbinary(); 1329: break; 1330: case TYPE_E: 1331: setebcdic(); 1332: break; 1333: case TYPE_L: 1334: settenex(); 1335: break; 1336: } 1337: if (cpend) { 1338: char msg[2]; 1339: 1340: fprintf(cout,"%c%c",IAC,IP); 1341: (void) fflush(cout); 1342: *msg = IAC; 1343: *(msg+1) = DM; 1344: if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1345: perror("abort"); 1346: fprintf(cout,"ABOR\r\n"); 1347: (void) fflush(cout); 1348: FD_ZERO(&mask); 1349: FD_SET(fileno(cin), &mask); 1350: if ((nfnd = empty(&mask,10)) <= 0) { 1351: if (nfnd < 0) { 1352: perror("abort"); 1353: } 1354: if (ptabflg) 1355: code = -1; 1356: lostpeer(); 1357: } 1358: (void) getreply(0); 1359: (void) getreply(0); 1360: } 1361: pswitch(1); 1362: if (ptabflg) 1363: code = -1; 1364: (void) signal(SIGINT, oldintr); 1365: return; 1366: } 1367: } 1368: if (cpend) { 1369: char msg[2]; 1370: 1371: fprintf(cout,"%c%c",IAC,IP); 1372: (void) fflush(cout); 1373: *msg = IAC; 1374: *(msg+1) = DM; 1375: if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1376: perror("abort"); 1377: fprintf(cout,"ABOR\r\n"); 1378: (void) fflush(cout); 1379: FD_ZERO(&mask); 1380: FD_SET(fileno(cin), &mask); 1381: if ((nfnd = empty(&mask,10)) <= 0) { 1382: if (nfnd < 0) { 1383: perror("abort"); 1384: } 1385: if (ptabflg) 1386: code = -1; 1387: lostpeer(); 1388: } 1389: (void) getreply(0); 1390: (void) getreply(0); 1391: } 1392: pswitch(!proxy); 1393: if (cpend) { 1394: FD_ZERO(&mask); 1395: FD_SET(fileno(cin), &mask); 1396: if ((nfnd = empty(&mask,10)) <= 0) { 1397: if (nfnd < 0) { 1398: perror("abort"); 1399: } 1400: if (ptabflg) 1401: code = -1; 1402: lostpeer(); 1403: } 1404: (void) getreply(0); 1405: (void) getreply(0); 1406: } 1407: if (proxy) 1408: pswitch(0); 1409: switch (oldtype) { 1410: case 0: 1411: break; 1412: case TYPE_A: 1413: setascii(); 1414: break; 1415: case TYPE_I: 1416: setbinary(); 1417: break; 1418: case TYPE_E: 1419: setebcdic(); 1420: break; 1421: case TYPE_L: 1422: settenex(); 1423: break; 1424: } 1425: pswitch(1); 1426: if (ptabflg) 1427: code = -1; 1428: (void) signal(SIGINT, oldintr); 1429: } 1430: 1431: reset() 1432: { 1433: struct fd_set mask; 1434: int nfnd = 1; 1435: 1436: FD_ZERO(&mask); 1437: while (nfnd) { 1438: FD_SET(fileno(cin), &mask); 1439: if ((nfnd = empty(&mask,0)) < 0) { 1440: perror("reset"); 1441: code = -1; 1442: lostpeer(); 1443: } 1444: else if (nfnd) { 1445: (void) getreply(0); 1446: } 1447: } 1448: } 1449: 1450: char * 1451: gunique(local) 1452: char *local; 1453: { 1454: static char new[MAXPATHLEN]; 1455: char *cp = rindex(local, '/'); 1456: int d, count=0; 1457: char ext = '1'; 1458: 1459: if (cp) 1460: *cp = '\0'; 1461: d = access(cp ? local : ".", 2); 1462: if (cp) 1463: *cp = '/'; 1464: if (d < 0) { 1465: perror(local); 1466: return((char *) 0); 1467: } 1468: (void) strcpy(new, local); 1469: cp = new + strlen(new); 1470: *cp++ = '.'; 1471: while (!d) { 1472: if (++count == 100) { 1473: printf("runique: can't find unique file name.\n"); 1474: return((char *) 0); 1475: } 1476: *cp++ = ext; 1477: *cp = '\0'; 1478: if (ext == '9') 1479: ext = '0'; 1480: else 1481: ext++; 1482: if ((d = access(new, 0)) < 0) 1483: break; 1484: if (ext != '0') 1485: cp--; 1486: else if (*(cp - 2) == '.') 1487: *(cp - 1) = '1'; 1488: else { 1489: *(cp - 2) = *(cp - 2) + 1; 1490: cp--; 1491: } 1492: } 1493: return(new); 1494: }