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