1 /* 2 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $Id: ftpd.c,v 1.41 1997/07/24 09:26:12 davidn Exp $ 34 */ 35 36 #if 0 37 #ifndef lint 38 static char copyright[] = 39 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 #endif 43 44 #if 0 45 #ifndef lint 46 static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; 47 #endif /* not lint */ 48 #endif 49 50 /* 51 * FTP server. 52 */ 53 #include <sys/param.h> 54 #include <sys/stat.h> 55 #include <sys/ioctl.h> 56 #include <sys/socket.h> 57 #include <sys/wait.h> 58 #include <sys/mman.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/ip.h> 63 #include <netinet/tcp.h> 64 65 #define FTP_NAMES 66 #include <arpa/ftp.h> 67 #include <arpa/inet.h> 68 #include <arpa/telnet.h> 69 70 #include <ctype.h> 71 #include <dirent.h> 72 #include <err.h> 73 #include <errno.h> 74 #include <fcntl.h> 75 #include <glob.h> 76 #include <limits.h> 77 #include <netdb.h> 78 #include <pwd.h> 79 #include <grp.h> 80 #include <setjmp.h> 81 #include <signal.h> 82 #include <stdio.h> 83 #include <stdlib.h> 84 #include <string.h> 85 #include <syslog.h> 86 #include <time.h> 87 #include <unistd.h> 88 #include <libutil.h> 89 #ifdef LOGIN_CAP 90 #include <login_cap.h> 91 #endif 92 93 #ifdef SKEY 94 #include <skey.h> 95 #endif 96 97 #include "pathnames.h" 98 #include "extern.h" 99 100 #if __STDC__ 101 #include <stdarg.h> 102 #else 103 #include <varargs.h> 104 #endif 105 106 #ifdef INTERNAL_LS 107 static char version[] = "Version 6.00LS"; 108 #undef main 109 #else 110 static char version[] = "Version 6.00"; 111 #endif 112 113 extern off_t restart_point; 114 extern char cbuf[]; 115 116 struct sockaddr_in server_addr; 117 struct sockaddr_in ctrl_addr; 118 struct sockaddr_in data_source; 119 struct sockaddr_in data_dest; 120 struct sockaddr_in his_addr; 121 struct sockaddr_in pasv_addr; 122 123 int daemon_mode; 124 int data; 125 jmp_buf errcatch, urgcatch; 126 int logged_in; 127 struct passwd *pw; 128 int debug; 129 int timeout = 900; /* timeout after 15 minutes of inactivity */ 130 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 131 int logging; 132 int restricted_data_ports = 1; 133 int paranoid = 1; /* be extra careful about security */ 134 int anon_only = 0; /* Only anonymous ftp allowed */ 135 int guest; 136 int dochroot; 137 int stats; 138 int statfd = -1; 139 int type; 140 int form; 141 int stru; /* avoid C keyword */ 142 int mode; 143 int usedefault = 1; /* for data transfers */ 144 int pdata = -1; /* for passive mode */ 145 sig_atomic_t transflag; 146 off_t file_size; 147 off_t byte_count; 148 #if !defined(CMASK) || CMASK == 0 149 #undef CMASK 150 #define CMASK 027 151 #endif 152 int defumask = CMASK; /* default umask value */ 153 char tmpline[7]; 154 char *hostname; 155 #ifdef VIRTUAL_HOSTING 156 char *ftpuser; 157 158 static struct ftphost { 159 struct ftphost *next; 160 struct in_addr hostaddr; 161 char *hostname; 162 char *anonuser; 163 char *statfile; 164 char *welcome; 165 char *loginmsg; 166 } *thishost, *firsthost; 167 168 #endif 169 char remotehost[MAXHOSTNAMELEN]; 170 char *ident = NULL; 171 172 static char ttyline[20]; 173 char *tty = ttyline; /* for klogin */ 174 175 #ifdef KERBEROS 176 int klogin __P((struct passwd *, char *, char *, char *)); 177 #endif 178 179 struct in_addr bind_address; 180 char *pid_file = NULL; 181 182 #if defined(KERBEROS) 183 int notickets = 1; 184 int noticketsdontcomplain = 1; 185 char *krbtkfile_env = NULL; 186 #endif 187 188 /* 189 * Timeout intervals for retrying connections 190 * to hosts that don't accept PORT cmds. This 191 * is a kludge, but given the problems with TCP... 192 */ 193 #define SWAITMAX 90 /* wait at most 90 seconds */ 194 #define SWAITINT 5 /* interval between retries */ 195 196 int swaitmax = SWAITMAX; 197 int swaitint = SWAITINT; 198 199 #ifdef SETPROCTITLE 200 #ifdef OLD_SETPROCTITLE 201 char **Argv = NULL; /* pointer to argument vector */ 202 char *LastArgv = NULL; /* end of argv */ 203 #endif /* OLD_SETPROCTITLE */ 204 char proctitle[LINE_MAX]; /* initial part of title */ 205 #endif /* SETPROCTITLE */ 206 207 #ifdef SKEY 208 int pwok = 0; 209 char addr_string[20]; /* XXX */ 210 #endif 211 212 #define LOGCMD(cmd, file) \ 213 if (logging > 1) \ 214 syslog(LOG_INFO,"%s %s%s", cmd, \ 215 *(file) == '/' ? "" : curdir(), file); 216 #define LOGCMD2(cmd, file1, file2) \ 217 if (logging > 1) \ 218 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ 219 *(file1) == '/' ? "" : curdir(), file1, \ 220 *(file2) == '/' ? "" : curdir(), file2); 221 #define LOGBYTES(cmd, file, cnt) \ 222 if (logging > 1) { \ 223 if (cnt == (off_t)-1) \ 224 syslog(LOG_INFO,"%s %s%s", cmd, \ 225 *(file) == '/' ? "" : curdir(), file); \ 226 else \ 227 syslog(LOG_INFO, "%s %s%s = %qd bytes", \ 228 cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \ 229 } 230 231 #ifdef VIRTUAL_HOSTING 232 static void inithosts __P((void)); 233 static void selecthost __P((struct in_addr *)); 234 #endif 235 static void ack __P((char *)); 236 static void myoob __P((int)); 237 static int checkuser __P((char *, char *)); 238 static FILE *dataconn __P((char *, off_t, char *)); 239 static void dolog __P((struct sockaddr_in *)); 240 static char *curdir __P((void)); 241 static void end_login __P((void)); 242 static FILE *getdatasock __P((char *)); 243 static char *gunique __P((char *)); 244 static void lostconn __P((int)); 245 static int receive_data __P((FILE *, FILE *)); 246 static void send_data __P((FILE *, FILE *, off_t, off_t, int)); 247 static struct passwd * 248 sgetpwnam __P((char *)); 249 static char *sgetsave __P((char *)); 250 static void reapchild __P((int)); 251 static void logxfer __P((char *, long, long)); 252 253 static char * 254 curdir() 255 { 256 static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ 257 258 if (getcwd(path, sizeof(path)-2) == NULL) 259 return (""); 260 if (path[1] != '\0') /* special case for root dir. */ 261 strcat(path, "/"); 262 /* For guest account, skip / since it's chrooted */ 263 return (guest ? path+1 : path); 264 } 265 266 int 267 main(argc, argv, envp) 268 int argc; 269 char *argv[]; 270 char **envp; 271 { 272 int addrlen, ch, on = 1, tos; 273 char *cp, line[LINE_MAX]; 274 FILE *fd; 275 276 tzset(); /* in case no timezone database in ~ftp */ 277 278 #ifdef OLD_SETPROCTITLE 279 /* 280 * Save start and extent of argv for setproctitle. 281 */ 282 Argv = argv; 283 while (*envp) 284 envp++; 285 LastArgv = envp[-1] + strlen(envp[-1]); 286 #endif /* OLD_SETPROCTITLE */ 287 288 289 bind_address.s_addr = htonl(INADDR_ANY); 290 while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:")) != -1) { 291 switch (ch) { 292 case 'D': 293 daemon_mode++; 294 break; 295 296 case 'd': 297 debug++; 298 break; 299 300 case 'l': 301 logging++; /* > 1 == extra logging */ 302 break; 303 304 case 'R': 305 paranoid = 0; 306 break; 307 308 case 'S': 309 stats++; 310 break; 311 312 case 'T': 313 maxtimeout = atoi(optarg); 314 if (timeout > maxtimeout) 315 timeout = maxtimeout; 316 break; 317 318 case 't': 319 timeout = atoi(optarg); 320 if (maxtimeout < timeout) 321 maxtimeout = timeout; 322 break; 323 324 case 'U': 325 restricted_data_ports = 0; 326 break; 327 328 case 'a': 329 if (!inet_aton(optarg, &bind_address)) 330 errx(1, "invalid address for -a"); 331 break; 332 333 case 'p': 334 pid_file = optarg; 335 break; 336 337 case 'u': 338 { 339 long val = 0; 340 341 val = strtol(optarg, &optarg, 8); 342 if (*optarg != '\0' || val < 0) 343 warnx("bad value for -u"); 344 else 345 defumask = val; 346 break; 347 } 348 case 'A': 349 anon_only = 1; 350 break; 351 352 case 'v': 353 debug = 1; 354 break; 355 356 default: 357 warnx("unknown flag -%c ignored", optopt); 358 break; 359 } 360 } 361 362 #ifdef VIRTUAL_HOSTING 363 inithosts(); 364 #endif 365 (void) freopen(_PATH_DEVNULL, "w", stderr); 366 367 /* 368 * LOG_NDELAY sets up the logging connection immediately, 369 * necessary for anonymous ftp's that chroot and can't do it later. 370 */ 371 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 372 373 if (daemon_mode) { 374 int ctl_sock, fd; 375 struct servent *sv; 376 377 /* 378 * Detach from parent. 379 */ 380 if (daemon(1, 1) < 0) { 381 syslog(LOG_ERR, "failed to become a daemon"); 382 exit(1); 383 } 384 (void) signal(SIGCHLD, reapchild); 385 /* 386 * Get port number for ftp/tcp. 387 */ 388 sv = getservbyname("ftp", "tcp"); 389 if (sv == NULL) { 390 syslog(LOG_ERR, "getservbyname for ftp failed"); 391 exit(1); 392 } 393 /* 394 * Open a socket, bind it to the FTP port, and start 395 * listening. 396 */ 397 ctl_sock = socket(AF_INET, SOCK_STREAM, 0); 398 if (ctl_sock < 0) { 399 syslog(LOG_ERR, "control socket: %m"); 400 exit(1); 401 } 402 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, 403 (char *)&on, sizeof(on)) < 0) 404 syslog(LOG_ERR, "control setsockopt: %m");; 405 server_addr.sin_family = AF_INET; 406 server_addr.sin_addr = bind_address; 407 server_addr.sin_port = sv->s_port; 408 if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) { 409 syslog(LOG_ERR, "control bind: %m"); 410 exit(1); 411 } 412 if (listen(ctl_sock, 32) < 0) { 413 syslog(LOG_ERR, "control listen: %m"); 414 exit(1); 415 } 416 /* 417 * Atomically write process ID 418 */ 419 if (pid_file) 420 { 421 int fd; 422 char buf[20]; 423 424 fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC 425 | O_NONBLOCK | O_EXLOCK, 0644); 426 if (fd < 0) 427 if (errno == EAGAIN) 428 errx(1, "%s: file locked", pid_file); 429 else 430 err(1, "%s", pid_file); 431 snprintf(buf, sizeof(buf), 432 "%lu\n", (unsigned long) getpid()); 433 if (write(fd, buf, strlen(buf)) < 0) 434 err(1, "%s: write", pid_file); 435 /* Leave the pid file open and locked */ 436 } 437 /* 438 * Loop forever accepting connection requests and forking off 439 * children to handle them. 440 */ 441 while (1) { 442 addrlen = sizeof(his_addr); 443 fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen); 444 if (fork() == 0) { 445 /* child */ 446 (void) dup2(fd, 0); 447 (void) dup2(fd, 1); 448 close(ctl_sock); 449 break; 450 } 451 close(fd); 452 } 453 } else { 454 addrlen = sizeof(his_addr); 455 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 456 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 457 exit(1); 458 } 459 } 460 461 (void) signal(SIGCHLD, SIG_IGN); 462 (void) signal(SIGPIPE, lostconn); 463 if ((int)signal(SIGURG, myoob) < 0) 464 syslog(LOG_ERR, "signal: %m"); 465 466 #ifdef SKEY 467 strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string)); 468 #endif 469 addrlen = sizeof(ctrl_addr); 470 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 471 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 472 exit(1); 473 } 474 #ifdef VIRTUAL_HOSTING 475 /* select our identity from virtual host table */ 476 selecthost(&ctrl_addr.sin_addr); 477 #endif 478 #ifdef IP_TOS 479 tos = IPTOS_LOWDELAY; 480 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 481 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 482 #endif 483 data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); 484 485 /* set this here so klogin can use it... */ 486 (void)sprintf(ttyline, "ftp%d", getpid()); 487 488 /* Try to handle urgent data inline */ 489 #ifdef SO_OOBINLINE 490 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) 491 syslog(LOG_ERR, "setsockopt: %m"); 492 #endif 493 494 #ifdef F_SETOWN 495 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 496 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 497 #endif 498 dolog(&his_addr); 499 /* 500 * Set up default state 501 */ 502 data = -1; 503 type = TYPE_A; 504 form = FORM_N; 505 stru = STRU_F; 506 mode = MODE_S; 507 tmpline[0] = '\0'; 508 509 /* If logins are disabled, print out the message. */ 510 if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { 511 while (fgets(line, sizeof(line), fd) != NULL) { 512 if ((cp = strchr(line, '\n')) != NULL) 513 *cp = '\0'; 514 lreply(530, "%s", line); 515 } 516 (void) fflush(stdout); 517 (void) fclose(fd); 518 reply(530, "System not available."); 519 exit(0); 520 } 521 #ifdef VIRTUAL_HOSTING 522 if ((fd = fopen(thishost->welcome, "r")) != NULL) { 523 #else 524 if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { 525 #endif 526 while (fgets(line, sizeof(line), fd) != NULL) { 527 if ((cp = strchr(line, '\n')) != NULL) 528 *cp = '\0'; 529 lreply(220, "%s", line); 530 } 531 (void) fflush(stdout); 532 (void) fclose(fd); 533 /* reply(220,) must follow */ 534 } 535 #ifndef VIRTUAL_HOSTING 536 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 537 fatal("Ran out of memory."); 538 (void) gethostname(hostname, MAXHOSTNAMELEN); 539 #endif 540 reply(220, "%s FTP server (%s) ready.", hostname, version); 541 (void) setjmp(errcatch); 542 for (;;) 543 (void) yyparse(); 544 /* NOTREACHED */ 545 } 546 547 static void 548 lostconn(signo) 549 int signo; 550 { 551 552 if (debug) 553 syslog(LOG_DEBUG, "lost connection"); 554 dologout(-1); 555 } 556 557 #ifdef VIRTUAL_HOSTING 558 /* 559 * read in virtual host tables (if they exist) 560 */ 561 562 static void 563 inithosts() 564 { 565 FILE *fp; 566 char *cp; 567 struct hostent *hp; 568 struct ftphost *hrp, *lhrp; 569 char line[1024]; 570 571 /* 572 * Fill in the default host information 573 */ 574 if (gethostname(line, sizeof(line)) < 0) 575 line[0] = '\0'; 576 if ((hrp = malloc(sizeof(struct ftphost))) == NULL || 577 (hrp->hostname = strdup(line)) == NULL) 578 fatal("Ran out of memory."); 579 memset(&hrp->hostaddr, 0, sizeof hrp->hostaddr); 580 if ((hp = gethostbyname(hrp->hostname)) != NULL) 581 (void) memcpy(&hrp->hostaddr, 582 hp->h_addr_list[0], 583 sizeof(hrp->hostaddr)); 584 hrp->statfile = _PATH_FTPDSTATFILE; 585 hrp->welcome = _PATH_FTPWELCOME; 586 hrp->loginmsg = _PATH_FTPLOGINMESG; 587 hrp->anonuser = "ftp"; 588 hrp->next = NULL; 589 thishost = firsthost = lhrp = hrp; 590 if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) { 591 while (fgets(line, sizeof(line), fp) != NULL) { 592 int i; 593 594 if ((cp = strchr(line, '\n')) == NULL) { 595 /* ignore long lines */ 596 while (fgets(line, sizeof(line), fp) != NULL && 597 strchr(line, '\n') == NULL) 598 ; 599 continue; 600 } 601 *cp = '\0'; 602 cp = strtok(line, " \t"); 603 /* skip comments and empty lines */ 604 if (cp == NULL || line[0] == '#') 605 continue; 606 /* first, try a standard gethostbyname() */ 607 if ((hp = gethostbyname(cp)) == NULL) 608 continue; 609 for (hrp = firsthost; hrp != NULL; hrp = hrp->next) { 610 if (memcmp(&hrp->hostaddr, 611 hp->h_addr_list[0], 612 sizeof(hrp->hostaddr)) == 0) 613 break; 614 } 615 if (hrp == NULL) { 616 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 617 continue; 618 /* defaults */ 619 hrp->statfile = _PATH_FTPDSTATFILE; 620 hrp->welcome = _PATH_FTPWELCOME; 621 hrp->loginmsg = _PATH_FTPLOGINMESG; 622 hrp->anonuser = "ftp"; 623 hrp->next = NULL; 624 lhrp->next = hrp; 625 lhrp = hrp; 626 } 627 (void) memcpy(&hrp->hostaddr, 628 hp->h_addr_list[0], 629 sizeof(hrp->hostaddr)); 630 /* 631 * determine hostname to use. 632 * force defined name if it is a valid alias 633 * otherwise fallback to primary hostname 634 */ 635 if ((hp = gethostbyaddr((char*)&hrp->hostaddr, 636 sizeof(hrp->hostaddr), 637 AF_INET)) != NULL) { 638 if (strcmp(cp, hp->h_name) != 0) { 639 if (hp->h_aliases == NULL) 640 cp = hp->h_name; 641 else { 642 i = 0; 643 while (hp->h_aliases[i] && 644 strcmp(cp, hp->h_aliases[i]) != 0) 645 ++i; 646 if (hp->h_aliases[i] == NULL) 647 cp = hp->h_name; 648 } 649 } 650 } 651 hrp->hostname = strdup(cp); 652 /* ok, now we now peel off the rest */ 653 i = 0; 654 while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) { 655 if (*cp != '-' && (cp = strdup(cp)) != NULL) { 656 switch (i) { 657 case 0: /* anon user permissions */ 658 hrp->anonuser = cp; 659 break; 660 case 1: /* statistics file */ 661 hrp->statfile = cp; 662 break; 663 case 2: /* welcome message */ 664 hrp->welcome = cp; 665 break; 666 case 3: /* login message */ 667 hrp->loginmsg = cp; 668 break; 669 } 670 } 671 ++i; 672 } 673 } 674 (void) fclose(fp); 675 } 676 } 677 678 static void 679 selecthost(a) 680 struct in_addr *a; 681 { 682 struct ftphost *hrp; 683 684 hrp = thishost = firsthost; /* default */ 685 while (hrp != NULL) { 686 if (memcmp(a, &hrp->hostaddr, sizeof(hrp->hostaddr)) == 0) { 687 thishost = hrp; 688 break; 689 } 690 hrp = hrp->next; 691 } 692 /* setup static variables as appropriate */ 693 hostname = thishost->hostname; 694 ftpuser = thishost->anonuser; 695 } 696 #endif 697 698 /* 699 * Helper function for sgetpwnam(). 700 */ 701 static char * 702 sgetsave(s) 703 char *s; 704 { 705 char *new = malloc((unsigned) strlen(s) + 1); 706 707 if (new == NULL) { 708 perror_reply(421, "Local resource failure: malloc"); 709 dologout(1); 710 /* NOTREACHED */ 711 } 712 (void) strcpy(new, s); 713 return (new); 714 } 715 716 /* 717 * Save the result of a getpwnam. Used for USER command, since 718 * the data returned must not be clobbered by any other command 719 * (e.g., globbing). 720 */ 721 static struct passwd * 722 sgetpwnam(name) 723 char *name; 724 { 725 static struct passwd save; 726 struct passwd *p; 727 728 if ((p = getpwnam(name)) == NULL) 729 return (p); 730 if (save.pw_name) { 731 free(save.pw_name); 732 free(save.pw_passwd); 733 free(save.pw_gecos); 734 free(save.pw_dir); 735 free(save.pw_shell); 736 } 737 save = *p; 738 save.pw_name = sgetsave(p->pw_name); 739 save.pw_passwd = sgetsave(p->pw_passwd); 740 save.pw_gecos = sgetsave(p->pw_gecos); 741 save.pw_dir = sgetsave(p->pw_dir); 742 save.pw_shell = sgetsave(p->pw_shell); 743 return (&save); 744 } 745 746 static int login_attempts; /* number of failed login attempts */ 747 static int askpasswd; /* had user command, ask for passwd */ 748 static char curname[10]; /* current USER name */ 749 750 /* 751 * USER command. 752 * Sets global passwd pointer pw if named account exists and is acceptable; 753 * sets askpasswd if a PASS command is expected. If logged in previously, 754 * need to reset state. If name is "ftp" or "anonymous", the name is not in 755 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 756 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 757 * requesting login privileges. Disallow anyone who does not have a standard 758 * shell as returned by getusershell(). Disallow anyone mentioned in the file 759 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 760 */ 761 void 762 user(name) 763 char *name; 764 { 765 char *cp, *shell; 766 767 if (logged_in) { 768 if (guest) { 769 reply(530, "Can't change user from guest login."); 770 return; 771 } else if (dochroot) { 772 reply(530, "Can't change user from chroot user."); 773 return; 774 } 775 end_login(); 776 } 777 778 guest = 0; 779 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 780 if (checkuser(_PATH_FTPUSERS, "ftp") || 781 checkuser(_PATH_FTPUSERS, "anonymous")) 782 reply(530, "User %s access denied.", name); 783 #ifdef VIRTUAL_HOSTING 784 else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) { 785 #else 786 else if ((pw = sgetpwnam("ftp")) != NULL) { 787 #endif 788 guest = 1; 789 askpasswd = 1; 790 reply(331, 791 "Guest login ok, send your email address as password."); 792 } else 793 reply(530, "User %s unknown.", name); 794 if (!askpasswd && logging) 795 syslog(LOG_NOTICE, 796 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); 797 return; 798 } 799 if (anon_only != 0) { 800 reply(530, "Sorry, only anonymous ftp allowed."); 801 return; 802 } 803 804 if ((pw = sgetpwnam(name))) { 805 if ((shell = pw->pw_shell) == NULL || *shell == 0) 806 shell = _PATH_BSHELL; 807 while ((cp = getusershell()) != NULL) 808 if (strcmp(cp, shell) == 0) 809 break; 810 endusershell(); 811 812 if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) { 813 reply(530, "User %s access denied.", name); 814 if (logging) 815 syslog(LOG_NOTICE, 816 "FTP LOGIN REFUSED FROM %s, %s", 817 remotehost, name); 818 pw = (struct passwd *) NULL; 819 return; 820 } 821 } 822 if (logging) 823 strncpy(curname, name, sizeof(curname)-1); 824 #ifdef SKEY 825 pwok = skeyaccess(name, NULL, remotehost, addr_string); 826 reply(331, "%s", skey_challenge(name, pw, pwok)); 827 #else 828 reply(331, "Password required for %s.", name); 829 #endif 830 askpasswd = 1; 831 /* 832 * Delay before reading passwd after first failed 833 * attempt to slow down passwd-guessing programs. 834 */ 835 if (login_attempts) 836 sleep((unsigned) login_attempts); 837 } 838 839 /* 840 * Check if a user is in the file "fname" 841 */ 842 static int 843 checkuser(fname, name) 844 char *fname; 845 char *name; 846 { 847 FILE *fd; 848 int found = 0; 849 char *p, line[BUFSIZ]; 850 851 if ((fd = fopen(fname, "r")) != NULL) { 852 while (!found && fgets(line, sizeof(line), fd) != NULL) 853 if ((p = strchr(line, '\n')) != NULL) { 854 *p = '\0'; 855 if (line[0] == '#') 856 continue; 857 /* 858 * if first chr is '@', check group membership 859 */ 860 if (line[0] == '@') { 861 int i = 0; 862 struct group *grp; 863 864 if ((grp = getgrnam(line+1)) == NULL) 865 continue; 866 while (!found && grp->gr_mem[i]) 867 found = strcmp(name, 868 grp->gr_mem[i++]) 869 == 0; 870 } 871 /* 872 * Otherwise, just check for username match 873 */ 874 else 875 found = strcmp(line, name) == 0; 876 } 877 (void) fclose(fd); 878 } 879 return (found); 880 } 881 882 /* 883 * Terminate login as previous user, if any, resetting state; 884 * used when USER command is given or login fails. 885 */ 886 static void 887 end_login() 888 { 889 890 (void) seteuid((uid_t)0); 891 if (logged_in) 892 ftpd_logwtmp(ttyline, "", ""); 893 pw = NULL; 894 #ifdef LOGIN_CAP 895 setusercontext(NULL, getpwuid(0), (uid_t)0, 896 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 897 #endif 898 logged_in = 0; 899 guest = 0; 900 dochroot = 0; 901 } 902 903 void 904 pass(passwd) 905 char *passwd; 906 { 907 int rval; 908 FILE *fd; 909 #ifdef LOGIN_CAP 910 login_cap_t *lc = NULL; 911 #endif 912 static char homedir[MAXPATHLEN]; 913 914 if (logged_in || askpasswd == 0) { 915 reply(503, "Login with USER first."); 916 return; 917 } 918 askpasswd = 0; 919 if (!guest) { /* "ftp" is only account allowed no password */ 920 if (pw == NULL) { 921 rval = 1; /* failure below */ 922 goto skip; 923 } 924 #if defined(KERBEROS) 925 rval = klogin(pw, "", hostname, passwd); 926 if (rval == 0) 927 goto skip; 928 #endif 929 #ifdef SKEY 930 rval = strcmp(skey_crypt(passwd, pw->pw_passwd, pw, pwok), 931 pw->pw_passwd); 932 pwok = 0; 933 #else 934 rval = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd); 935 #endif 936 /* The strcmp does not catch null passwords! */ 937 if (*pw->pw_passwd == '\0' || 938 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 939 rval = 1; /* failure */ 940 skip: 941 /* 942 * If rval == 1, the user failed the authentication check 943 * above. If rval == 0, either Kerberos or local authentication 944 * succeeded. 945 */ 946 if (rval) { 947 reply(530, "Login incorrect."); 948 if (logging) 949 syslog(LOG_NOTICE, 950 "FTP LOGIN FAILED FROM %s, %s", 951 remotehost, curname); 952 pw = NULL; 953 if (login_attempts++ >= 5) { 954 syslog(LOG_NOTICE, 955 "repeated login failures from %s", 956 remotehost); 957 exit(0); 958 } 959 return; 960 } 961 } 962 login_attempts = 0; /* this time successful */ 963 if (setegid((gid_t)pw->pw_gid) < 0) { 964 reply(550, "Can't set gid."); 965 return; 966 } 967 /* May be overridden by login.conf */ 968 (void) umask(defumask); 969 #ifdef LOGIN_CAP 970 if ((lc = login_getpwclass(pw)) != NULL) { 971 char remote_ip[MAXHOSTNAMELEN]; 972 973 strncpy(remote_ip, inet_ntoa(his_addr.sin_addr), 974 sizeof(remote_ip) - 1); 975 remote_ip[sizeof(remote_ip) - 1] = 0; 976 if (!auth_hostok(lc, remotehost, remote_ip)) { 977 syslog(LOG_INFO|LOG_AUTH, 978 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 979 pw->pw_name); 980 reply(530, "Permission denied.\n"); 981 pw = NULL; 982 return; 983 } 984 if (!auth_timeok(lc, time(NULL))) { 985 reply(530, "Login not available right now.\n"); 986 pw = NULL; 987 return; 988 } 989 } 990 setusercontext(lc, pw, (uid_t)0, 991 LOGIN_SETGROUP|LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 992 #else 993 (void) initgroups(pw->pw_name, pw->pw_gid); 994 #endif 995 996 /* open wtmp before chroot */ 997 ftpd_logwtmp(ttyline, pw->pw_name, remotehost); 998 logged_in = 1; 999 1000 if (guest && stats && statfd < 0) 1001 #ifdef VIRTUAL_HOSTING 1002 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0) 1003 #else 1004 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 1005 #endif 1006 stats = 0; 1007 1008 dochroot = 1009 #ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1010 login_getcapbool(lc, "ftp-chroot", 0) || 1011 #endif 1012 checkuser(_PATH_FTPCHROOT, pw->pw_name); 1013 if (guest) { 1014 /* 1015 * We MUST do a chdir() after the chroot. Otherwise 1016 * the old current directory will be accessible as "." 1017 * outside the new root! 1018 */ 1019 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1020 reply(550, "Can't set guest privileges."); 1021 goto bad; 1022 } 1023 } else if (dochroot) { 1024 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1025 reply(550, "Can't change root."); 1026 goto bad; 1027 } 1028 } else if (chdir(pw->pw_dir) < 0) { 1029 if (chdir("/") < 0) { 1030 reply(530, "User %s: can't change directory to %s.", 1031 pw->pw_name, pw->pw_dir); 1032 goto bad; 1033 } else 1034 lreply(230, "No directory! Logging in with home=/"); 1035 } 1036 if (seteuid((uid_t)pw->pw_uid) < 0) { 1037 reply(550, "Can't set uid."); 1038 goto bad; 1039 } 1040 1041 /* 1042 * Set home directory so that use of ~ (tilde) works correctly. 1043 */ 1044 if (getcwd(homedir, MAXPATHLEN) != NULL) 1045 setenv("HOME", homedir, 1); 1046 1047 /* 1048 * Display a login message, if it exists. 1049 * N.B. reply(230,) must follow the message. 1050 */ 1051 #ifdef VIRTUAL_HOSTING 1052 if ((fd = fopen(thishost->loginmsg, "r")) != NULL) { 1053 #else 1054 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 1055 #endif 1056 char *cp, line[LINE_MAX]; 1057 1058 while (fgets(line, sizeof(line), fd) != NULL) { 1059 if ((cp = strchr(line, '\n')) != NULL) 1060 *cp = '\0'; 1061 lreply(230, "%s", line); 1062 } 1063 (void) fflush(stdout); 1064 (void) fclose(fd); 1065 } 1066 if (guest) { 1067 if (ident != NULL) 1068 free(ident); 1069 ident = strdup(passwd); 1070 if (ident == NULL) 1071 fatal("Ran out of memory."); 1072 1073 reply(230, "Guest login ok, access restrictions apply."); 1074 #ifdef SETPROCTITLE 1075 #ifdef VIRTUAL_HOSTING 1076 if (thishost != firsthost) 1077 snprintf(proctitle, sizeof(proctitle), 1078 "%s: anonymous(%s)/%.*s", remotehost, hostname, 1079 sizeof(proctitle) - sizeof(remotehost) - 1080 sizeof(": anonymous/"), passwd); 1081 else 1082 #endif 1083 snprintf(proctitle, sizeof(proctitle), 1084 "%s: anonymous/%.*s", remotehost, 1085 sizeof(proctitle) - sizeof(remotehost) - 1086 sizeof(": anonymous/"), passwd); 1087 setproctitle("%s", proctitle); 1088 #endif /* SETPROCTITLE */ 1089 if (logging) 1090 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1091 remotehost, passwd); 1092 } else { 1093 if (dochroot) 1094 reply(230, "User %s logged in, access restrictions apply.", 1095 pw->pw_name); 1096 else 1097 reply(230, "User %s logged in.", pw->pw_name); 1098 1099 #ifdef SETPROCTITLE 1100 snprintf(proctitle, sizeof(proctitle), 1101 "%s: %s", remotehost, pw->pw_name); 1102 setproctitle("%s", proctitle); 1103 #endif /* SETPROCTITLE */ 1104 if (logging) 1105 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1106 remotehost, pw->pw_name); 1107 } 1108 #ifdef LOGIN_CAP 1109 login_close(lc); 1110 #endif 1111 return; 1112 bad: 1113 /* Forget all about it... */ 1114 #ifdef LOGIN_CAP 1115 login_close(lc); 1116 #endif 1117 end_login(); 1118 } 1119 1120 void 1121 retrieve(cmd, name) 1122 char *cmd, *name; 1123 { 1124 FILE *fin, *dout; 1125 struct stat st; 1126 int (*closefunc) __P((FILE *)); 1127 long start; 1128 1129 if (cmd == 0) { 1130 fin = fopen(name, "r"), closefunc = fclose; 1131 st.st_size = 0; 1132 } else { 1133 char line[BUFSIZ]; 1134 1135 (void) sprintf(line, cmd, name), name = line; 1136 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1137 st.st_size = -1; 1138 st.st_blksize = BUFSIZ; 1139 } 1140 if (fin == NULL) { 1141 if (errno != 0) { 1142 perror_reply(550, name); 1143 if (cmd == 0) { 1144 LOGCMD("get", name); 1145 } 1146 } 1147 return; 1148 } 1149 byte_count = -1; 1150 if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { 1151 reply(550, "%s: not a plain file.", name); 1152 goto done; 1153 } 1154 if (restart_point) { 1155 if (type == TYPE_A) { 1156 off_t i, n; 1157 int c; 1158 1159 n = restart_point; 1160 i = 0; 1161 while (i++ < n) { 1162 if ((c=getc(fin)) == EOF) { 1163 perror_reply(550, name); 1164 goto done; 1165 } 1166 if (c == '\n') 1167 i++; 1168 } 1169 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1170 perror_reply(550, name); 1171 goto done; 1172 } 1173 } 1174 dout = dataconn(name, st.st_size, "w"); 1175 if (dout == NULL) 1176 goto done; 1177 time(&start); 1178 send_data(fin, dout, st.st_blksize, st.st_size, 1179 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1180 if (cmd == 0 && guest && stats) 1181 logxfer(name, st.st_size, start); 1182 (void) fclose(dout); 1183 data = -1; 1184 pdata = -1; 1185 done: 1186 if (cmd == 0) 1187 LOGBYTES("get", name, byte_count); 1188 (*closefunc)(fin); 1189 } 1190 1191 void 1192 store(name, mode, unique) 1193 char *name, *mode; 1194 int unique; 1195 { 1196 FILE *fout, *din; 1197 struct stat st; 1198 int (*closefunc) __P((FILE *)); 1199 1200 if ((unique || guest) && stat(name, &st) == 0 && 1201 (name = gunique(name)) == NULL) { 1202 LOGCMD(*mode == 'w' ? "put" : "append", name); 1203 return; 1204 } 1205 1206 if (restart_point) 1207 mode = "r+"; 1208 fout = fopen(name, mode); 1209 closefunc = fclose; 1210 if (fout == NULL) { 1211 perror_reply(553, name); 1212 LOGCMD(*mode == 'w' ? "put" : "append", name); 1213 return; 1214 } 1215 byte_count = -1; 1216 if (restart_point) { 1217 if (type == TYPE_A) { 1218 off_t i, n; 1219 int c; 1220 1221 n = restart_point; 1222 i = 0; 1223 while (i++ < n) { 1224 if ((c=getc(fout)) == EOF) { 1225 perror_reply(550, name); 1226 goto done; 1227 } 1228 if (c == '\n') 1229 i++; 1230 } 1231 /* 1232 * We must do this seek to "current" position 1233 * because we are changing from reading to 1234 * writing. 1235 */ 1236 if (fseek(fout, 0L, L_INCR) < 0) { 1237 perror_reply(550, name); 1238 goto done; 1239 } 1240 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1241 perror_reply(550, name); 1242 goto done; 1243 } 1244 } 1245 din = dataconn(name, (off_t)-1, "r"); 1246 if (din == NULL) 1247 goto done; 1248 if (receive_data(din, fout) == 0) { 1249 if (unique) 1250 reply(226, "Transfer complete (unique file name:%s).", 1251 name); 1252 else 1253 reply(226, "Transfer complete."); 1254 } 1255 (void) fclose(din); 1256 data = -1; 1257 pdata = -1; 1258 done: 1259 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); 1260 (*closefunc)(fout); 1261 } 1262 1263 static FILE * 1264 getdatasock(mode) 1265 char *mode; 1266 { 1267 int on = 1, s, t, tries; 1268 1269 if (data >= 0) 1270 return (fdopen(data, mode)); 1271 (void) seteuid((uid_t)0); 1272 s = socket(AF_INET, SOCK_STREAM, 0); 1273 if (s < 0) 1274 goto bad; 1275 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 1276 (char *) &on, sizeof(on)) < 0) 1277 goto bad; 1278 /* anchor socket to avoid multi-homing problems */ 1279 data_source.sin_len = sizeof(struct sockaddr_in); 1280 data_source.sin_family = AF_INET; 1281 data_source.sin_addr = ctrl_addr.sin_addr; 1282 for (tries = 1; ; tries++) { 1283 if (bind(s, (struct sockaddr *)&data_source, 1284 sizeof(data_source)) >= 0) 1285 break; 1286 if (errno != EADDRINUSE || tries > 10) 1287 goto bad; 1288 sleep(tries); 1289 } 1290 (void) seteuid((uid_t)pw->pw_uid); 1291 #ifdef IP_TOS 1292 on = IPTOS_THROUGHPUT; 1293 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1294 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1295 #endif 1296 #ifdef TCP_NOPUSH 1297 /* 1298 * Turn off push flag to keep sender TCP from sending short packets 1299 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1300 * to set the send buffer size as well, but that may not be desirable 1301 * in heavy-load situations. 1302 */ 1303 on = 1; 1304 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) 1305 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 1306 #endif 1307 #ifdef SO_SNDBUF 1308 on = 65536; 1309 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) 1310 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); 1311 #endif 1312 1313 return (fdopen(s, mode)); 1314 bad: 1315 /* Return the real value of errno (close may change it) */ 1316 t = errno; 1317 (void) seteuid((uid_t)pw->pw_uid); 1318 (void) close(s); 1319 errno = t; 1320 return (NULL); 1321 } 1322 1323 static FILE * 1324 dataconn(name, size, mode) 1325 char *name; 1326 off_t size; 1327 char *mode; 1328 { 1329 char sizebuf[32]; 1330 FILE *file; 1331 int retry = 0, tos; 1332 1333 file_size = size; 1334 byte_count = 0; 1335 if (size != (off_t) -1) 1336 (void) sprintf(sizebuf, " (%qd bytes)", size); 1337 else 1338 (void) strcpy(sizebuf, ""); 1339 if (pdata >= 0) { 1340 struct sockaddr_in from; 1341 int s, fromlen = sizeof(from); 1342 struct timeval timeout; 1343 fd_set set; 1344 1345 FD_ZERO(&set); 1346 FD_SET(pdata, &set); 1347 1348 timeout.tv_usec = 0; 1349 timeout.tv_sec = 120; 1350 1351 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 || 1352 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) { 1353 reply(425, "Can't open data connection."); 1354 (void) close(pdata); 1355 pdata = -1; 1356 return (NULL); 1357 } 1358 (void) close(pdata); 1359 pdata = s; 1360 #ifdef IP_TOS 1361 tos = IPTOS_THROUGHPUT; 1362 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1363 sizeof(int)); 1364 #endif 1365 reply(150, "Opening %s mode data connection for '%s'%s.", 1366 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1367 return (fdopen(pdata, mode)); 1368 } 1369 if (data >= 0) { 1370 reply(125, "Using existing data connection for '%s'%s.", 1371 name, sizebuf); 1372 usedefault = 1; 1373 return (fdopen(data, mode)); 1374 } 1375 if (usedefault) 1376 data_dest = his_addr; 1377 usedefault = 1; 1378 file = getdatasock(mode); 1379 if (file == NULL) { 1380 reply(425, "Can't create data socket (%s,%d): %s.", 1381 inet_ntoa(data_source.sin_addr), 1382 ntohs(data_source.sin_port), strerror(errno)); 1383 return (NULL); 1384 } 1385 data = fileno(file); 1386 while (connect(data, (struct sockaddr *)&data_dest, 1387 sizeof(data_dest)) < 0) { 1388 if (errno == EADDRINUSE && retry < swaitmax) { 1389 sleep((unsigned) swaitint); 1390 retry += swaitint; 1391 continue; 1392 } 1393 perror_reply(425, "Can't build data connection"); 1394 (void) fclose(file); 1395 data = -1; 1396 return (NULL); 1397 } 1398 reply(150, "Opening %s mode data connection for '%s'%s.", 1399 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1400 return (file); 1401 } 1402 1403 /* 1404 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1405 * encapsulation of the data subject to Mode, Structure, and Type. 1406 * 1407 * NB: Form isn't handled. 1408 */ 1409 static void 1410 send_data(instr, outstr, blksize, filesize, isreg) 1411 FILE *instr, *outstr; 1412 off_t blksize; 1413 off_t filesize; 1414 int isreg; 1415 { 1416 int c, cnt, filefd, netfd; 1417 char *buf, *bp; 1418 size_t len; 1419 1420 transflag++; 1421 if (setjmp(urgcatch)) { 1422 transflag = 0; 1423 return; 1424 } 1425 switch (type) { 1426 1427 case TYPE_A: 1428 while ((c = getc(instr)) != EOF) { 1429 byte_count++; 1430 if (c == '\n') { 1431 if (ferror(outstr)) 1432 goto data_err; 1433 (void) putc('\r', outstr); 1434 } 1435 (void) putc(c, outstr); 1436 } 1437 fflush(outstr); 1438 transflag = 0; 1439 if (ferror(instr)) 1440 goto file_err; 1441 if (ferror(outstr)) 1442 goto data_err; 1443 reply(226, "Transfer complete."); 1444 return; 1445 1446 case TYPE_I: 1447 case TYPE_L: 1448 /* 1449 * isreg is only set if we are not doing restart and we 1450 * are sending a regular file 1451 */ 1452 netfd = fileno(outstr); 1453 filefd = fileno(instr); 1454 1455 if (isreg && filesize < (off_t)16 * 1024 * 1024) { 1456 buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, 1457 (off_t)0); 1458 if (buf == MAP_FAILED) { 1459 syslog(LOG_WARNING, "mmap(%lu): %m", 1460 (unsigned long)filesize); 1461 goto oldway; 1462 } 1463 bp = buf; 1464 len = filesize; 1465 do { 1466 cnt = write(netfd, bp, len); 1467 len -= cnt; 1468 bp += cnt; 1469 if (cnt > 0) byte_count += cnt; 1470 } while(cnt > 0 && len > 0); 1471 1472 transflag = 0; 1473 munmap(buf, (size_t)filesize); 1474 if (cnt < 0) 1475 goto data_err; 1476 reply(226, "Transfer complete."); 1477 return; 1478 } 1479 1480 oldway: 1481 if ((buf = malloc((u_int)blksize)) == NULL) { 1482 transflag = 0; 1483 perror_reply(451, "Local resource failure: malloc"); 1484 return; 1485 } 1486 1487 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 1488 write(netfd, buf, cnt) == cnt) 1489 byte_count += cnt; 1490 transflag = 0; 1491 (void)free(buf); 1492 if (cnt != 0) { 1493 if (cnt < 0) 1494 goto file_err; 1495 goto data_err; 1496 } 1497 reply(226, "Transfer complete."); 1498 return; 1499 default: 1500 transflag = 0; 1501 reply(550, "Unimplemented TYPE %d in send_data", type); 1502 return; 1503 } 1504 1505 data_err: 1506 transflag = 0; 1507 perror_reply(426, "Data connection"); 1508 return; 1509 1510 file_err: 1511 transflag = 0; 1512 perror_reply(551, "Error on input file"); 1513 } 1514 1515 /* 1516 * Transfer data from peer to "outstr" using the appropriate encapulation of 1517 * the data subject to Mode, Structure, and Type. 1518 * 1519 * N.B.: Form isn't handled. 1520 */ 1521 static int 1522 receive_data(instr, outstr) 1523 FILE *instr, *outstr; 1524 { 1525 int c; 1526 int cnt, bare_lfs; 1527 char buf[BUFSIZ]; 1528 1529 transflag++; 1530 if (setjmp(urgcatch)) { 1531 transflag = 0; 1532 return (-1); 1533 } 1534 1535 bare_lfs = 0; 1536 1537 switch (type) { 1538 1539 case TYPE_I: 1540 case TYPE_L: 1541 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 1542 if (write(fileno(outstr), buf, cnt) != cnt) 1543 goto file_err; 1544 byte_count += cnt; 1545 } 1546 if (cnt < 0) 1547 goto data_err; 1548 transflag = 0; 1549 return (0); 1550 1551 case TYPE_E: 1552 reply(553, "TYPE E not implemented."); 1553 transflag = 0; 1554 return (-1); 1555 1556 case TYPE_A: 1557 while ((c = getc(instr)) != EOF) { 1558 byte_count++; 1559 if (c == '\n') 1560 bare_lfs++; 1561 while (c == '\r') { 1562 if (ferror(outstr)) 1563 goto data_err; 1564 if ((c = getc(instr)) != '\n') { 1565 (void) putc ('\r', outstr); 1566 if (c == '\0' || c == EOF) 1567 goto contin2; 1568 } 1569 } 1570 (void) putc(c, outstr); 1571 contin2: ; 1572 } 1573 fflush(outstr); 1574 if (ferror(instr)) 1575 goto data_err; 1576 if (ferror(outstr)) 1577 goto file_err; 1578 transflag = 0; 1579 if (bare_lfs) { 1580 lreply(226, 1581 "WARNING! %d bare linefeeds received in ASCII mode", 1582 bare_lfs); 1583 (void)printf(" File may not have transferred correctly.\r\n"); 1584 } 1585 return (0); 1586 default: 1587 reply(550, "Unimplemented TYPE %d in receive_data", type); 1588 transflag = 0; 1589 return (-1); 1590 } 1591 1592 data_err: 1593 transflag = 0; 1594 perror_reply(426, "Data Connection"); 1595 return (-1); 1596 1597 file_err: 1598 transflag = 0; 1599 perror_reply(452, "Error writing file"); 1600 return (-1); 1601 } 1602 1603 void 1604 statfilecmd(filename) 1605 char *filename; 1606 { 1607 FILE *fin; 1608 int c; 1609 char line[LINE_MAX]; 1610 1611 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 1612 fin = ftpd_popen(line, "r"); 1613 lreply(211, "status of %s:", filename); 1614 while ((c = getc(fin)) != EOF) { 1615 if (c == '\n') { 1616 if (ferror(stdout)){ 1617 perror_reply(421, "control connection"); 1618 (void) ftpd_pclose(fin); 1619 dologout(1); 1620 /* NOTREACHED */ 1621 } 1622 if (ferror(fin)) { 1623 perror_reply(551, filename); 1624 (void) ftpd_pclose(fin); 1625 return; 1626 } 1627 (void) putc('\r', stdout); 1628 } 1629 (void) putc(c, stdout); 1630 } 1631 (void) ftpd_pclose(fin); 1632 reply(211, "End of Status"); 1633 } 1634 1635 void 1636 statcmd() 1637 { 1638 struct sockaddr_in *sin; 1639 u_char *a, *p; 1640 1641 lreply(211, "%s FTP server status:", hostname, version); 1642 printf(" %s\r\n", version); 1643 printf(" Connected to %s", remotehost); 1644 if (!isdigit(remotehost[0])) 1645 printf(" (%s)", inet_ntoa(his_addr.sin_addr)); 1646 printf("\r\n"); 1647 if (logged_in) { 1648 if (guest) 1649 printf(" Logged in anonymously\r\n"); 1650 else 1651 printf(" Logged in as %s\r\n", pw->pw_name); 1652 } else if (askpasswd) 1653 printf(" Waiting for password\r\n"); 1654 else 1655 printf(" Waiting for user name\r\n"); 1656 printf(" TYPE: %s", typenames[type]); 1657 if (type == TYPE_A || type == TYPE_E) 1658 printf(", FORM: %s", formnames[form]); 1659 if (type == TYPE_L) 1660 #if NBBY == 8 1661 printf(" %d", NBBY); 1662 #else 1663 printf(" %d", bytesize); /* need definition! */ 1664 #endif 1665 printf("; STRUcture: %s; transfer MODE: %s\r\n", 1666 strunames[stru], modenames[mode]); 1667 if (data != -1) 1668 printf(" Data connection open\r\n"); 1669 else if (pdata != -1) { 1670 printf(" in Passive mode"); 1671 sin = &pasv_addr; 1672 goto printaddr; 1673 } else if (usedefault == 0) { 1674 printf(" PORT"); 1675 sin = &data_dest; 1676 printaddr: 1677 a = (u_char *) &sin->sin_addr; 1678 p = (u_char *) &sin->sin_port; 1679 #define UC(b) (((int) b) & 0xff) 1680 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), 1681 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1682 #undef UC 1683 } else 1684 printf(" No data connection\r\n"); 1685 reply(211, "End of status"); 1686 } 1687 1688 void 1689 fatal(s) 1690 char *s; 1691 { 1692 1693 reply(451, "Error in server: %s\n", s); 1694 reply(221, "Closing connection due to server error."); 1695 dologout(0); 1696 /* NOTREACHED */ 1697 } 1698 1699 void 1700 #if __STDC__ 1701 reply(int n, const char *fmt, ...) 1702 #else 1703 reply(n, fmt, va_alist) 1704 int n; 1705 char *fmt; 1706 va_dcl 1707 #endif 1708 { 1709 va_list ap; 1710 #if __STDC__ 1711 va_start(ap, fmt); 1712 #else 1713 va_start(ap); 1714 #endif 1715 (void)printf("%d ", n); 1716 (void)vprintf(fmt, ap); 1717 (void)printf("\r\n"); 1718 (void)fflush(stdout); 1719 if (debug) { 1720 syslog(LOG_DEBUG, "<--- %d ", n); 1721 vsyslog(LOG_DEBUG, fmt, ap); 1722 } 1723 } 1724 1725 void 1726 #if __STDC__ 1727 lreply(int n, const char *fmt, ...) 1728 #else 1729 lreply(n, fmt, va_alist) 1730 int n; 1731 char *fmt; 1732 va_dcl 1733 #endif 1734 { 1735 va_list ap; 1736 #if __STDC__ 1737 va_start(ap, fmt); 1738 #else 1739 va_start(ap); 1740 #endif 1741 (void)printf("%d- ", n); 1742 (void)vprintf(fmt, ap); 1743 (void)printf("\r\n"); 1744 (void)fflush(stdout); 1745 if (debug) { 1746 syslog(LOG_DEBUG, "<--- %d- ", n); 1747 vsyslog(LOG_DEBUG, fmt, ap); 1748 } 1749 } 1750 1751 static void 1752 ack(s) 1753 char *s; 1754 { 1755 1756 reply(250, "%s command successful.", s); 1757 } 1758 1759 void 1760 nack(s) 1761 char *s; 1762 { 1763 1764 reply(502, "%s command not implemented.", s); 1765 } 1766 1767 /* ARGSUSED */ 1768 void 1769 yyerror(s) 1770 char *s; 1771 { 1772 char *cp; 1773 1774 if ((cp = strchr(cbuf,'\n'))) 1775 *cp = '\0'; 1776 reply(500, "'%s': command not understood.", cbuf); 1777 } 1778 1779 void 1780 delete(name) 1781 char *name; 1782 { 1783 struct stat st; 1784 1785 LOGCMD("delete", name); 1786 if (stat(name, &st) < 0) { 1787 perror_reply(550, name); 1788 return; 1789 } 1790 if ((st.st_mode&S_IFMT) == S_IFDIR) { 1791 if (rmdir(name) < 0) { 1792 perror_reply(550, name); 1793 return; 1794 } 1795 goto done; 1796 } 1797 if (unlink(name) < 0) { 1798 perror_reply(550, name); 1799 return; 1800 } 1801 done: 1802 ack("DELE"); 1803 } 1804 1805 void 1806 cwd(path) 1807 char *path; 1808 { 1809 1810 if (chdir(path) < 0) 1811 perror_reply(550, path); 1812 else 1813 ack("CWD"); 1814 } 1815 1816 void 1817 makedir(name) 1818 char *name; 1819 { 1820 1821 LOGCMD("mkdir", name); 1822 if (mkdir(name, 0777) < 0) 1823 perror_reply(550, name); 1824 else 1825 reply(257, "MKD command successful."); 1826 } 1827 1828 void 1829 removedir(name) 1830 char *name; 1831 { 1832 1833 LOGCMD("rmdir", name); 1834 if (rmdir(name) < 0) 1835 perror_reply(550, name); 1836 else 1837 ack("RMD"); 1838 } 1839 1840 void 1841 pwd() 1842 { 1843 char path[MAXPATHLEN + 1]; 1844 1845 if (getwd(path) == (char *)NULL) 1846 reply(550, "%s.", path); 1847 else 1848 reply(257, "\"%s\" is current directory.", path); 1849 } 1850 1851 char * 1852 renamefrom(name) 1853 char *name; 1854 { 1855 struct stat st; 1856 1857 if (stat(name, &st) < 0) { 1858 perror_reply(550, name); 1859 return ((char *)0); 1860 } 1861 reply(350, "File exists, ready for destination name"); 1862 return (name); 1863 } 1864 1865 void 1866 renamecmd(from, to) 1867 char *from, *to; 1868 { 1869 struct stat st; 1870 1871 LOGCMD2("rename", from, to); 1872 1873 if (guest && (stat(to, &st) == 0)) { 1874 reply(550, "%s: permission denied", to); 1875 return; 1876 } 1877 1878 if (rename(from, to) < 0) 1879 perror_reply(550, "rename"); 1880 else 1881 ack("RNTO"); 1882 } 1883 1884 static void 1885 dolog(sin) 1886 struct sockaddr_in *sin; 1887 { 1888 struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, 1889 sizeof(struct in_addr), AF_INET); 1890 1891 if (hp) 1892 (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)); 1893 else 1894 (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), 1895 sizeof(remotehost)); 1896 #ifdef SETPROCTITLE 1897 #ifdef VIRTUAL_HOSTING 1898 if (thishost != firsthost) 1899 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 1900 remotehost, hostname); 1901 else 1902 #endif 1903 snprintf(proctitle, sizeof(proctitle), "%s: connected", 1904 remotehost); 1905 setproctitle("%s", proctitle); 1906 #endif /* SETPROCTITLE */ 1907 1908 if (logging) { 1909 #ifdef VIRTUAL_HOSTING 1910 if (thishost != firsthost) 1911 syslog(LOG_INFO, "connection from %s (to %s)", 1912 remotehost, hostname); 1913 else 1914 #endif 1915 syslog(LOG_INFO, "connection from %s", remotehost); 1916 } 1917 } 1918 1919 /* 1920 * Record logout in wtmp file 1921 * and exit with supplied status. 1922 */ 1923 void 1924 dologout(status) 1925 int status; 1926 { 1927 /* 1928 * Prevent reception of SIGURG from resulting in a resumption 1929 * back to the main program loop. 1930 */ 1931 transflag = 0; 1932 1933 if (logged_in) { 1934 (void) seteuid((uid_t)0); 1935 ftpd_logwtmp(ttyline, "", ""); 1936 #if defined(KERBEROS) 1937 if (!notickets && krbtkfile_env) 1938 unlink(krbtkfile_env); 1939 #endif 1940 } 1941 /* beware of flushing buffers after a SIGPIPE */ 1942 _exit(status); 1943 } 1944 1945 static void 1946 myoob(signo) 1947 int signo; 1948 { 1949 char *cp; 1950 1951 /* only process if transfer occurring */ 1952 if (!transflag) 1953 return; 1954 cp = tmpline; 1955 if (getline(cp, 7, stdin) == NULL) { 1956 reply(221, "You could at least say goodbye."); 1957 dologout(0); 1958 } 1959 upper(cp); 1960 if (strcmp(cp, "ABOR\r\n") == 0) { 1961 tmpline[0] = '\0'; 1962 reply(426, "Transfer aborted. Data connection closed."); 1963 reply(226, "Abort successful"); 1964 longjmp(urgcatch, 1); 1965 } 1966 if (strcmp(cp, "STAT\r\n") == 0) { 1967 if (file_size != (off_t) -1) 1968 reply(213, "Status: %qd of %qd bytes transferred", 1969 byte_count, file_size); 1970 else 1971 reply(213, "Status: %qd bytes transferred", byte_count); 1972 } 1973 } 1974 1975 /* 1976 * Note: a response of 425 is not mentioned as a possible response to 1977 * the PASV command in RFC959. However, it has been blessed as 1978 * a legitimate response by Jon Postel in a telephone conversation 1979 * with Rick Adams on 25 Jan 89. 1980 */ 1981 void 1982 passive() 1983 { 1984 int len; 1985 char *p, *a; 1986 1987 if (pdata >= 0) /* close old port if one set */ 1988 close(pdata); 1989 1990 pdata = socket(AF_INET, SOCK_STREAM, 0); 1991 if (pdata < 0) { 1992 perror_reply(425, "Can't open passive connection"); 1993 return; 1994 } 1995 1996 (void) seteuid((uid_t)0); 1997 1998 #ifdef IP_PORTRANGE 1999 { 2000 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2001 : IP_PORTRANGE_DEFAULT; 2002 2003 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2004 (char *)&on, sizeof(on)) < 0) 2005 goto pasv_error; 2006 } 2007 #endif 2008 2009 pasv_addr = ctrl_addr; 2010 pasv_addr.sin_port = 0; 2011 if (bind(pdata, (struct sockaddr *)&pasv_addr, 2012 sizeof(pasv_addr)) < 0) 2013 goto pasv_error; 2014 2015 (void) seteuid((uid_t)pw->pw_uid); 2016 2017 len = sizeof(pasv_addr); 2018 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2019 goto pasv_error; 2020 if (listen(pdata, 1) < 0) 2021 goto pasv_error; 2022 a = (char *) &pasv_addr.sin_addr; 2023 p = (char *) &pasv_addr.sin_port; 2024 2025 #define UC(b) (((int) b) & 0xff) 2026 2027 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2028 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2029 return; 2030 2031 pasv_error: 2032 (void) seteuid((uid_t)pw->pw_uid); 2033 (void) close(pdata); 2034 pdata = -1; 2035 perror_reply(425, "Can't open passive connection"); 2036 return; 2037 } 2038 2039 /* 2040 * Generate unique name for file with basename "local". 2041 * The file named "local" is already known to exist. 2042 * Generates failure reply on error. 2043 */ 2044 static char * 2045 gunique(local) 2046 char *local; 2047 { 2048 static char new[MAXPATHLEN]; 2049 struct stat st; 2050 int count; 2051 char *cp; 2052 2053 cp = strrchr(local, '/'); 2054 if (cp) 2055 *cp = '\0'; 2056 if (stat(cp ? local : ".", &st) < 0) { 2057 perror_reply(553, cp ? local : "."); 2058 return ((char *) 0); 2059 } 2060 if (cp) 2061 *cp = '/'; 2062 (void) snprintf(new, sizeof(new), "%s", local); 2063 cp = new + strlen(new); 2064 *cp++ = '.'; 2065 for (count = 1; count < 100; count++) { 2066 (void)sprintf(cp, "%d", count); 2067 if (stat(new, &st) < 0) 2068 return (new); 2069 } 2070 reply(452, "Unique file name cannot be created."); 2071 return (NULL); 2072 } 2073 2074 /* 2075 * Format and send reply containing system error number. 2076 */ 2077 void 2078 perror_reply(code, string) 2079 int code; 2080 char *string; 2081 { 2082 2083 reply(code, "%s: %s.", string, strerror(errno)); 2084 } 2085 2086 static char *onefile[] = { 2087 "", 2088 0 2089 }; 2090 2091 void 2092 send_file_list(whichf) 2093 char *whichf; 2094 { 2095 struct stat st; 2096 DIR *dirp = NULL; 2097 struct dirent *dir; 2098 FILE *dout = NULL; 2099 char **dirlist, *dirname; 2100 int simple = 0; 2101 int freeglob = 0; 2102 glob_t gl; 2103 2104 if (strpbrk(whichf, "~{[*?") != NULL) { 2105 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 2106 2107 memset(&gl, 0, sizeof(gl)); 2108 freeglob = 1; 2109 if (glob(whichf, flags, 0, &gl)) { 2110 reply(550, "not found"); 2111 goto out; 2112 } else if (gl.gl_pathc == 0) { 2113 errno = ENOENT; 2114 perror_reply(550, whichf); 2115 goto out; 2116 } 2117 dirlist = gl.gl_pathv; 2118 } else { 2119 onefile[0] = whichf; 2120 dirlist = onefile; 2121 simple = 1; 2122 } 2123 2124 if (setjmp(urgcatch)) { 2125 transflag = 0; 2126 goto out; 2127 } 2128 while ((dirname = *dirlist++)) { 2129 if (stat(dirname, &st) < 0) { 2130 /* 2131 * If user typed "ls -l", etc, and the client 2132 * used NLST, do what the user meant. 2133 */ 2134 if (dirname[0] == '-' && *dirlist == NULL && 2135 transflag == 0) { 2136 retrieve(_PATH_LS " %s", dirname); 2137 goto out; 2138 } 2139 perror_reply(550, whichf); 2140 if (dout != NULL) { 2141 (void) fclose(dout); 2142 transflag = 0; 2143 data = -1; 2144 pdata = -1; 2145 } 2146 goto out; 2147 } 2148 2149 if (S_ISREG(st.st_mode)) { 2150 if (dout == NULL) { 2151 dout = dataconn("file list", (off_t)-1, "w"); 2152 if (dout == NULL) 2153 goto out; 2154 transflag++; 2155 } 2156 fprintf(dout, "%s%s\n", dirname, 2157 type == TYPE_A ? "\r" : ""); 2158 byte_count += strlen(dirname) + 1; 2159 continue; 2160 } else if (!S_ISDIR(st.st_mode)) 2161 continue; 2162 2163 if ((dirp = opendir(dirname)) == NULL) 2164 continue; 2165 2166 while ((dir = readdir(dirp)) != NULL) { 2167 char nbuf[MAXPATHLEN]; 2168 2169 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 2170 continue; 2171 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 2172 dir->d_namlen == 2) 2173 continue; 2174 2175 sprintf(nbuf, "%s/%s", dirname, dir->d_name); 2176 2177 /* 2178 * We have to do a stat to insure it's 2179 * not a directory or special file. 2180 */ 2181 if (simple || (stat(nbuf, &st) == 0 && 2182 S_ISREG(st.st_mode))) { 2183 if (dout == NULL) { 2184 dout = dataconn("file list", (off_t)-1, 2185 "w"); 2186 if (dout == NULL) 2187 goto out; 2188 transflag++; 2189 } 2190 if (nbuf[0] == '.' && nbuf[1] == '/') 2191 fprintf(dout, "%s%s\n", &nbuf[2], 2192 type == TYPE_A ? "\r" : ""); 2193 else 2194 fprintf(dout, "%s%s\n", nbuf, 2195 type == TYPE_A ? "\r" : ""); 2196 byte_count += strlen(nbuf) + 1; 2197 } 2198 } 2199 (void) closedir(dirp); 2200 } 2201 2202 if (dout == NULL) 2203 reply(550, "No files found."); 2204 else if (ferror(dout) != 0) 2205 perror_reply(550, "Data connection"); 2206 else 2207 reply(226, "Transfer complete."); 2208 2209 transflag = 0; 2210 if (dout != NULL) 2211 (void) fclose(dout); 2212 data = -1; 2213 pdata = -1; 2214 out: 2215 if (freeglob) { 2216 freeglob = 0; 2217 globfree(&gl); 2218 } 2219 } 2220 2221 void 2222 reapchild(signo) 2223 int signo; 2224 { 2225 while (wait3(NULL, WNOHANG, NULL) > 0); 2226 } 2227 2228 #ifdef OLD_SETPROCTITLE 2229 /* 2230 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 2231 * Warning, since this is usually started from inetd.conf, it often doesn't 2232 * have much of an environment or arglist to overwrite. 2233 */ 2234 void 2235 #if __STDC__ 2236 setproctitle(const char *fmt, ...) 2237 #else 2238 setproctitle(fmt, va_alist) 2239 char *fmt; 2240 va_dcl 2241 #endif 2242 { 2243 int i; 2244 va_list ap; 2245 char *p, *bp, ch; 2246 char buf[LINE_MAX]; 2247 2248 #if __STDC__ 2249 va_start(ap, fmt); 2250 #else 2251 va_start(ap); 2252 #endif 2253 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 2254 2255 /* make ps print our process name */ 2256 p = Argv[0]; 2257 *p++ = '-'; 2258 2259 i = strlen(buf); 2260 if (i > LastArgv - p - 2) { 2261 i = LastArgv - p - 2; 2262 buf[i] = '\0'; 2263 } 2264 bp = buf; 2265 while (ch = *bp++) 2266 if (ch != '\n' && ch != '\r') 2267 *p++ = ch; 2268 while (p < LastArgv) 2269 *p++ = ' '; 2270 } 2271 #endif /* OLD_SETPROCTITLE */ 2272 2273 static void 2274 logxfer(name, size, start) 2275 char *name; 2276 long size; 2277 long start; 2278 { 2279 char buf[1024]; 2280 char path[MAXPATHLEN + 1]; 2281 long now; 2282 2283 if (statfd >= 0 && getwd(path) != NULL) { 2284 time(&now); 2285 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", 2286 ctime(&now)+4, ident, remotehost, 2287 path, name, size, now - start + (now == start)); 2288 write(statfd, buf, strlen(buf)); 2289 } 2290 } 2291