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