1 /* 2 * Copyright (c) 1980 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.4 (Berkeley) 01/13/86"; 9 #endif not lint 10 11 #include <sys/param.h> 12 #include <sys/stat.h> 13 #include <sys/ioctl.h> 14 #include <sys/socket.h> 15 #include <sys/time.h> 16 17 #include <netinet/in.h> 18 #include <arpa/ftp.h> 19 20 #include <stdio.h> 21 #include <signal.h> 22 #include <errno.h> 23 #include <netdb.h> 24 25 #include "ftp_var.h" 26 27 struct sockaddr_in hisctladdr; 28 struct sockaddr_in data_addr; 29 int data = -1; 30 int connected; 31 struct sockaddr_in myctladdr; 32 33 FILE *cin, *cout; 34 FILE *dataconn(); 35 36 char * 37 hookup(host, port) 38 char *host; 39 int port; 40 { 41 register struct hostent *hp = 0; 42 static char hostnamebuf[80]; 43 int s, len; 44 45 bzero((char *)&hisctladdr, sizeof (hisctladdr)); 46 hisctladdr.sin_addr.s_addr = inet_addr(host); 47 if (hisctladdr.sin_addr.s_addr != -1) { 48 hisctladdr.sin_family = AF_INET; 49 (void) strcpy(hostnamebuf, host); 50 } else { 51 hp = gethostbyname(host); 52 if (hp == NULL) { 53 printf("%s: unknown host\n", host); 54 return (0); 55 } 56 hisctladdr.sin_family = hp->h_addrtype; 57 bcopy(hp->h_addr_list[0], 58 (caddr_t)&hisctladdr.sin_addr, hp->h_length); 59 (void) strcpy(hostnamebuf, hp->h_name); 60 } 61 hostname = hostnamebuf; 62 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 63 if (s < 0) { 64 perror("ftp: socket"); 65 return (0); 66 } 67 hisctladdr.sin_port = port; 68 while (connect(s, (caddr_t)&hisctladdr, sizeof (hisctladdr)) < 0) { 69 if (hp && hp->h_addr_list[1]) { 70 int oerrno = errno; 71 72 fprintf(stderr, "ftp: connect to address %s: ", 73 inet_ntoa(hisctladdr.sin_addr)); 74 errno = oerrno; 75 perror(0); 76 hp->h_addr_list++; 77 bcopy(hp->h_addr_list[0], 78 (caddr_t)&hisctladdr.sin_addr, hp->h_length); 79 fprintf(stderr, "Trying %s...\n", 80 inet_ntoa(hisctladdr.sin_addr)); 81 continue; 82 } 83 perror("ftp: connect"); 84 goto bad; 85 } 86 len = sizeof (myctladdr); 87 if (getsockname(s, (char *)&myctladdr, &len) < 0) { 88 perror("ftp: getsockname"); 89 goto bad; 90 } 91 cin = fdopen(s, "r"); 92 cout = fdopen(s, "w"); 93 if (cin == NULL || cout == NULL) { 94 fprintf(stderr, "ftp: fdopen failed.\n"); 95 if (cin) 96 fclose(cin); 97 if (cout) 98 fclose(cout); 99 goto bad; 100 } 101 if (verbose) 102 printf("Connected to %s.\n", hostname); 103 (void) getreply(0); /* read startup message from server */ 104 return (hostname); 105 bad: 106 close(s); 107 return ((char *)0); 108 } 109 110 login(host) 111 char *host; 112 { 113 char acct[80]; 114 char *user, *pass; 115 int n; 116 117 user = pass = 0; 118 ruserpass(host, &user, &pass); 119 n = command("USER %s", user); 120 if (n == CONTINUE) 121 n = command("PASS %s", pass); 122 if (n == CONTINUE) { 123 printf("Account: "); (void) fflush(stdout); 124 (void) fgets(acct, sizeof(acct) - 1, stdin); 125 acct[strlen(acct) - 1] = '\0'; 126 n = command("ACCT %s", acct); 127 } 128 if (n != COMPLETE) { 129 fprintf(stderr, "Login failed.\n"); 130 return (0); 131 } 132 return (1); 133 } 134 135 /*VARARGS 1*/ 136 command(fmt, args) 137 char *fmt; 138 { 139 140 if (debug) { 141 printf("---> "); 142 _doprnt(fmt, &args, stdout); 143 printf("\n"); 144 (void) fflush(stdout); 145 } 146 if (cout == NULL) { 147 perror ("No control connection for command"); 148 return (0); 149 } 150 _doprnt(fmt, &args, cout); 151 fprintf(cout, "\r\n"); 152 (void) fflush(cout); 153 return (getreply(!strcmp(fmt, "QUIT"))); 154 } 155 156 #include <ctype.h> 157 158 getreply(expecteof) 159 int expecteof; 160 { 161 register int c, n; 162 register int code, dig; 163 int originalcode = 0, continuation = 0; 164 165 for (;;) { 166 dig = n = code = 0; 167 while ((c = getc(cin)) != '\n') { 168 dig++; 169 if (c == EOF) { 170 if (expecteof) 171 return (0); 172 lostpeer(); 173 exit(1); 174 } 175 if (verbose && c != '\r' || 176 (n == '5' && dig > 4)) 177 putchar(c); 178 if (dig < 4 && isdigit(c)) 179 code = code * 10 + (c - '0'); 180 if (dig == 4 && c == '-') 181 continuation++; 182 if (n == 0) 183 n = c; 184 } 185 if (verbose || n == '5') { 186 putchar(c); 187 (void) fflush (stdout); 188 } 189 if (continuation && code != originalcode) { 190 if (originalcode == 0) 191 originalcode = code; 192 continue; 193 } 194 if (expecteof || empty(cin)) 195 return (n - '0'); 196 } 197 } 198 199 empty(f) 200 FILE *f; 201 { 202 long mask; 203 struct timeval t; 204 205 if (f->_cnt > 0) 206 return (0); 207 mask = (1 << fileno(f)); 208 t.tv_sec = t.tv_usec = 0; 209 (void) select(20, &mask, 0, 0, &t); 210 return (mask == 0); 211 } 212 213 jmp_buf sendabort; 214 215 abortsend() 216 { 217 218 longjmp(sendabort, 1); 219 } 220 221 sendrequest(cmd, local, remote) 222 char *cmd, *local, *remote; 223 { 224 FILE *fin, *dout, *popen(); 225 int (*closefunc)(), pclose(), fclose(), (*oldintr)(); 226 char buf[BUFSIZ]; 227 long bytes = 0, hashbytes = sizeof (buf); 228 register int c, d; 229 struct stat st; 230 struct timeval start, stop; 231 232 closefunc = NULL; 233 if (setjmp(sendabort)) 234 goto bad; 235 oldintr = signal(SIGINT, abortsend); 236 if (strcmp(local, "-") == 0) 237 fin = stdin; 238 else if (*local == '|') { 239 fin = popen(local + 1, "r"); 240 if (fin == NULL) { 241 perror(local + 1); 242 goto bad; 243 } 244 closefunc = pclose; 245 } else { 246 fin = fopen(local, "r"); 247 if (fin == NULL) { 248 perror(local); 249 goto bad; 250 } 251 closefunc = fclose; 252 if (fstat(fileno(fin), &st) < 0 || 253 (st.st_mode&S_IFMT) != S_IFREG) { 254 fprintf(stderr, "%s: not a plain file.\n", local); 255 goto bad; 256 } 257 } 258 if (initconn()) 259 goto bad; 260 if (remote) { 261 if (command("%s %s", cmd, remote) != PRELIM) 262 goto bad; 263 } else 264 if (command("%s", cmd) != PRELIM) 265 goto bad; 266 dout = dataconn("w"); 267 if (dout == NULL) 268 goto bad; 269 gettimeofday(&start, (struct timezone *)0); 270 switch (type) { 271 272 case TYPE_I: 273 case TYPE_L: 274 errno = d = 0; 275 while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 276 if ((d = write(fileno (dout), buf, c)) < 0) 277 break; 278 bytes += c; 279 if (hash) { 280 putchar('#'); 281 fflush(stdout); 282 } 283 } 284 if (hash && bytes > 0) { 285 putchar('\n'); 286 fflush(stdout); 287 } 288 if (c < 0) 289 perror(local); 290 if (d < 0) 291 perror("netout"); 292 break; 293 294 case TYPE_A: 295 while ((c = getc(fin)) != EOF) { 296 if (c == '\n') { 297 while (hash && (bytes >= hashbytes)) { 298 putchar('#'); 299 fflush(stdout); 300 hashbytes += sizeof (buf); 301 } 302 if (ferror(dout)) 303 break; 304 putc('\r', dout); 305 bytes++; 306 } 307 putc(c, dout); 308 bytes++; 309 if (c == '\r') { 310 putc('\0', dout); 311 bytes++; 312 } 313 } 314 if (hash) { 315 if (bytes < hashbytes) 316 putchar('#'); 317 putchar('\n'); 318 fflush(stdout); 319 } 320 if (ferror(fin)) 321 perror(local); 322 if (ferror(dout)) 323 perror("netout"); 324 break; 325 } 326 gettimeofday(&stop, (struct timezone *)0); 327 if (closefunc != NULL) 328 (*closefunc)(fin); 329 (void) fclose(dout); 330 (void) getreply(0); 331 done: 332 signal(SIGINT, oldintr); 333 if (bytes > 0 && verbose) 334 ptransfer("sent", bytes, &start, &stop); 335 return; 336 bad: 337 if (data >= 0) 338 (void) close(data), data = -1; 339 if (closefunc != NULL && fin != NULL) 340 (*closefunc)(fin); 341 goto done; 342 } 343 344 jmp_buf recvabort; 345 346 abortrecv() 347 { 348 349 longjmp(recvabort, 1); 350 } 351 352 recvrequest(cmd, local, remote, mode) 353 char *cmd, *local, *remote, *mode; 354 { 355 FILE *fout, *din, *popen(); 356 int (*closefunc)(), pclose(), fclose(), (*oldintr)(); 357 char buf[BUFSIZ]; 358 long bytes = 0, hashbytes = sizeof (buf); 359 register int c, d; 360 struct timeval start, stop; 361 362 closefunc = NULL; 363 if (setjmp(recvabort)) 364 goto bad; 365 oldintr = signal(SIGINT, abortrecv); 366 if (strcmp(local, "-") && *local != '|') 367 if (access(local, 2) < 0) { 368 char *dir = rindex(local, '/'); 369 370 if (dir != NULL) 371 *dir = 0; 372 d = access(dir ? local : ".", 2); 373 if (dir != NULL) 374 *dir = '/'; 375 if (d < 0) { 376 perror(local); 377 goto bad; 378 } 379 } 380 if (initconn()) 381 goto bad; 382 if (remote) { 383 if (command("%s %s", cmd, remote) != PRELIM) 384 goto bad; 385 } else 386 if (command("%s", cmd) != PRELIM) 387 goto bad; 388 if (strcmp(local, "-") == 0) 389 fout = stdout; 390 else if (*local == '|') { 391 fout = popen(local + 1, "w"); 392 closefunc = pclose; 393 } else { 394 fout = fopen(local, mode); 395 closefunc = fclose; 396 } 397 if (fout == NULL) { 398 perror(local + 1); 399 goto bad; 400 } 401 din = dataconn("r"); 402 if (din == NULL) 403 goto bad; 404 gettimeofday(&start, (struct timezone *)0); 405 switch (type) { 406 407 case TYPE_I: 408 case TYPE_L: 409 errno = d = 0; 410 while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 411 if ((d = write(fileno(fout), buf, c)) < 0) 412 break; 413 bytes += c; 414 if (hash) { 415 putchar('#'); 416 fflush(stdout); 417 } 418 } 419 if (hash && bytes > 0) { 420 putchar('\n'); 421 fflush(stdout); 422 } 423 if (c < 0) 424 perror("netin"); 425 if (d < 0) 426 perror(local); 427 break; 428 429 case TYPE_A: 430 while ((c = getc(din)) != EOF) { 431 if (c == '\r') { 432 while (hash && (bytes >= hashbytes)) { 433 putchar('#'); 434 fflush(stdout); 435 hashbytes += sizeof (buf); 436 } 437 bytes++; 438 if ((c = getc(din)) != '\n') { 439 if (ferror (fout)) 440 break; 441 putc ('\r', fout); 442 } 443 if (c == '\0') { 444 bytes++; 445 continue; 446 } 447 } 448 putc (c, fout); 449 bytes++; 450 } 451 if (hash) { 452 if (bytes < hashbytes) 453 putchar('#'); 454 putchar('\n'); 455 fflush(stdout); 456 } 457 if (ferror (din)) 458 perror ("netin"); 459 if (ferror (fout)) 460 perror (local); 461 break; 462 } 463 gettimeofday(&stop, (struct timezone *)0); 464 (void) fclose(din); 465 if (closefunc != NULL) 466 (*closefunc)(fout); 467 (void) getreply(0); 468 done: 469 signal(SIGINT, oldintr); 470 if (bytes > 0 && verbose) 471 ptransfer("received", bytes, &start, &stop); 472 return; 473 bad: 474 if (data >= 0) 475 (void) close(data), data = -1; 476 if (closefunc != NULL && fout != NULL) 477 (*closefunc)(fout); 478 goto done; 479 } 480 481 /* 482 * Need to start a listen on the data channel 483 * before we send the command, otherwise the 484 * server's connect may fail. 485 */ 486 static int sendport = -1; 487 488 initconn() 489 { 490 register char *p, *a; 491 int result, len; 492 int on = 1; 493 494 noport: 495 data_addr = myctladdr; 496 if (sendport) 497 data_addr.sin_port = 0; /* let system pick one */ 498 if (data != -1) 499 (void) close (data); 500 data = socket(AF_INET, SOCK_STREAM, 0); 501 if (data < 0) { 502 perror("ftp: socket"); 503 return (1); 504 } 505 if (!sendport) 506 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 507 perror("ftp: setsockopt (resuse address)"); 508 goto bad; 509 } 510 if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 511 perror("ftp: bind"); 512 goto bad; 513 } 514 if (options & SO_DEBUG && 515 setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 516 perror("ftp: setsockopt (ignored)"); 517 len = sizeof (data_addr); 518 if (getsockname(data, (char *)&data_addr, &len) < 0) { 519 perror("ftp: getsockname"); 520 goto bad; 521 } 522 if (listen(data, 1) < 0) { 523 perror("ftp: listen"); 524 goto bad; 525 } 526 if (sendport) { 527 a = (char *)&data_addr.sin_addr; 528 p = (char *)&data_addr.sin_port; 529 #define UC(b) (((int)b)&0xff) 530 result = 531 command("PORT %d,%d,%d,%d,%d,%d", 532 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 533 UC(p[0]), UC(p[1])); 534 if (result == ERROR && sendport == -1) { 535 sendport = 0; 536 goto noport; 537 } 538 return (result != COMPLETE); 539 } 540 return (0); 541 bad: 542 (void) close(data), data = -1; 543 return (1); 544 } 545 546 FILE * 547 dataconn(mode) 548 char *mode; 549 { 550 struct sockaddr_in from; 551 int s, fromlen = sizeof (from); 552 553 s = accept(data, &from, &fromlen, 0); 554 if (s < 0) { 555 perror("ftp: accept"); 556 (void) close(data), data = -1; 557 return (NULL); 558 } 559 (void) close(data); 560 data = s; 561 return (fdopen(data, mode)); 562 } 563 564 ptransfer(direction, bytes, t0, t1) 565 char *direction; 566 long bytes; 567 struct timeval *t0, *t1; 568 { 569 struct timeval td; 570 float s, bs; 571 572 tvsub(&td, t1, t0); 573 s = td.tv_sec + (td.tv_usec / 1000000.); 574 #define nz(x) ((x) == 0 ? 1 : (x)) 575 bs = bytes / nz(s); 576 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 577 bytes, direction, s, bs / 1024.); 578 } 579 580 tvadd(tsum, t0) 581 struct timeval *tsum, *t0; 582 { 583 584 tsum->tv_sec += t0->tv_sec; 585 tsum->tv_usec += t0->tv_usec; 586 if (tsum->tv_usec > 1000000) 587 tsum->tv_sec++, tsum->tv_usec -= 1000000; 588 } 589 590 tvsub(tdiff, t1, t0) 591 struct timeval *tdiff, *t1, *t0; 592 { 593 594 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 595 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 596 if (tdiff->tv_usec < 0) 597 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 598 } 599