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