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