1 #ifndef lint 2 static char sccsid[] = "@(#)ftp.c 4.7 (Berkeley) 03/23/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 10 #include <netinet/in.h> 11 12 #include <stdio.h> 13 #include <signal.h> 14 #include <time.h> 15 #include <errno.h> 16 #include <netdb.h> 17 18 #include "ftp.h" 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) { 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 putchar('\n'); 307 fflush(stdout); 308 } 309 if (ferror(fin)) 310 perror(local); 311 if (ferror(dout)) 312 perror("netout"); 313 break; 314 } 315 gettimeofday(&stop, (struct timezone *)0); 316 if (closefunc != NULL) 317 (*closefunc)(fin); 318 (void) fclose(dout); 319 (void) getreply(0); 320 done: 321 signal(SIGINT, oldintr); 322 if (bytes > 0 && verbose) 323 ptransfer("sent", bytes, &start, &stop); 324 return; 325 bad: 326 if (data >= 0) 327 (void) close(data), data = -1; 328 if (closefunc != NULL && fin != NULL) 329 (*closefunc)(fin); 330 goto done; 331 } 332 333 jmp_buf recvabort; 334 335 abortrecv() 336 { 337 338 longjmp(recvabort, 1); 339 } 340 341 recvrequest(cmd, local, remote, mode) 342 char *cmd, *local, *remote, *mode; 343 { 344 FILE *fout, *din, *popen(); 345 int (*closefunc)(), pclose(), fclose(), (*oldintr)(); 346 char buf[BUFSIZ]; 347 long bytes = 0, hashbytes = sizeof (buf); 348 register int c, d; 349 struct timeval start, stop; 350 351 closefunc = NULL; 352 if (setjmp(recvabort)) 353 goto bad; 354 oldintr = signal(SIGINT, abortrecv); 355 if (strcmp(local, "-") && *local != '|') 356 if (access(local, 2) < 0) { 357 char *dir = rindex(local, '/'); 358 359 if (dir != NULL) 360 *dir = 0; 361 if (access(dir ? dir : ".", 2) < 0) { 362 perror(local); 363 goto bad; 364 } 365 if (dir != NULL) 366 *dir = '/'; 367 } 368 if (initconn()) 369 goto bad; 370 if (remote) { 371 if (command("%s %s", cmd, remote) != PRELIM) 372 goto bad; 373 } else 374 if (command("%s", cmd) != PRELIM) 375 goto bad; 376 if (strcmp(local, "-") == 0) 377 fout = stdout; 378 else if (*local == '|') { 379 fout = popen(local + 1, "w"); 380 closefunc = pclose; 381 } else { 382 fout = fopen(local, mode); 383 closefunc = fclose; 384 } 385 if (fout == NULL) { 386 perror(local + 1); 387 goto bad; 388 } 389 din = dataconn("r"); 390 if (din == NULL) 391 goto bad; 392 gettimeofday(&start, (struct timezone *)0); 393 switch (type) { 394 395 case TYPE_I: 396 case TYPE_L: 397 errno = d = 0; 398 while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 399 if ((d = write(fileno(fout), buf, c)) < 0) 400 break; 401 bytes += c; 402 if (hash) { 403 putchar('#'); 404 fflush(stdout); 405 } 406 } 407 if (hash) { 408 putchar('\n'); 409 fflush(stdout); 410 } 411 if (c < 0) 412 perror("netin"); 413 if (d < 0) 414 perror(local); 415 break; 416 417 case TYPE_A: 418 while ((c = getc(din)) != EOF) { 419 if (c == '\r') { 420 while (hash && (bytes >= hashbytes)) { 421 putchar('#'); 422 fflush(stdout); 423 hashbytes += sizeof (buf); 424 } 425 bytes++; 426 if ((c = getc(din)) != '\n') { 427 if (ferror (fout)) 428 break; 429 putc ('\r', fout); 430 } 431 if (c == '\0') { 432 bytes++; 433 continue; 434 } 435 } 436 putc (c, fout); 437 bytes++; 438 } 439 if (hash) { 440 putchar('\n'); 441 fflush(stdout); 442 } 443 if (ferror (din)) 444 perror ("netin"); 445 if (ferror (fout)) 446 perror (local); 447 break; 448 } 449 gettimeofday(&stop, (struct timezone *)0); 450 (void) fclose(din); 451 if (closefunc != NULL) 452 (*closefunc)(fout); 453 (void) getreply(0); 454 done: 455 signal(SIGINT, oldintr); 456 if (bytes > 0 && verbose) 457 ptransfer("received", bytes, &start, &stop); 458 return; 459 bad: 460 if (data >= 0) 461 (void) close(data), data = -1; 462 if (closefunc != NULL && fout != NULL) 463 (*closefunc)(fout); 464 goto done; 465 } 466 467 /* 468 * Need to start a listen on the data channel 469 * before we send the command, otherwise the 470 * server's connect may fail. 471 */ 472 static int sendport = -1; 473 474 initconn() 475 { 476 register char *p, *a; 477 int result, len; 478 479 noport: 480 data_addr = myctladdr; 481 if (sendport) 482 data_addr.sin_port = 0; /* let system pick one */ 483 if (data != -1) 484 (void) close (data); 485 data = socket(AF_INET, SOCK_STREAM, 0, 0); 486 if (data < 0) { 487 perror("ftp: socket"); 488 return (1); 489 } 490 if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 491 perror("ftp: bind"); 492 goto bad; 493 } 494 if (options & SO_DEBUG && 495 setsockopt(data, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 496 perror("ftp: setsockopt (ignored)"); 497 len = sizeof (data_addr); 498 if (getsockname(data, (char *)&data_addr, &len) < 0) { 499 perror("ftp: getsockname"); 500 goto bad; 501 } 502 if (listen(data, 1) < 0) { 503 perror("ftp: listen"); 504 goto bad; 505 } 506 if (sendport) { 507 a = (char *)&data_addr.sin_addr; 508 p = (char *)&data_addr.sin_port; 509 #define UC(b) (((int)b)&0xff) 510 result = 511 command("PORT %d,%d,%d,%d,%d,%d", 512 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 513 UC(p[0]), UC(p[1])); 514 if (result == ERROR && sendport == -1) { 515 sendport = 0; 516 goto noport; 517 } 518 return (result != COMPLETE); 519 } 520 return (0); 521 bad: 522 (void) close(data), data = -1; 523 return (1); 524 } 525 526 FILE * 527 dataconn(mode) 528 char *mode; 529 { 530 struct sockaddr_in from; 531 int s, fromlen = sizeof (from); 532 533 s = accept(data, &from, &fromlen, 0); 534 if (s < 0) { 535 perror("ftp: accept"); 536 (void) close(data), data = -1; 537 return (NULL); 538 } 539 (void) close(data); 540 data = s; 541 return (fdopen(data, mode)); 542 } 543 544 ptransfer(direction, bytes, t0, t1) 545 char *direction; 546 long bytes; 547 struct timeval *t0, *t1; 548 { 549 struct timeval td; 550 long ms; 551 float bs; 552 553 tvsub(&td, t1, t0); 554 ms = (td.tv_sec * 1000) + (td.tv_usec / 1000); 555 #define nz(x) ((x) == 0 ? 1 : (x)) 556 bs = ((bytes * NBBY * 1000) / (float) nz(ms)) / NBBY; 557 printf("%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n", 558 bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.); 559 } 560 561 tvadd(tsum, t0) 562 struct timeval *tsum, *t0; 563 { 564 565 tsum->tv_sec += t0->tv_sec; 566 tsum->tv_usec += t0->tv_usec; 567 if (tsum->tv_usec > 1000000) 568 tsum->tv_sec++, tsum->tv_usec -= 1000000; 569 } 570 571 tvsub(tdiff, t1, t0) 572 struct timeval *tdiff, *t1, *t0; 573 { 574 575 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 576 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 577 if (tdiff->tv_usec < 0) 578 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 579 } 580