1 #ifndef lint 2 static char sccsid[] = "@(#)ftp.c 4.16 (Berkeley) 03/11/85"; 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); 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.\n", 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 d = access(dir ? local : ".", 2); 364 if (dir != NULL) 365 *dir = '/'; 366 if (d < 0) { 367 perror(local); 368 goto bad; 369 } 370 } 371 if (initconn()) 372 goto bad; 373 if (remote) { 374 if (command("%s %s", cmd, remote) != PRELIM) 375 goto bad; 376 } else 377 if (command("%s", cmd) != PRELIM) 378 goto bad; 379 if (strcmp(local, "-") == 0) 380 fout = stdout; 381 else if (*local == '|') { 382 fout = popen(local + 1, "w"); 383 closefunc = pclose; 384 } else { 385 fout = fopen(local, mode); 386 closefunc = fclose; 387 } 388 if (fout == NULL) { 389 perror(local + 1); 390 goto bad; 391 } 392 din = dataconn("r"); 393 if (din == NULL) 394 goto bad; 395 gettimeofday(&start, (struct timezone *)0); 396 switch (type) { 397 398 case TYPE_I: 399 case TYPE_L: 400 errno = d = 0; 401 while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 402 if ((d = write(fileno(fout), buf, c)) < 0) 403 break; 404 bytes += c; 405 if (hash) { 406 putchar('#'); 407 fflush(stdout); 408 } 409 } 410 if (hash && bytes > 0) { 411 putchar('\n'); 412 fflush(stdout); 413 } 414 if (c < 0) 415 perror("netin"); 416 if (d < 0) 417 perror(local); 418 break; 419 420 case TYPE_A: 421 while ((c = getc(din)) != EOF) { 422 if (c == '\r') { 423 while (hash && (bytes >= hashbytes)) { 424 putchar('#'); 425 fflush(stdout); 426 hashbytes += sizeof (buf); 427 } 428 bytes++; 429 if ((c = getc(din)) != '\n') { 430 if (ferror (fout)) 431 break; 432 putc ('\r', fout); 433 } 434 if (c == '\0') { 435 bytes++; 436 continue; 437 } 438 } 439 putc (c, fout); 440 bytes++; 441 } 442 if (hash) { 443 if (bytes < hashbytes) 444 putchar('#'); 445 putchar('\n'); 446 fflush(stdout); 447 } 448 if (ferror (din)) 449 perror ("netin"); 450 if (ferror (fout)) 451 perror (local); 452 break; 453 } 454 gettimeofday(&stop, (struct timezone *)0); 455 (void) fclose(din); 456 if (closefunc != NULL) 457 (*closefunc)(fout); 458 (void) getreply(0); 459 done: 460 signal(SIGINT, oldintr); 461 if (bytes > 0 && verbose) 462 ptransfer("received", bytes, &start, &stop); 463 return; 464 bad: 465 if (data >= 0) 466 (void) close(data), data = -1; 467 if (closefunc != NULL && fout != NULL) 468 (*closefunc)(fout); 469 goto done; 470 } 471 472 /* 473 * Need to start a listen on the data channel 474 * before we send the command, otherwise the 475 * server's connect may fail. 476 */ 477 static int sendport = -1; 478 479 initconn() 480 { 481 register char *p, *a; 482 int result, len; 483 int on = 1; 484 485 noport: 486 data_addr = myctladdr; 487 if (sendport) 488 data_addr.sin_port = 0; /* let system pick one */ 489 if (data != -1) 490 (void) close (data); 491 data = socket(AF_INET, SOCK_STREAM, 0); 492 if (data < 0) { 493 perror("ftp: socket"); 494 return (1); 495 } 496 if (!sendport) 497 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 498 perror("ftp: setsockopt (resuse address)"); 499 goto bad; 500 } 501 if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 502 perror("ftp: bind"); 503 goto bad; 504 } 505 if (options & SO_DEBUG && 506 setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 507 perror("ftp: setsockopt (ignored)"); 508 len = sizeof (data_addr); 509 if (getsockname(data, (char *)&data_addr, &len) < 0) { 510 perror("ftp: getsockname"); 511 goto bad; 512 } 513 if (listen(data, 1) < 0) { 514 perror("ftp: listen"); 515 goto bad; 516 } 517 if (sendport) { 518 a = (char *)&data_addr.sin_addr; 519 p = (char *)&data_addr.sin_port; 520 #define UC(b) (((int)b)&0xff) 521 result = 522 command("PORT %d,%d,%d,%d,%d,%d", 523 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 524 UC(p[0]), UC(p[1])); 525 if (result == ERROR && sendport == -1) { 526 sendport = 0; 527 goto noport; 528 } 529 return (result != COMPLETE); 530 } 531 return (0); 532 bad: 533 (void) close(data), data = -1; 534 return (1); 535 } 536 537 FILE * 538 dataconn(mode) 539 char *mode; 540 { 541 struct sockaddr_in from; 542 int s, fromlen = sizeof (from); 543 544 s = accept(data, &from, &fromlen, 0); 545 if (s < 0) { 546 perror("ftp: accept"); 547 (void) close(data), data = -1; 548 return (NULL); 549 } 550 (void) close(data); 551 data = s; 552 return (fdopen(data, mode)); 553 } 554 555 ptransfer(direction, bytes, t0, t1) 556 char *direction; 557 long bytes; 558 struct timeval *t0, *t1; 559 { 560 struct timeval td; 561 float s, bs; 562 563 tvsub(&td, t1, t0); 564 s = td.tv_sec + (td.tv_usec / 1000000.); 565 #define nz(x) ((x) == 0 ? 1 : (x)) 566 bs = bytes / nz(s); 567 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 568 bytes, direction, s, bs / 1024.); 569 } 570 571 tvadd(tsum, t0) 572 struct timeval *tsum, *t0; 573 { 574 575 tsum->tv_sec += t0->tv_sec; 576 tsum->tv_usec += t0->tv_usec; 577 if (tsum->tv_usec > 1000000) 578 tsum->tv_sec++, tsum->tv_usec -= 1000000; 579 } 580 581 tvsub(tdiff, t1, t0) 582 struct timeval *tdiff, *t1, *t0; 583 { 584 585 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 586 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 587 if (tdiff->tv_usec < 0) 588 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 589 } 590