17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*b13be141Snakanon * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 287c478bd9Sstevel@tonic-gate * All Rights Reserved 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 337c478bd9Sstevel@tonic-gate * The Regents of the University of California 347c478bd9Sstevel@tonic-gate * All Rights Reserved 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 377c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 387c478bd9Sstevel@tonic-gate * contributors. 397c478bd9Sstevel@tonic-gate */ 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * syslogd -- log system messages 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * This program implements a system log. It takes a series of lines. 477c478bd9Sstevel@tonic-gate * Each line may have a priority, signified as "<n>" as 487c478bd9Sstevel@tonic-gate * the first characters of the line. If this is 497c478bd9Sstevel@tonic-gate * not present, a default priority is used. 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will 527c478bd9Sstevel@tonic-gate * cause it to reconfigure. 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * Defined Constants: 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * MAXLINE -- the maximimum line length that can be handled. 577c478bd9Sstevel@tonic-gate * DEFUPRI -- the default priority for user messages. 587c478bd9Sstevel@tonic-gate * DEFSPRI -- the default priority for kernel messages. 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #include <unistd.h> 637c478bd9Sstevel@tonic-gate #include <note.h> 647c478bd9Sstevel@tonic-gate #include <errno.h> 657c478bd9Sstevel@tonic-gate #include <sys/types.h> 667c478bd9Sstevel@tonic-gate #include <stdio.h> 67004388ebScasper #include <stdio_ext.h> 687c478bd9Sstevel@tonic-gate #include <stdlib.h> 697c478bd9Sstevel@tonic-gate #include <ctype.h> 707c478bd9Sstevel@tonic-gate #include <signal.h> 717c478bd9Sstevel@tonic-gate #include <string.h> 727c478bd9Sstevel@tonic-gate #include <strings.h> 730ea5e3a5Sjjj #include <libscf.h> 747c478bd9Sstevel@tonic-gate #include <netconfig.h> 757c478bd9Sstevel@tonic-gate #include <netdir.h> 767c478bd9Sstevel@tonic-gate #include <pwd.h> 777c478bd9Sstevel@tonic-gate #include <sys/socket.h> 787c478bd9Sstevel@tonic-gate #include <tiuser.h> 797c478bd9Sstevel@tonic-gate #include <utmpx.h> 807c478bd9Sstevel@tonic-gate #include <limits.h> 817c478bd9Sstevel@tonic-gate #include <pthread.h> 827c478bd9Sstevel@tonic-gate #include <fcntl.h> 837c478bd9Sstevel@tonic-gate #include <stropts.h> 847c478bd9Sstevel@tonic-gate #include <assert.h> 857c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #include <sys/param.h> 887c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 897c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 907c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 917c478bd9Sstevel@tonic-gate #include <sys/stat.h> 927c478bd9Sstevel@tonic-gate #include <sys/time.h> 937c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 947c478bd9Sstevel@tonic-gate #include <sys/poll.h> 957c478bd9Sstevel@tonic-gate #include <sys/wait.h> 967c478bd9Sstevel@tonic-gate #include <sys/resource.h> 977c478bd9Sstevel@tonic-gate #include <sys/mman.h> 987c478bd9Sstevel@tonic-gate #include <sys/note.h> 997c478bd9Sstevel@tonic-gate #include <door.h> 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #include <wchar.h> 1027c478bd9Sstevel@tonic-gate #include <locale.h> 1037c478bd9Sstevel@tonic-gate #include <stdarg.h> 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate #include "dataq.h" 1067c478bd9Sstevel@tonic-gate #include "conf.h" 1077c478bd9Sstevel@tonic-gate #include "syslogd.h" 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate #define DOORFILE "/var/run/syslog_door" 1107c478bd9Sstevel@tonic-gate #define RELATIVE_DOORFILE "../var/run/syslog_door" 1117c478bd9Sstevel@tonic-gate #define OLD_DOORFILE "/etc/.syslog_door" 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate #define PIDFILE "/var/run/syslog.pid" 1147c478bd9Sstevel@tonic-gate #define RELATIVE_PIDFILE "../var/run/syslog.pid" 1157c478bd9Sstevel@tonic-gate #define OLD_PIDFILE "/etc/syslog.pid" 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate static char *Version = "%I%"; 1187c478bd9Sstevel@tonic-gate static char *LogName = "/dev/log"; 1197c478bd9Sstevel@tonic-gate static char *ConfFile = "/etc/syslog.conf"; 1207c478bd9Sstevel@tonic-gate static char ctty[] = "/dev/console"; 1217c478bd9Sstevel@tonic-gate static char sysmsg[] = "/dev/sysmsg"; 1227c478bd9Sstevel@tonic-gate static int DoorFd = -1; 1237c478bd9Sstevel@tonic-gate static int DoorCreated = 0; 1247c478bd9Sstevel@tonic-gate static int PidfileCreated = 0; 1257c478bd9Sstevel@tonic-gate static char *DoorFileName = DOORFILE; 1267c478bd9Sstevel@tonic-gate static char *PidFileName = PIDFILE; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * configuration file directives 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate static struct code PriNames[] = { 1337c478bd9Sstevel@tonic-gate "panic", LOG_EMERG, 1347c478bd9Sstevel@tonic-gate "emerg", LOG_EMERG, 1357c478bd9Sstevel@tonic-gate "alert", LOG_ALERT, 1367c478bd9Sstevel@tonic-gate "crit", LOG_CRIT, 1377c478bd9Sstevel@tonic-gate "err", LOG_ERR, 1387c478bd9Sstevel@tonic-gate "error", LOG_ERR, 1397c478bd9Sstevel@tonic-gate "warn", LOG_WARNING, 1407c478bd9Sstevel@tonic-gate "warning", LOG_WARNING, 1417c478bd9Sstevel@tonic-gate "notice", LOG_NOTICE, 1427c478bd9Sstevel@tonic-gate "info", LOG_INFO, 1437c478bd9Sstevel@tonic-gate "debug", LOG_DEBUG, 1447c478bd9Sstevel@tonic-gate "none", NOPRI, 1457c478bd9Sstevel@tonic-gate NULL, -1 1467c478bd9Sstevel@tonic-gate }; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate static struct code FacNames[] = { 1497c478bd9Sstevel@tonic-gate "kern", LOG_KERN, 1507c478bd9Sstevel@tonic-gate "user", LOG_USER, 1517c478bd9Sstevel@tonic-gate "mail", LOG_MAIL, 1527c478bd9Sstevel@tonic-gate "daemon", LOG_DAEMON, 1537c478bd9Sstevel@tonic-gate "auth", LOG_AUTH, 1547c478bd9Sstevel@tonic-gate "security", LOG_AUTH, 1557c478bd9Sstevel@tonic-gate "mark", LOG_MARK, 1567c478bd9Sstevel@tonic-gate "syslog", LOG_SYSLOG, 1577c478bd9Sstevel@tonic-gate "lpr", LOG_LPR, 1587c478bd9Sstevel@tonic-gate "news", LOG_NEWS, 1597c478bd9Sstevel@tonic-gate "uucp", LOG_UUCP, 1607c478bd9Sstevel@tonic-gate "audit", LOG_AUDIT, 1617c478bd9Sstevel@tonic-gate "cron", LOG_CRON, 1627c478bd9Sstevel@tonic-gate "local0", LOG_LOCAL0, 1637c478bd9Sstevel@tonic-gate "local1", LOG_LOCAL1, 1647c478bd9Sstevel@tonic-gate "local2", LOG_LOCAL2, 1657c478bd9Sstevel@tonic-gate "local3", LOG_LOCAL3, 1667c478bd9Sstevel@tonic-gate "local4", LOG_LOCAL4, 1677c478bd9Sstevel@tonic-gate "local5", LOG_LOCAL5, 1687c478bd9Sstevel@tonic-gate "local6", LOG_LOCAL6, 1697c478bd9Sstevel@tonic-gate "local7", LOG_LOCAL7, 1707c478bd9Sstevel@tonic-gate NULL, -1 1717c478bd9Sstevel@tonic-gate }; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate static char *TypeNames[7] = { 1747c478bd9Sstevel@tonic-gate "UNUSED", "FILE", "TTY", "CONSOLE", 1757c478bd9Sstevel@tonic-gate "FORW", "USERS", "WALL" 1767c478bd9Sstevel@tonic-gate }; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * we allocate our own thread stacks so we can create them 1807c478bd9Sstevel@tonic-gate * without the MAP_NORESERVE option. We need to be sure 1817c478bd9Sstevel@tonic-gate * we have stack space even if the machine runs out of swap 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate #define DEFAULT_STACKSIZE (100 * 1024) /* 100 k stack */ 1857c478bd9Sstevel@tonic-gate #define DEFAULT_REDZONESIZE (8 * 1024) /* 8k redzone */ 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static pthread_mutex_t wmp = PTHREAD_MUTEX_INITIALIZER; /* wallmsg lock */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate static pthread_mutex_t cft = PTHREAD_MUTEX_INITIALIZER; 1907c478bd9Sstevel@tonic-gate static int conf_threads = 0; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate static pthread_mutex_t hup_lock = PTHREAD_MUTEX_INITIALIZER; 1937c478bd9Sstevel@tonic-gate static pthread_cond_t hup_done = PTHREAD_COND_INITIALIZER; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate static pthread_mutex_t logerror_lock = PTHREAD_MUTEX_INITIALIZER; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate #define HUP_ACCEPTABLE 0x0000 /* can start SIGHUP process */ 1987c478bd9Sstevel@tonic-gate #define HUP_INPROGRESS 0x0001 /* SIGHUP process in progress */ 1997c478bd9Sstevel@tonic-gate #define HUP_COMPLETED 0x0002 /* SIGHUP process completed */ 2007c478bd9Sstevel@tonic-gate #define HUP_SUSP_LOGMSG_REQD 0x1000 /* request to suspend */ 2017c478bd9Sstevel@tonic-gate #define HUP_LOGMSG_SUSPENDED 0x2000 /* logmsg is suspended */ 2027c478bd9Sstevel@tonic-gate static int hup_state = HUP_ACCEPTABLE; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate static size_t stacksize; /* thread stack size */ 2057c478bd9Sstevel@tonic-gate static size_t redzonesize; /* thread stack redzone size */ 2067c478bd9Sstevel@tonic-gate static char *stack_ptr; /* ptr to allocated stacks */ 2077c478bd9Sstevel@tonic-gate static char *cstack_ptr; /* ptr to conf_thr stacks */ 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate static time_t start_time; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static pthread_t sys_thread; /* queues messages from us */ 2127c478bd9Sstevel@tonic-gate static pthread_t net_thread; /* queues messages from the net */ 2137c478bd9Sstevel@tonic-gate static pthread_t log_thread; /* message processing thread */ 2147c478bd9Sstevel@tonic-gate static pthread_t hnl_thread; /* hostname lookup thread */ 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate static dataq_t inputq; /* the input queue */ 2177c478bd9Sstevel@tonic-gate static dataq_t tmpq; /* temporary queue for err msg */ 2187c478bd9Sstevel@tonic-gate static dataq_t hnlq; /* hostname lookup queue */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate static struct filed fallback[2]; 2217c478bd9Sstevel@tonic-gate static struct filed *Files; 2227c478bd9Sstevel@tonic-gate static int nlogs; 2237c478bd9Sstevel@tonic-gate static int Debug; /* debug flag */ 2247c478bd9Sstevel@tonic-gate static host_list_t LocalHostName; /* our hostname */ 2257c478bd9Sstevel@tonic-gate static host_list_t NullHostName; /* in case of lookup failure */ 2267c478bd9Sstevel@tonic-gate static int debuglev = 1; /* debug print level */ 2277c478bd9Sstevel@tonic-gate static int interrorlog; /* internal error logging */ 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate static int MarkInterval = 20; /* interval between marks (mins) */ 2307c478bd9Sstevel@tonic-gate static int Marking = 0; /* non-zero if marking some file */ 2317c478bd9Sstevel@tonic-gate static int Ninputs = 0; /* number of network inputs */ 2327c478bd9Sstevel@tonic-gate static int curalarm = 0; /* current timeout value (secs) */ 2337c478bd9Sstevel@tonic-gate static int sys_msg_count = 0; /* total msgs rcvd from local log */ 2347c478bd9Sstevel@tonic-gate static int sys_init_msg_count = 0; /* initially received */ 2357c478bd9Sstevel@tonic-gate static int net_msg_count = 0; /* total msgs rcvd from net */ 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate static struct pollfd Pfd; /* Pollfd for local the log device */ 2387c478bd9Sstevel@tonic-gate static struct pollfd *Nfd; /* Array of pollfds for udp ports */ 2397c478bd9Sstevel@tonic-gate static struct netconfig *Ncf; 2407c478bd9Sstevel@tonic-gate static struct netbuf **Myaddrs; 2417c478bd9Sstevel@tonic-gate static struct t_unitdata **Udp; 2427c478bd9Sstevel@tonic-gate static struct t_uderr **Errp; 2437c478bd9Sstevel@tonic-gate static int turnoff = 0; 2447c478bd9Sstevel@tonic-gate static int shutting_down; 2457c478bd9Sstevel@tonic-gate 246*b13be141Snakanon /* for managing door server threads */ 247*b13be141Snakanon static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER; 248*b13be141Snakanon static uint_t door_server_cnt = 0; 249*b13be141Snakanon static pthread_attr_t door_thr_attr; 250*b13be141Snakanon 251293d1fc4Spd155743 static struct hostname_cache **hnc_cache; 2527c478bd9Sstevel@tonic-gate static pthread_mutex_t hnc_mutex = PTHREAD_MUTEX_INITIALIZER; 2537c478bd9Sstevel@tonic-gate static size_t hnc_size = DEF_HNC_SIZE; 2547c478bd9Sstevel@tonic-gate static unsigned int hnc_ttl = DEF_HNC_TTL; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate #define DPRINT0(d, m) if ((Debug) && debuglev >= (d)) \ 2577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m) 2587c478bd9Sstevel@tonic-gate #define DPRINT1(d, m, a) if ((Debug) && debuglev >= (d)) \ 2597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a) 2607c478bd9Sstevel@tonic-gate #define DPRINT2(d, m, a, b) if ((Debug) && debuglev >= (d)) \ 2617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b) 2627c478bd9Sstevel@tonic-gate #define DPRINT3(d, m, a, b, c) if ((Debug) && debuglev >= (d)) \ 2637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c) 2647c478bd9Sstevel@tonic-gate #define DPRINT4(d, m, a, b, c, e) if ((Debug) && debuglev >= (d)) \ 2657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c, e) 2667c478bd9Sstevel@tonic-gate #define MALLOC_FAIL(x) \ 2677c478bd9Sstevel@tonic-gate logerror("malloc failed: " x) 2687c478bd9Sstevel@tonic-gate #define MALLOC_FAIL_EXIT \ 2697c478bd9Sstevel@tonic-gate logerror("malloc failed - fatal"); \ 2707c478bd9Sstevel@tonic-gate exit(1) 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate #define MAILCMD "mailx -s \"syslogd shut down\" root" 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * Number of seconds to wait before giving up on threads that won't 2777c478bd9Sstevel@tonic-gate * shutdown: (that's right, 10 minutes!) 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate #define LOOP_MAX (10 * 60) 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Interval(sec) to check the status of output queue while processing 2837c478bd9Sstevel@tonic-gate * HUP signal. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate #define LOOP_INTERVAL (15) 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate int 2887c478bd9Sstevel@tonic-gate main(int argc, char **argv) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate int i; 2917c478bd9Sstevel@tonic-gate char *pstr; 2927c478bd9Sstevel@tonic-gate int sig, fd; 2937c478bd9Sstevel@tonic-gate int tflag = 0, Tflag = 0; 2947c478bd9Sstevel@tonic-gate sigset_t sigs, allsigs; 2957c478bd9Sstevel@tonic-gate struct rlimit rlim; 2967c478bd9Sstevel@tonic-gate char *debugstr; 2977c478bd9Sstevel@tonic-gate int mcount = 0; 2987c478bd9Sstevel@tonic-gate struct sigaction act; 2997c478bd9Sstevel@tonic-gate pthread_t mythreadno = 0; 3007c478bd9Sstevel@tonic-gate char cbuf [30]; 3017c478bd9Sstevel@tonic-gate struct stat sb; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate #ifdef DEBUG 3047c478bd9Sstevel@tonic-gate #define DEBUGDIR "/var/tmp" 3057c478bd9Sstevel@tonic-gate if (chdir(DEBUGDIR)) 3067c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): Unable to cd to %s\n", mythreadno, 3077c478bd9Sstevel@tonic-gate DEBUGDIR); 3087c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if ((debugstr = getenv("SYSLOGD_DEBUG")) != NULL) 3137c478bd9Sstevel@tonic-gate if ((debuglev = atoi(debugstr)) == 0) 3147c478bd9Sstevel@tonic-gate debuglev = 1; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate #if ! defined(TEXT_DOMAIN) /* should be defined by cc -D */ 3177c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 3187c478bd9Sstevel@tonic-gate #endif 3197c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate (void) time(&start_time); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if (lstat("/var/run", &sb) != 0 || !(S_ISDIR(sb.st_mode))) { 3247c478bd9Sstevel@tonic-gate DoorFileName = OLD_DOORFILE; 3257c478bd9Sstevel@tonic-gate PidFileName = OLD_PIDFILE; 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3280ea5e3a5Sjjj properties(); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate while ((i = getopt(argc, argv, "df:p:m:tT")) != EOF) { 3317c478bd9Sstevel@tonic-gate switch (i) { 3327c478bd9Sstevel@tonic-gate case 'f': /* configuration file */ 3337c478bd9Sstevel@tonic-gate ConfFile = optarg; 3347c478bd9Sstevel@tonic-gate break; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate case 'd': /* debug */ 3377c478bd9Sstevel@tonic-gate Debug++; 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate case 'p': /* path */ 3417c478bd9Sstevel@tonic-gate LogName = optarg; 3427c478bd9Sstevel@tonic-gate break; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate case 'm': /* mark interval */ 3457c478bd9Sstevel@tonic-gate for (pstr = optarg; *pstr; pstr++) { 3467c478bd9Sstevel@tonic-gate if (! (isdigit(*pstr))) { 3477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3487c478bd9Sstevel@tonic-gate "Illegal interval\n"); 3497c478bd9Sstevel@tonic-gate usage(); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate MarkInterval = atoi(optarg); 3537c478bd9Sstevel@tonic-gate if (MarkInterval < 1 || MarkInterval > INT_MAX) { 3547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3557c478bd9Sstevel@tonic-gate "Interval must be between 1 and %d\n", 3567c478bd9Sstevel@tonic-gate INT_MAX); 3577c478bd9Sstevel@tonic-gate usage(); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate break; 3607c478bd9Sstevel@tonic-gate case 't': /* turn off remote reception */ 3617c478bd9Sstevel@tonic-gate tflag++; 3627c478bd9Sstevel@tonic-gate turnoff++; 3637c478bd9Sstevel@tonic-gate break; 3647c478bd9Sstevel@tonic-gate case 'T': /* turn on remote reception */ 3657c478bd9Sstevel@tonic-gate Tflag++; 3667c478bd9Sstevel@tonic-gate turnoff = 0; 3677c478bd9Sstevel@tonic-gate break; 3687c478bd9Sstevel@tonic-gate default: 3697c478bd9Sstevel@tonic-gate usage(); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (optind < argc) 3747c478bd9Sstevel@tonic-gate usage(); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if (tflag && Tflag) { 3777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "specify only one of -t and -T\n"); 3787c478bd9Sstevel@tonic-gate usage(); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * close all fd's except 0-2 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate closefrom(3); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (!Debug) { 3887c478bd9Sstevel@tonic-gate if (fork()) 3897c478bd9Sstevel@tonic-gate return (0); 3907c478bd9Sstevel@tonic-gate (void) close(0); 3917c478bd9Sstevel@tonic-gate (void) open("/", 0); 3927c478bd9Sstevel@tonic-gate (void) dup2(0, 1); 3937c478bd9Sstevel@tonic-gate (void) dup2(0, 2); 3947c478bd9Sstevel@tonic-gate untty(); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (Debug) { 3987c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * DO NOT call logerror() until tmpq is initialized. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate disable_errorlog(); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * ensure that file descriptor limit is "high enough" 4087c478bd9Sstevel@tonic-gate */ 4097c478bd9Sstevel@tonic-gate (void) getrlimit(RLIMIT_NOFILE, &rlim); 4107c478bd9Sstevel@tonic-gate if (rlim.rlim_cur < rlim.rlim_max) 4117c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 4127c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) 4137c478bd9Sstevel@tonic-gate logerror("Unable to increase file descriptor limit."); 414004388ebScasper (void) enable_extended_FILE_stdio(-1, -1); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* block all signals from all threads initially */ 4177c478bd9Sstevel@tonic-gate (void) sigfillset(&allsigs); 4187c478bd9Sstevel@tonic-gate (void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL); 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): Started at time %s", mythreadno, 4217c478bd9Sstevel@tonic-gate ctime_r(&start_time, cbuf)); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate init(); /* read configuration, start threads */ 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): off & running....\n", mythreadno); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* now set up to catch signals we care about */ 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigs); 4307c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGHUP); /* reconfigure */ 4317c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGALRM); /* mark & flush timer */ 4327c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGTERM); /* exit */ 4337c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGINT); /* exit if debugging */ 4347c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGQUIT); /* exit if debugging */ 4357c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGPIPE); /* catch & discard */ 4367c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGUSR1); /* dump debug stats */ 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * We must set up to catch these signals, even though sigwait 4407c478bd9Sstevel@tonic-gate * will get them before the isr does. Setting SA_SIGINFO ensures 4417c478bd9Sstevel@tonic-gate * that signals will be enqueued. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 4457c478bd9Sstevel@tonic-gate act.sa_sigaction = signull; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &act, NULL); 4487c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &act, NULL); 4497c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &act, NULL); 4507c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &act, NULL); 4517c478bd9Sstevel@tonic-gate (void) sigaction(SIGQUIT, &act, NULL); 4527c478bd9Sstevel@tonic-gate (void) sigaction(SIGPIPE, &act, NULL); 4537c478bd9Sstevel@tonic-gate (void) sigaction(SIGUSR1, &act, NULL); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* we now turn into the signal handling thread */ 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate DPRINT1(2, "main(%u): now handling signals\n", mythreadno); 4587c478bd9Sstevel@tonic-gate for (;;) { 4597c478bd9Sstevel@tonic-gate (void) sigwait(&sigs, &sig); 4607c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): received signal %d\n", mythreadno, sig); 4617c478bd9Sstevel@tonic-gate switch (sig) { 4627c478bd9Sstevel@tonic-gate case SIGALRM: 4637c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): Got SIGALRM\n", 4647c478bd9Sstevel@tonic-gate mythreadno); 4657c478bd9Sstevel@tonic-gate flushmsg(NOCOPY); 4667c478bd9Sstevel@tonic-gate if (Marking && (++mcount % MARKCOUNT == 0)) { 4677c478bd9Sstevel@tonic-gate if (logmymsg(LOG_INFO, "-- MARK --", 4687c478bd9Sstevel@tonic-gate ADDDATE|MARK|NOCOPY, 0) == -1) { 4697c478bd9Sstevel@tonic-gate MALLOC_FAIL( 4707c478bd9Sstevel@tonic-gate "dropping MARK message"); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate mcount = 0; 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT; 4767c478bd9Sstevel@tonic-gate (void) alarm((unsigned)curalarm); 4777c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): Next alarm in %d " 4787c478bd9Sstevel@tonic-gate "seconds\n", mythreadno, curalarm); 4797c478bd9Sstevel@tonic-gate break; 4807c478bd9Sstevel@tonic-gate case SIGHUP: 4817c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): got SIGHUP - " 4827c478bd9Sstevel@tonic-gate "reconfiguring\n", mythreadno); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate reconfigure(); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): done processing SIGHUP\n", 4877c478bd9Sstevel@tonic-gate mythreadno); 4887c478bd9Sstevel@tonic-gate break; 4897c478bd9Sstevel@tonic-gate case SIGQUIT: 4907c478bd9Sstevel@tonic-gate case SIGINT: 4917c478bd9Sstevel@tonic-gate if (!Debug) { 4927c478bd9Sstevel@tonic-gate /* allow these signals if debugging */ 4937c478bd9Sstevel@tonic-gate break; 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 4967c478bd9Sstevel@tonic-gate case SIGTERM: 4977c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): going down on signal %d\n", 4987c478bd9Sstevel@tonic-gate mythreadno, sig); 4997c478bd9Sstevel@tonic-gate (void) alarm(0); 5007c478bd9Sstevel@tonic-gate flushmsg(0); 5017c478bd9Sstevel@tonic-gate errno = 0; 5027c478bd9Sstevel@tonic-gate t_errno = 0; 5037c478bd9Sstevel@tonic-gate logerror("going down on signal %d", sig); 5047c478bd9Sstevel@tonic-gate disable_errorlog(); /* force msg to console */ 5057c478bd9Sstevel@tonic-gate (void) shutdown_msg(); /* stop threads */ 5067c478bd9Sstevel@tonic-gate shutdown_input(); 5077c478bd9Sstevel@tonic-gate close_door(); 5087c478bd9Sstevel@tonic-gate delete_doorfiles(); 5097c478bd9Sstevel@tonic-gate return (0); 5107c478bd9Sstevel@tonic-gate break; 5117c478bd9Sstevel@tonic-gate case SIGUSR1: /* secret debug dump mode */ 5127c478bd9Sstevel@tonic-gate /* if in debug mode, use stdout */ 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if (Debug) { 5157c478bd9Sstevel@tonic-gate dumpstats(STDOUT_FILENO); 5167c478bd9Sstevel@tonic-gate break; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate /* otherwise dump to a debug file */ 5197c478bd9Sstevel@tonic-gate if ((fd = open(DEBUGFILE, 5207c478bd9Sstevel@tonic-gate (O_WRONLY|O_CREAT|O_TRUNC|O_EXCL), 5217c478bd9Sstevel@tonic-gate 0644)) < 0) 5227c478bd9Sstevel@tonic-gate break; 5237c478bd9Sstevel@tonic-gate dumpstats(fd); 5247c478bd9Sstevel@tonic-gate (void) close(fd); 5257c478bd9Sstevel@tonic-gate break; 5267c478bd9Sstevel@tonic-gate default: 5277c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): unexpected signal %d\n", 5287c478bd9Sstevel@tonic-gate mythreadno, sig); 5297c478bd9Sstevel@tonic-gate break; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Attempts to open the local log device 5367c478bd9Sstevel@tonic-gate * and return a file descriptor. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate static int 5397c478bd9Sstevel@tonic-gate openklog(char *name, int mode) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate int fd; 5427c478bd9Sstevel@tonic-gate struct strioctl str; 5437c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (Debug) { 5467c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if ((fd = open(name, mode)) < 0) { 5507c478bd9Sstevel@tonic-gate logerror("cannot open %s", name); 5517c478bd9Sstevel@tonic-gate DPRINT3(1, "openklog(%u): cannot create %s (%d)\n", 5527c478bd9Sstevel@tonic-gate mythreadno, name, errno); 5537c478bd9Sstevel@tonic-gate return (-1); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate str.ic_cmd = I_CONSLOG; 5567c478bd9Sstevel@tonic-gate str.ic_timout = 0; 5577c478bd9Sstevel@tonic-gate str.ic_len = 0; 5587c478bd9Sstevel@tonic-gate str.ic_dp = NULL; 5597c478bd9Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) < 0) { 5607c478bd9Sstevel@tonic-gate logerror("cannot register to log console messages"); 5617c478bd9Sstevel@tonic-gate DPRINT2(1, "openklog(%u): cannot register to log " 5627c478bd9Sstevel@tonic-gate "console messages (%d)\n", mythreadno, errno); 5637c478bd9Sstevel@tonic-gate return (-1); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate return (fd); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * Open the log device, and pull up all pending messages. 5717c478bd9Sstevel@tonic-gate */ 5727c478bd9Sstevel@tonic-gate static void 5737c478bd9Sstevel@tonic-gate prepare_sys_poll() 5747c478bd9Sstevel@tonic-gate { 5757c478bd9Sstevel@tonic-gate int nfds, funix; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if ((funix = openklog(LogName, O_RDONLY)) < 0) { 5787c478bd9Sstevel@tonic-gate logerror("can't open kernel log device - fatal"); 5797c478bd9Sstevel@tonic-gate exit(1); 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate Pfd.fd = funix; 5837c478bd9Sstevel@tonic-gate Pfd.events = POLLIN; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate for (;;) { 5867c478bd9Sstevel@tonic-gate nfds = poll(&Pfd, 1, 0); 5877c478bd9Sstevel@tonic-gate if (nfds <= 0) { 5887c478bd9Sstevel@tonic-gate if (sys_init_msg_count > 0) 5897c478bd9Sstevel@tonic-gate flushmsg(SYNC_FILE); 5907c478bd9Sstevel@tonic-gate break; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (Pfd.revents & POLLIN) { 5947c478bd9Sstevel@tonic-gate getkmsg(0); 5957c478bd9Sstevel@tonic-gate } else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { 5967c478bd9Sstevel@tonic-gate logerror("kernel log driver poll error"); 5977c478bd9Sstevel@tonic-gate break; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate /* 6047c478bd9Sstevel@tonic-gate * this thread listens to the local stream log driver for log messages 6057c478bd9Sstevel@tonic-gate * generated by this host, formats them, and queues them to the logger 6067c478bd9Sstevel@tonic-gate * thread. 6077c478bd9Sstevel@tonic-gate */ 6087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6097c478bd9Sstevel@tonic-gate static void * 6107c478bd9Sstevel@tonic-gate sys_poll(void *ap) 6117c478bd9Sstevel@tonic-gate { 6127c478bd9Sstevel@tonic-gate int nfds; 6137c478bd9Sstevel@tonic-gate static int klogerrs = 0; 6147c478bd9Sstevel@tonic-gate pthread_t mythreadno; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if (Debug) { 6177c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate DPRINT1(1, "sys_poll(%u): sys_thread started\n", mythreadno); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * Try to process as many messages as we can without blocking on poll. 6247c478bd9Sstevel@tonic-gate * We count such "initial" messages with sys_init_msg_count and 6257c478bd9Sstevel@tonic-gate * enqueue them without the SYNC_FILE flag. When no more data is 6267c478bd9Sstevel@tonic-gate * waiting on the local log device, we set timeout to INFTIM, 6277c478bd9Sstevel@tonic-gate * clear sys_init_msg_count, and generate a flush message to sync 6287c478bd9Sstevel@tonic-gate * the previously counted initial messages out to disk. 6297c478bd9Sstevel@tonic-gate */ 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate sys_init_msg_count = 0; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate for (;;) { 6347c478bd9Sstevel@tonic-gate errno = 0; 6357c478bd9Sstevel@tonic-gate t_errno = 0; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate nfds = poll(&Pfd, 1, INFTIM); 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate if (nfds == 0) 6407c478bd9Sstevel@tonic-gate continue; 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (nfds < 0) { 6437c478bd9Sstevel@tonic-gate if (errno != EINTR) 6447c478bd9Sstevel@tonic-gate logerror("poll"); 6457c478bd9Sstevel@tonic-gate continue; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate if (Pfd.revents & POLLIN) { 6487c478bd9Sstevel@tonic-gate getkmsg(INFTIM); 6497c478bd9Sstevel@tonic-gate } else { 6507c478bd9Sstevel@tonic-gate if (shutting_down) { 6517c478bd9Sstevel@tonic-gate pthread_exit(0); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { 6547c478bd9Sstevel@tonic-gate logerror("kernel log driver poll error"); 6557c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 6567c478bd9Sstevel@tonic-gate Pfd.fd = -1; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate while (Pfd.fd == -1 && klogerrs++ < 10) { 6617c478bd9Sstevel@tonic-gate Pfd.fd = openklog(LogName, O_RDONLY); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate if (klogerrs >= 10) { 6647c478bd9Sstevel@tonic-gate logerror("can't reopen kernel log device - fatal"); 6657c478bd9Sstevel@tonic-gate exit(1); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 6697c478bd9Sstevel@tonic-gate return (NULL); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * Pull up one message from log driver. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate static void 6767c478bd9Sstevel@tonic-gate getkmsg(int timeout) 6777c478bd9Sstevel@tonic-gate { 6787c478bd9Sstevel@tonic-gate int flags = 0, i; 6797c478bd9Sstevel@tonic-gate char *lastline; 6807c478bd9Sstevel@tonic-gate struct strbuf ctl, dat; 6817c478bd9Sstevel@tonic-gate struct log_ctl hdr; 6827c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 6837c478bd9Sstevel@tonic-gate size_t buflen; 6847c478bd9Sstevel@tonic-gate size_t len; 6857c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE+1]; 6867c478bd9Sstevel@tonic-gate pthread_t mythreadno; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (Debug) { 6897c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE; 6937c478bd9Sstevel@tonic-gate dat.buf = buf; 6947c478bd9Sstevel@tonic-gate ctl.maxlen = sizeof (struct log_ctl); 6957c478bd9Sstevel@tonic-gate ctl.buf = (caddr_t)&hdr; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) { 6987c478bd9Sstevel@tonic-gate lastline = &dat.buf[dat.len]; 6997c478bd9Sstevel@tonic-gate *lastline = '\0'; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate DPRINT2(5, "sys_poll:(%u): getmsg: dat.len = %d\n", 7027c478bd9Sstevel@tonic-gate mythreadno, dat.len); 7037c478bd9Sstevel@tonic-gate buflen = strlen(buf); 7047c478bd9Sstevel@tonic-gate len = findnl_bkwd(buf, buflen); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate (void) memcpy(tmpbuf, buf, len); 7077c478bd9Sstevel@tonic-gate tmpbuf[len] = '\0'; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate /* 7107c478bd9Sstevel@tonic-gate * Format sys will enqueue the log message. 7117c478bd9Sstevel@tonic-gate * Set the sync flag if timeout != 0, which 7127c478bd9Sstevel@tonic-gate * means that we're done handling all the 7137c478bd9Sstevel@tonic-gate * initial messages ready during startup. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate if (timeout == 0) { 7167c478bd9Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 0); 7177c478bd9Sstevel@tonic-gate sys_init_msg_count++; 7187c478bd9Sstevel@tonic-gate } else { 7197c478bd9Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 1); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate sys_msg_count++; 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (len != buflen) { 7247c478bd9Sstevel@tonic-gate /* If anything remains in buf */ 7257c478bd9Sstevel@tonic-gate size_t remlen; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate if (buf[len] == '\n') { 7287c478bd9Sstevel@tonic-gate /* skip newline */ 7297c478bd9Sstevel@tonic-gate len++; 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * Move the remaining bytes to 7347c478bd9Sstevel@tonic-gate * the beginnning of buf. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate remlen = buflen - len; 7387c478bd9Sstevel@tonic-gate (void) memcpy(buf, &buf[len], remlen); 7397c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE - remlen; 7407c478bd9Sstevel@tonic-gate dat.buf = &buf[remlen]; 7417c478bd9Sstevel@tonic-gate } else { 7427c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE; 7437c478bd9Sstevel@tonic-gate dat.buf = buf; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if (i == 0 && dat.len > 0) { 7487c478bd9Sstevel@tonic-gate dat.buf[dat.len] = '\0'; 7497c478bd9Sstevel@tonic-gate /* 7507c478bd9Sstevel@tonic-gate * Format sys will enqueue the log message. 7517c478bd9Sstevel@tonic-gate * Set the sync flag if timeout != 0, which 7527c478bd9Sstevel@tonic-gate * means that we're done handling all the 7537c478bd9Sstevel@tonic-gate * initial messages ready during startup. 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.maxlen = %d\n", 7567c478bd9Sstevel@tonic-gate mythreadno, dat.maxlen); 7577c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.len = %d\n", 7587c478bd9Sstevel@tonic-gate mythreadno, dat.len); 7597c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: strlen(dat.buf) = %d\n", 7607c478bd9Sstevel@tonic-gate mythreadno, strlen(dat.buf)); 7617c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.buf = \"%s\"\n", 7627c478bd9Sstevel@tonic-gate mythreadno, dat.buf); 7637c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): buf len = %d\n", 7647c478bd9Sstevel@tonic-gate mythreadno, strlen(buf)); 7657c478bd9Sstevel@tonic-gate if (timeout == 0) { 7667c478bd9Sstevel@tonic-gate formatsys(&hdr, buf, 0); 7677c478bd9Sstevel@tonic-gate sys_init_msg_count++; 7687c478bd9Sstevel@tonic-gate } else { 7697c478bd9Sstevel@tonic-gate formatsys(&hdr, buf, 1); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate sys_msg_count++; 7727c478bd9Sstevel@tonic-gate } else if (i < 0 && errno != EINTR) { 7737c478bd9Sstevel@tonic-gate if (!shutting_down) { 7747c478bd9Sstevel@tonic-gate logerror("kernel log driver read error"); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 7777c478bd9Sstevel@tonic-gate Pfd.fd = -1; 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * this thread polls all the network interfaces for syslog messages 7837c478bd9Sstevel@tonic-gate * forwarded to us, tags them with the hostname they are received 7847c478bd9Sstevel@tonic-gate * from, and queues them to the logger thread. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7877c478bd9Sstevel@tonic-gate static void * 7887c478bd9Sstevel@tonic-gate net_poll(void *ap) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate int nfds, i; 7917c478bd9Sstevel@tonic-gate int flags = 0; 7927c478bd9Sstevel@tonic-gate struct t_unitdata *udp; 7937c478bd9Sstevel@tonic-gate struct t_uderr *errp; 7947c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 7957c478bd9Sstevel@tonic-gate char *uap; 7967c478bd9Sstevel@tonic-gate log_message_t *mp; 7977c478bd9Sstevel@tonic-gate host_info_t *hinfo; 7987c478bd9Sstevel@tonic-gate pthread_t mythreadno; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate if (Debug) { 8017c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): net_thread started\n", mythreadno); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate for (;;) { 8097c478bd9Sstevel@tonic-gate errno = 0; 8107c478bd9Sstevel@tonic-gate t_errno = 0; 8117c478bd9Sstevel@tonic-gate nfds = poll(Nfd, Ninputs, -1); 8127c478bd9Sstevel@tonic-gate if (nfds == 0) 8137c478bd9Sstevel@tonic-gate continue; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate if (nfds < 0) { 8167c478bd9Sstevel@tonic-gate if (errno != EINTR) 8177c478bd9Sstevel@tonic-gate logerror("poll"); 8187c478bd9Sstevel@tonic-gate continue; 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate for (i = 0; nfds > 0 && i < Ninputs; i++) { 8217c478bd9Sstevel@tonic-gate if ((Nfd[i].revents & POLLIN) == 0) { 8227c478bd9Sstevel@tonic-gate if (shutting_down) { 8237c478bd9Sstevel@tonic-gate pthread_exit(0); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate if (Nfd[i].revents & 8267c478bd9Sstevel@tonic-gate (POLLNVAL|POLLHUP|POLLERR)) { 8277c478bd9Sstevel@tonic-gate logerror("POLLNVAL|POLLHUP|POLLERR"); 8287c478bd9Sstevel@tonic-gate (void) t_close(Nfd[i].fd); 8297c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 8307c478bd9Sstevel@tonic-gate nfds--; 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate continue; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate udp = Udp[i]; 8367c478bd9Sstevel@tonic-gate udp->udata.buf = buf; 8377c478bd9Sstevel@tonic-gate udp->udata.maxlen = MAXLINE; 8387c478bd9Sstevel@tonic-gate udp->udata.len = 0; 8397c478bd9Sstevel@tonic-gate flags = 0; 8407c478bd9Sstevel@tonic-gate if (t_rcvudata(Nfd[i].fd, udp, &flags) < 0) { 8417c478bd9Sstevel@tonic-gate errp = Errp[i]; 8427c478bd9Sstevel@tonic-gate if (t_errno == TLOOK) { 8437c478bd9Sstevel@tonic-gate if (t_rcvuderr(Nfd[i].fd, errp) < 0) { 8447c478bd9Sstevel@tonic-gate if (!shutting_down) { 8457c478bd9Sstevel@tonic-gate logerror("t_rcvuderr"); 8467c478bd9Sstevel@tonic-gate } 8470ea5e3a5Sjjj (void) t_close(Nfd[i].fd); 8487c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate } else { 8517c478bd9Sstevel@tonic-gate if (!shutting_down) { 8527c478bd9Sstevel@tonic-gate logerror("t_rcvudata"); 8537c478bd9Sstevel@tonic-gate } 8540ea5e3a5Sjjj (void) t_close(Nfd[i].fd); 8557c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate nfds--; 8587c478bd9Sstevel@tonic-gate if (shutting_down) { 8597c478bd9Sstevel@tonic-gate pthread_exit(0); 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate continue; 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate nfds--; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate if (udp->udata.len == 0) { 8667c478bd9Sstevel@tonic-gate if (Debug) { 8677c478bd9Sstevel@tonic-gate uap = NULL; 8687c478bd9Sstevel@tonic-gate if (udp->addr.len > 0) { 8697c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i], 8707c478bd9Sstevel@tonic-gate &udp->addr); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate DPRINT2(1, "net_poll(%u):" 8737c478bd9Sstevel@tonic-gate " received empty packet" 8747c478bd9Sstevel@tonic-gate " from %s\n", mythreadno, 8757c478bd9Sstevel@tonic-gate uap ? uap : "<unknown>"); 8767c478bd9Sstevel@tonic-gate if (uap) 8777c478bd9Sstevel@tonic-gate free(uap); 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate continue; /* No data */ 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate if (udp->addr.len == 0) { 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * The previous message was larger than 8847c478bd9Sstevel@tonic-gate * MAXLINE, and T_MORE should have been set. 8857c478bd9Sstevel@tonic-gate * Further data needs to be discarded as 8867c478bd9Sstevel@tonic-gate * we've already received MAXLINE. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): discarding packet " 8897c478bd9Sstevel@tonic-gate "exceeds max line size\n", mythreadno); 8907c478bd9Sstevel@tonic-gate continue; 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate net_msg_count++; 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 8967c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 8977c478bd9Sstevel@tonic-gate "remote"); 8987c478bd9Sstevel@tonic-gate continue; 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate buf[udp->udata.len] = '\0'; 9027c478bd9Sstevel@tonic-gate formatnet(&udp->udata, mp); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (Debug) { 9057c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i], &udp->addr); 9067c478bd9Sstevel@tonic-gate DPRINT2(1, "net_poll(%u): received message" 9077c478bd9Sstevel@tonic-gate " from %s\n", mythreadno, 9087c478bd9Sstevel@tonic-gate uap ? uap : "<unknown>"); 9097c478bd9Sstevel@tonic-gate free(uap); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate if ((hinfo = malloc(sizeof (*hinfo))) == NULL || 9127c478bd9Sstevel@tonic-gate (hinfo->addr.buf = 9137c478bd9Sstevel@tonic-gate malloc(udp->addr.len)) == NULL) { 9147c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 9157c478bd9Sstevel@tonic-gate "remote"); 9167c478bd9Sstevel@tonic-gate if (hinfo) { 9177c478bd9Sstevel@tonic-gate free(hinfo); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate free_msg(mp); 9207c478bd9Sstevel@tonic-gate continue; 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate hinfo->ncp = &Ncf[i]; 9247c478bd9Sstevel@tonic-gate hinfo->addr.len = udp->addr.len; 9257c478bd9Sstevel@tonic-gate (void) memcpy(hinfo->addr.buf, udp->addr.buf, 9267c478bd9Sstevel@tonic-gate udp->addr.len); 9277c478bd9Sstevel@tonic-gate mp->ptr = hinfo; 9287c478bd9Sstevel@tonic-gate if (dataq_enqueue(&hnlq, (void *)mp) == -1) { 9297c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 9307c478bd9Sstevel@tonic-gate "remote"); 9317c478bd9Sstevel@tonic-gate free_msg(mp); 9327c478bd9Sstevel@tonic-gate free(hinfo->addr.buf); 9337c478bd9Sstevel@tonic-gate free(hinfo); 9347c478bd9Sstevel@tonic-gate continue; 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate DPRINT3(5, "net_poll(%u): enqueued msg %p " 9370ea5e3a5Sjjj "on queue %p\n", mythreadno, (void *)mp, 9380ea5e3a5Sjjj (void *)&hnlq); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 9427c478bd9Sstevel@tonic-gate return (NULL); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate static void 9467c478bd9Sstevel@tonic-gate usage(void) 9477c478bd9Sstevel@tonic-gate { 9487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9497c478bd9Sstevel@tonic-gate "usage: syslogd [-d] [-t|-T] [-mmarkinterval] [-ppath]" 9507c478bd9Sstevel@tonic-gate " [-fconffile]\n"); 9517c478bd9Sstevel@tonic-gate exit(1); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate static void 9557c478bd9Sstevel@tonic-gate untty(void) 9567c478bd9Sstevel@tonic-gate { 9577c478bd9Sstevel@tonic-gate if (!Debug) 9587c478bd9Sstevel@tonic-gate (void) setsid(); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * generate a log message internally. The original version of syslogd 9637c478bd9Sstevel@tonic-gate * simply called logmsg directly, but because everything is now based 9647c478bd9Sstevel@tonic-gate * on message passing, we need an internal way to generate and queue 9657c478bd9Sstevel@tonic-gate * log messages from within syslogd itself. 9667c478bd9Sstevel@tonic-gate */ 9677c478bd9Sstevel@tonic-gate static int 9687c478bd9Sstevel@tonic-gate logmymsg(int pri, char *msg, int flags, int pending) 9697c478bd9Sstevel@tonic-gate { 9707c478bd9Sstevel@tonic-gate log_message_t *mp; 9717c478bd9Sstevel@tonic-gate pthread_t mythreadno; 9727c478bd9Sstevel@tonic-gate dataq_t *qptr; 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate if (Debug) { 9757c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 9797c478bd9Sstevel@tonic-gate return (-1); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 9837c478bd9Sstevel@tonic-gate mp->pri = pri; 9847c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 9857c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, msg, MAXLINE+1); 9867c478bd9Sstevel@tonic-gate mp->flags = flags; 9877c478bd9Sstevel@tonic-gate (void) time(&mp->ts); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate qptr = pending ? &tmpq : &inputq; 9907c478bd9Sstevel@tonic-gate if (dataq_enqueue(qptr, (void *)mp) == -1) { 9917c478bd9Sstevel@tonic-gate free_msg(mp); 9927c478bd9Sstevel@tonic-gate return (-1); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate DPRINT3(5, "logmymsg(%u): enqueued msg %p on queue %p\n", 9960ea5e3a5Sjjj mythreadno, (void *)mp, (void *)qptr); 9977c478bd9Sstevel@tonic-gate DPRINT2(5, "logmymsg(%u): Message content: %s\n", mythreadno, msg); 9987c478bd9Sstevel@tonic-gate return (0); 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate /* 10027c478bd9Sstevel@tonic-gate * Generate an internal shutdown message 10037c478bd9Sstevel@tonic-gate */ 10047c478bd9Sstevel@tonic-gate static int 10057c478bd9Sstevel@tonic-gate shutdown_msg(void) 10067c478bd9Sstevel@tonic-gate { 10077c478bd9Sstevel@tonic-gate pthread_t mythreadno; 10087c478bd9Sstevel@tonic-gate log_message_t *mp; 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate if (Debug) { 10117c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 10157c478bd9Sstevel@tonic-gate return (-1); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 10197c478bd9Sstevel@tonic-gate mp->flags = SHUTDOWN; 10207c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 10237c478bd9Sstevel@tonic-gate free_msg(mp); 10247c478bd9Sstevel@tonic-gate return (-1); 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate DPRINT3(5, "shutdown_msg(%u): enqueued msg %p on queue %p\n", 10280ea5e3a5Sjjj mythreadno, (void *)mp, (void *)&inputq); 10297c478bd9Sstevel@tonic-gate return (0); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Generate an internal flush message 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate static void 10367c478bd9Sstevel@tonic-gate flushmsg(int flags) 10377c478bd9Sstevel@tonic-gate { 10387c478bd9Sstevel@tonic-gate log_message_t *mp; 10397c478bd9Sstevel@tonic-gate pthread_t mythreadno; 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate if (Debug) { 10427c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 10467c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg"); 10477c478bd9Sstevel@tonic-gate return; 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 10517c478bd9Sstevel@tonic-gate mp->flags = FLUSHMSG | flags; 10527c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 10557c478bd9Sstevel@tonic-gate free_msg(mp); 10567c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg"); 10577c478bd9Sstevel@tonic-gate return; 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate DPRINT4(5, "flush_msg(%u): enqueued msg %p on queue %p, flags " 10610ea5e3a5Sjjj "0x%x\n", mythreadno, (void *)mp, (void *)&inputq, flags); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate /* 10657c478bd9Sstevel@tonic-gate * Do some processing on messages received from the net 10667c478bd9Sstevel@tonic-gate */ 10677c478bd9Sstevel@tonic-gate static void 10687c478bd9Sstevel@tonic-gate formatnet(struct netbuf *nbp, log_message_t *mp) 10697c478bd9Sstevel@tonic-gate { 10707c478bd9Sstevel@tonic-gate char *p; 10717c478bd9Sstevel@tonic-gate int pri; 10727c478bd9Sstevel@tonic-gate pthread_t mythreadno; 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if (Debug) { 10757c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10780ea5e3a5Sjjj DPRINT2(5, "formatnet(%u): called for msg %p\n", mythreadno, 10790ea5e3a5Sjjj (void *)mp); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate mp->flags = NETWORK; 10827c478bd9Sstevel@tonic-gate (void) time(&mp->ts); 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate /* test for special codes */ 10857c478bd9Sstevel@tonic-gate pri = DEFUPRI; 10867c478bd9Sstevel@tonic-gate p = nbp->buf; 10877c478bd9Sstevel@tonic-gate DPRINT2(9, "formatnet(%u): Message content:\n>%s<\n", mythreadno, 10887c478bd9Sstevel@tonic-gate p); 10897c478bd9Sstevel@tonic-gate if (*p == '<' && isdigit(*(p+1))) { 10907c478bd9Sstevel@tonic-gate pri = 0; 10917c478bd9Sstevel@tonic-gate while (isdigit(*++p)) 10927c478bd9Sstevel@tonic-gate pri = 10 * pri + (*p - '0'); 10937c478bd9Sstevel@tonic-gate if (*p == '>') 10947c478bd9Sstevel@tonic-gate ++p; 10957c478bd9Sstevel@tonic-gate if (pri <= 0 || pri >= (LOG_NFACILITIES << 3)) 10967c478bd9Sstevel@tonic-gate pri = DEFUPRI; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate mp->pri = pri; 11007c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, p, MAXLINE+1); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /* 11047c478bd9Sstevel@tonic-gate * Do some processing on messages generated by this host 11057c478bd9Sstevel@tonic-gate * and then enqueue the log message. 11067c478bd9Sstevel@tonic-gate */ 11077c478bd9Sstevel@tonic-gate static void 11087c478bd9Sstevel@tonic-gate formatsys(struct log_ctl *lp, char *msg, int sync) 11097c478bd9Sstevel@tonic-gate { 11107c478bd9Sstevel@tonic-gate char *p, *q; 11117c478bd9Sstevel@tonic-gate char line[MAXLINE + 1]; 11127c478bd9Sstevel@tonic-gate size_t msglen; 11137c478bd9Sstevel@tonic-gate log_message_t *mp; 11147c478bd9Sstevel@tonic-gate char cbuf[30]; 11157c478bd9Sstevel@tonic-gate pthread_t mythreadno; 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate if (Debug) { 11187c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate DPRINT3(3, "formatsys(%u): log_ctl.mid = %d, log_ctl.sid = %d\n", 11227c478bd9Sstevel@tonic-gate mythreadno, lp->mid, lp->sid); 11237c478bd9Sstevel@tonic-gate DPRINT2(9, "formatsys(%u): Message Content:\n>%s<\n", mythreadno, 11247c478bd9Sstevel@tonic-gate msg); 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate /* msglen includes the null termination */ 11277c478bd9Sstevel@tonic-gate msglen = strlen(msg) + 1; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate for (p = msg; *p != '\0'; ) { 11307c478bd9Sstevel@tonic-gate size_t linelen; 11317c478bd9Sstevel@tonic-gate size_t len; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate /* 11347c478bd9Sstevel@tonic-gate * Allocate a log_message_t structure. 11357c478bd9Sstevel@tonic-gate * We should do it here since a single message (msg) 11367c478bd9Sstevel@tonic-gate * could be composed of many lines. 11377c478bd9Sstevel@tonic-gate */ 11387c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 11417c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 11427c478bd9Sstevel@tonic-gate /* 11437c478bd9Sstevel@tonic-gate * Should bail out from the loop. 11447c478bd9Sstevel@tonic-gate */ 11457c478bd9Sstevel@tonic-gate break; 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate mp->flags &= ~NETWORK; 11497c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 11507c478bd9Sstevel@tonic-gate mp->ts = lp->ttime; 11517c478bd9Sstevel@tonic-gate if (lp->flags & SL_LOGONLY) 11527c478bd9Sstevel@tonic-gate mp->flags |= IGN_CONS; 11537c478bd9Sstevel@tonic-gate if (lp->flags & SL_CONSONLY) 11547c478bd9Sstevel@tonic-gate mp->flags |= IGN_FILE; 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate /* extract facility */ 11577c478bd9Sstevel@tonic-gate if ((lp->pri & LOG_FACMASK) == LOG_KERN) { 11587c478bd9Sstevel@tonic-gate (void) sprintf(line, "%.15s ", 11597c478bd9Sstevel@tonic-gate ctime_r(&mp->ts, cbuf) + 4); 11607c478bd9Sstevel@tonic-gate } else { 11617c478bd9Sstevel@tonic-gate (void) sprintf(line, ""); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate linelen = strlen(line); 11657c478bd9Sstevel@tonic-gate q = line + linelen; 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): msglen = %d\n", mythreadno, msglen); 11687c478bd9Sstevel@tonic-gate len = copynl_frwd(q, MAXLINE + 1 - linelen, p, msglen); 11697c478bd9Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): len (copynl_frwd) = %d\n", 11707c478bd9Sstevel@tonic-gate mythreadno, len); 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate p += len; 11737c478bd9Sstevel@tonic-gate msglen -= len; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if (*p == '\n') { 11767c478bd9Sstevel@tonic-gate /* skip newline */ 11777c478bd9Sstevel@tonic-gate p++; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate if (sync && ((lp->pri & LOG_FACMASK) == LOG_KERN)) 11817c478bd9Sstevel@tonic-gate mp->flags |= SYNC_FILE; /* fsync file after write */ 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate if (len != 0) { 11847c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, line, MAXLINE+1); 11857c478bd9Sstevel@tonic-gate mp->pri = lp->pri; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 11887c478bd9Sstevel@tonic-gate free_msg(mp); 11897c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 11907c478bd9Sstevel@tonic-gate break; 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate DPRINT3(5, "formatsys(%u): sys_thread enqueued msg " 11940ea5e3a5Sjjj "%p on queue %p\n", mythreadno, (void *)mp, 11950ea5e3a5Sjjj (void *)&inputq); 11967c478bd9Sstevel@tonic-gate } else 11977c478bd9Sstevel@tonic-gate free_msg(mp); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Log a message to the appropriate log files, users, etc. based on 12037c478bd9Sstevel@tonic-gate * the priority. 12047c478bd9Sstevel@tonic-gate */ 12057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12067c478bd9Sstevel@tonic-gate static void * 12077c478bd9Sstevel@tonic-gate logmsg(void *ap) 12087c478bd9Sstevel@tonic-gate { 12097c478bd9Sstevel@tonic-gate struct filed *f; 12107c478bd9Sstevel@tonic-gate int fac, prilev, flags, refcnt; 12117c478bd9Sstevel@tonic-gate int fake_shutdown, skip_shutdown; 12127c478bd9Sstevel@tonic-gate log_message_t *mp, *save_mp; 12137c478bd9Sstevel@tonic-gate pthread_t mythreadno; 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate if (Debug) { 12167c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate DPRINT1(1, "logmsg(%u): msg dispatcher started\n", mythreadno); 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate fake_shutdown = skip_shutdown = 0; 12227c478bd9Sstevel@tonic-gate save_mp = NULL; 12237c478bd9Sstevel@tonic-gate for (;;) { 12247c478bd9Sstevel@tonic-gate if (save_mp) { 12257c478bd9Sstevel@tonic-gate /* 12267c478bd9Sstevel@tonic-gate * If we have set aside a message in order to fake a 12277c478bd9Sstevel@tonic-gate * SHUTDOWN, use that message before picking from the 12287c478bd9Sstevel@tonic-gate * queue again. 12297c478bd9Sstevel@tonic-gate */ 12307c478bd9Sstevel@tonic-gate mp = save_mp; 12317c478bd9Sstevel@tonic-gate save_mp = NULL; 12327c478bd9Sstevel@tonic-gate } else { 12337c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&inputq, (void **)&mp, 0); 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 12367c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): msg dispatcher dequeued %p from " 12370ea5e3a5Sjjj "queue %p\n", mythreadno, (void *)mp, 12380ea5e3a5Sjjj (void *)&inputq); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* 12417c478bd9Sstevel@tonic-gate * In most cases, if the message traffic is low, logmsg() wakes 12427c478bd9Sstevel@tonic-gate * up when it receives the SHUTDOWN msg, and will sleep until 12437c478bd9Sstevel@tonic-gate * HUP process is complete. However, if the inputq is too 12447c478bd9Sstevel@tonic-gate * long, logmsg() may not receive SHUTDOWN before reconfigure() 12457c478bd9Sstevel@tonic-gate * releases the logger fds, filed and logit threads. That, in 12467c478bd9Sstevel@tonic-gate * turn, will cause logmsg to refer to invalid fileds. 12477c478bd9Sstevel@tonic-gate * 12487c478bd9Sstevel@tonic-gate * logmsg() needs to respond to the SHUTDOWN message within 12497c478bd9Sstevel@tonic-gate * LOOP_INTERVAL seconds when reconfigure() enqueues it. It 12507c478bd9Sstevel@tonic-gate * does so in most cases. When it does not respond in time, 12517c478bd9Sstevel@tonic-gate * logmsg() needs to be in suspended state immediately, since 12527c478bd9Sstevel@tonic-gate * filed may have been invalidated. reconfigure() will set the 12537c478bd9Sstevel@tonic-gate * HUP_SUSP_LOGMSG_REQD bit in hup_state and wait another 12547c478bd9Sstevel@tonic-gate * LOOP_INTERVAL seconds before proceeding. 12557c478bd9Sstevel@tonic-gate * 12567c478bd9Sstevel@tonic-gate * When HUP_SUSP_LOGMSG_REQD is set, we will create a fake 12577c478bd9Sstevel@tonic-gate * SHUTDOWN message, and dispatch it to the various logit 12587c478bd9Sstevel@tonic-gate * threads, and logmsg() itself will suspend. In order to 12597c478bd9Sstevel@tonic-gate * ignore the real SHUTDOWN which will arrive later, we keep a 12607c478bd9Sstevel@tonic-gate * counter (skip_shutdown) and decrement it when the SHUTDOWN 12617c478bd9Sstevel@tonic-gate * message arrives. 12627c478bd9Sstevel@tonic-gate */ 12637c478bd9Sstevel@tonic-gate if ((hup_state & HUP_SUSP_LOGMSG_REQD) && 12647c478bd9Sstevel@tonic-gate (mp->flags & SHUTDOWN) == 0) { 12657c478bd9Sstevel@tonic-gate DPRINT1(3, "logmsg(%u): suspend request\n", 12667c478bd9Sstevel@tonic-gate mythreadno); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate save_mp = mp; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* create a fake SHUTDOWN msg */ 12717c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 12727c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 12737c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 12747c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, 12757c478bd9Sstevel@tonic-gate "unable to shutdown " 12767c478bd9Sstevel@tonic-gate "logger thread"); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate continue; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate mp->flags = SHUTDOWN; 12817c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 12827c478bd9Sstevel@tonic-gate fake_shutdown = 1; 12837c478bd9Sstevel@tonic-gate skip_shutdown++; 12847c478bd9Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): pending SHUTDOWN %d\n", 12857c478bd9Sstevel@tonic-gate mythreadno, skip_shutdown); 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate /* 12897c478bd9Sstevel@tonic-gate * is it a shutdown or flush message ? 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) || (mp->flags & FLUSHMSG)) { 12920ea5e3a5Sjjj (void) pthread_mutex_lock(&mp->msg_mutex); 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) && 12957c478bd9Sstevel@tonic-gate !fake_shutdown && skip_shutdown > 0) { 12967c478bd9Sstevel@tonic-gate skip_shutdown--; 12970ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 12987c478bd9Sstevel@tonic-gate free_msg(mp); 12997c478bd9Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): released late " 13007c478bd9Sstevel@tonic-gate "arrived SHUTDOWN. pending %d\n", 13017c478bd9Sstevel@tonic-gate mythreadno, skip_shutdown); 13027c478bd9Sstevel@tonic-gate continue; 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 13060ea5e3a5Sjjj (void) pthread_mutex_lock(&f->filed_mutex); 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) { 13090ea5e3a5Sjjj (void) pthread_mutex_unlock( 13100ea5e3a5Sjjj &f->filed_mutex); 13117c478bd9Sstevel@tonic-gate continue; 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate f->f_queue_count++; 13157c478bd9Sstevel@tonic-gate mp->refcnt++; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue, 13187c478bd9Sstevel@tonic-gate (void *)mp) == -1) { 13197c478bd9Sstevel@tonic-gate f->f_queue_count--; 13207c478bd9Sstevel@tonic-gate mp->refcnt--; 13210ea5e3a5Sjjj (void) pthread_mutex_unlock( 13220ea5e3a5Sjjj &f->filed_mutex); 13237c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 13267c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, 13277c478bd9Sstevel@tonic-gate "unable to shutdown " 13287c478bd9Sstevel@tonic-gate "logger thread"); 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate continue; 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p " 13340ea5e3a5Sjjj "on queue %p\n", mythreadno, 13350ea5e3a5Sjjj (void *)mp, (void *)&f->f_queue); 13360ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate /* 13407c478bd9Sstevel@tonic-gate * flags value needs to be saved because mp may 13417c478bd9Sstevel@tonic-gate * have been freed before SHUTDOWN test below. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate flags = mp->flags; 13447c478bd9Sstevel@tonic-gate refcnt = mp->refcnt; 13457c478bd9Sstevel@tonic-gate 13460ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 13477c478bd9Sstevel@tonic-gate if (refcnt == 0) 13487c478bd9Sstevel@tonic-gate free_msg(mp); 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate if (flags & SHUTDOWN) { 13510ea5e3a5Sjjj (void) pthread_mutex_lock(&hup_lock); 13527c478bd9Sstevel@tonic-gate while (hup_state != HUP_COMPLETED) { 13537c478bd9Sstevel@tonic-gate hup_state |= HUP_LOGMSG_SUSPENDED; 13547c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&hup_done, 13557c478bd9Sstevel@tonic-gate &hup_lock); 13567c478bd9Sstevel@tonic-gate hup_state &= ~HUP_LOGMSG_SUSPENDED; 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate hup_state = HUP_ACCEPTABLE; 13590ea5e3a5Sjjj (void) pthread_mutex_unlock(&hup_lock); 13607c478bd9Sstevel@tonic-gate fake_shutdown = 0; 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate continue; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate /* 13667c478bd9Sstevel@tonic-gate * Check to see if msg looks non-standard. 13677c478bd9Sstevel@tonic-gate */ 13687c478bd9Sstevel@tonic-gate if ((int)strlen(mp->msg) < 16 || mp->msg[3] != ' ' || 13697c478bd9Sstevel@tonic-gate mp->msg[6] != ' ' || mp->msg[9] != ':' || 13707c478bd9Sstevel@tonic-gate mp->msg[12] != ':' || mp->msg[15] != ' ') 13717c478bd9Sstevel@tonic-gate mp->flags |= ADDDATE; 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate /* extract facility and priority level */ 13747c478bd9Sstevel@tonic-gate fac = (mp->pri & LOG_FACMASK) >> 3; 13757c478bd9Sstevel@tonic-gate if (mp->flags & MARK) 13767c478bd9Sstevel@tonic-gate fac = LOG_NFACILITIES; 13777c478bd9Sstevel@tonic-gate prilev = mp->pri & LOG_PRIMASK; 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate DPRINT3(3, "logmsg(%u): fac = %d, pri = %d\n", 13807c478bd9Sstevel@tonic-gate mythreadno, fac, prilev); 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate /* 13837c478bd9Sstevel@tonic-gate * Because different devices log at different speeds, 13847c478bd9Sstevel@tonic-gate * it's important to hold the mutex for the current 13857c478bd9Sstevel@tonic-gate * message until it's been enqueued to all log files, 13867c478bd9Sstevel@tonic-gate * so the reference count is accurate before any 13877c478bd9Sstevel@tonic-gate * of the log threads can decrement it. 13887c478bd9Sstevel@tonic-gate */ 13897c478bd9Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mp)) 13907c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW) 13910ea5e3a5Sjjj (void) pthread_mutex_lock(&mp->msg_mutex); 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 13947c478bd9Sstevel@tonic-gate /* skip messages that are incorrect priority */ 13957c478bd9Sstevel@tonic-gate if (f->f_pmask[fac] < (unsigned)prilev || 13967c478bd9Sstevel@tonic-gate f->f_pmask[fac] == NOPRI) 13977c478bd9Sstevel@tonic-gate continue; 13987c478bd9Sstevel@tonic-gate if (f->f_queue_count > Q_HIGHWATER_MARK) { 13997c478bd9Sstevel@tonic-gate DPRINT4(5, "logmsg(%u): Dropping message " 14007c478bd9Sstevel@tonic-gate "%p on file %p, count = %d\n", 14010ea5e3a5Sjjj mythreadno, (void *)mp, (void *)f, 14027c478bd9Sstevel@tonic-gate f->f_queue_count); 14037c478bd9Sstevel@tonic-gate continue; 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate /* 14077c478bd9Sstevel@tonic-gate * Need to grab filed_mutex before testing the f_type. 14087c478bd9Sstevel@tonic-gate * Otherwise logit() may set F_UNUSED after the test 14097c478bd9Sstevel@tonic-gate * below, and start pulling out the pending messages. 14107c478bd9Sstevel@tonic-gate */ 14117c478bd9Sstevel@tonic-gate 14120ea5e3a5Sjjj (void) pthread_mutex_lock(&f->filed_mutex); 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED || 14157c478bd9Sstevel@tonic-gate (f->f_type == F_FILE && (mp->flags & IGN_FILE)) || 14167c478bd9Sstevel@tonic-gate (f->f_type == F_CONSOLE && 14177c478bd9Sstevel@tonic-gate (mp->flags & IGN_CONS))) { 14180ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 14197c478bd9Sstevel@tonic-gate continue; 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate f->f_queue_count++; 14237c478bd9Sstevel@tonic-gate mp->refcnt++; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue, (void *)mp) == -1) { 14267c478bd9Sstevel@tonic-gate f->f_queue_count--; 14277c478bd9Sstevel@tonic-gate mp->refcnt--; 14280ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 14297c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 14307c478bd9Sstevel@tonic-gate continue; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p on queue " 14340ea5e3a5Sjjj "%p\n", mythreadno, (void *)mp, 14350ea5e3a5Sjjj (void *)&f->f_queue); 14360ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate refcnt = mp->refcnt; 14390ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 14407c478bd9Sstevel@tonic-gate if (refcnt == 0) 14417c478bd9Sstevel@tonic-gate free_msg(mp); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 14447c478bd9Sstevel@tonic-gate return (NULL); 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate /* 14487c478bd9Sstevel@tonic-gate * function to actually write the log message to the selected file. 14497c478bd9Sstevel@tonic-gate * each file has a logger thread that runs this routine. The function 14507c478bd9Sstevel@tonic-gate * is called with a pointer to its file structure. 14517c478bd9Sstevel@tonic-gate */ 14527c478bd9Sstevel@tonic-gate static void * 14537c478bd9Sstevel@tonic-gate logit(void *ap) 14547c478bd9Sstevel@tonic-gate { 14557c478bd9Sstevel@tonic-gate struct filed *f = ap; 14567c478bd9Sstevel@tonic-gate log_message_t *mp; 14577c478bd9Sstevel@tonic-gate int forwardingloop = 0; 14580ea5e3a5Sjjj const char *errmsg = "logit(%u): %s to %s forwarding loop detected\n"; 14597c478bd9Sstevel@tonic-gate int i, currofst, prevofst, refcnt; 14607c478bd9Sstevel@tonic-gate host_list_t *hlp; 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate assert(f != NULL); 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate DPRINT4(5, "logit(%u): logger started for \"%s\" (queue %p, filed " 14650ea5e3a5Sjjj "%p)\n", f->f_thread, f->f_un.f_fname, (void *)&f->f_queue, 14660ea5e3a5Sjjj (void *)f); 14677c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW); 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate while (f->f_type != F_UNUSED) { 14707c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0); 14717c478bd9Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue " 14720ea5e3a5Sjjj "%p\n", f->f_thread, (void *)mp, (void *)&f->f_queue); 14730ea5e3a5Sjjj (void) pthread_mutex_lock(&f->filed_mutex); 14747c478bd9Sstevel@tonic-gate assert(f->f_queue_count > 0); 14757c478bd9Sstevel@tonic-gate f->f_queue_count--; 14760ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 14777c478bd9Sstevel@tonic-gate assert(mp->refcnt > 0); 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate /* 14807c478bd9Sstevel@tonic-gate * is it a shutdown message ? 14817c478bd9Sstevel@tonic-gate */ 14827c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 14830ea5e3a5Sjjj (void) pthread_mutex_lock(&mp->msg_mutex); 14847c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 14850ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 14867c478bd9Sstevel@tonic-gate if (refcnt == 0) 14877c478bd9Sstevel@tonic-gate free_msg(mp); 14887c478bd9Sstevel@tonic-gate break; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate /* 14927c478bd9Sstevel@tonic-gate * Is it a logsync message? 14937c478bd9Sstevel@tonic-gate */ 14947c478bd9Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | LOGSYNC)) == 14957c478bd9Sstevel@tonic-gate (FLUSHMSG | LOGSYNC)) { 14967c478bd9Sstevel@tonic-gate if (f->f_type != F_FILE) 14977c478bd9Sstevel@tonic-gate goto out; /* nothing to do */ 14987c478bd9Sstevel@tonic-gate (void) close(f->f_file); 14997c478bd9Sstevel@tonic-gate f->f_file = open64(f->f_un.f_fname, 15007c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY); 15017c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 15027c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 15037c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 15047c478bd9Sstevel@tonic-gate f->f_stat.errs++; 15057c478bd9Sstevel@tonic-gate } 15067c478bd9Sstevel@tonic-gate goto out; 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate /* 15107c478bd9Sstevel@tonic-gate * If the message flags include both flush and sync, 15117c478bd9Sstevel@tonic-gate * then just sync the file out to disk if appropriate. 15127c478bd9Sstevel@tonic-gate */ 15137c478bd9Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | SYNC_FILE)) == 15147c478bd9Sstevel@tonic-gate (FLUSHMSG | SYNC_FILE)) { 15157c478bd9Sstevel@tonic-gate if (f->f_type == F_FILE) { 15167c478bd9Sstevel@tonic-gate DPRINT2(5, "logit(%u): got FLUSH|SYNC " 15177c478bd9Sstevel@tonic-gate "for filed %p\n", f->f_thread, 15180ea5e3a5Sjjj (void *)f); 15197c478bd9Sstevel@tonic-gate (void) fsync(f->f_file); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate goto out; 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * Otherwise if it's a standard flush message, write 15267c478bd9Sstevel@tonic-gate * out any saved messages to the file. 15277c478bd9Sstevel@tonic-gate */ 15287c478bd9Sstevel@tonic-gate if ((mp->flags & FLUSHMSG) && (f->f_prevcount > 0)) { 15297c478bd9Sstevel@tonic-gate set_flush_msg(f); 15307c478bd9Sstevel@tonic-gate writemsg(SAVED, f); 15317c478bd9Sstevel@tonic-gate goto out; 15327c478bd9Sstevel@tonic-gate } 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_current.msg, mp->msg, MAXLINE+1); 15357c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_current.host, mp->hlp->hl_hosts[0], 15367c478bd9Sstevel@tonic-gate SYS_NMLN); 15377c478bd9Sstevel@tonic-gate f->f_current.pri = mp->pri; 15387c478bd9Sstevel@tonic-gate f->f_current.flags = mp->flags; 15397c478bd9Sstevel@tonic-gate f->f_current.time = mp->ts; 15407c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 15417c478bd9Sstevel@tonic-gate hlp = mp->hlp; 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16; 15447c478bd9Sstevel@tonic-gate currofst = (f->f_current.flags & ADDDATE) ? 0 : 16; 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate if (f->f_type == F_FORW) { 15477c478bd9Sstevel@tonic-gate /* 15487c478bd9Sstevel@tonic-gate * Should not forward MARK messages, as they are 15497c478bd9Sstevel@tonic-gate * not defined outside of the current system. 15507c478bd9Sstevel@tonic-gate */ 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate if (mp->flags & MARK) { 15537c478bd9Sstevel@tonic-gate DPRINT1(1, "logit(%u): cannot forward " 15547c478bd9Sstevel@tonic-gate "Mark\n", f->f_thread); 15557c478bd9Sstevel@tonic-gate goto out; 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate /* 15597c478bd9Sstevel@tonic-gate * can not forward message if we do 15607c478bd9Sstevel@tonic-gate * not have a host to forward to 15617c478bd9Sstevel@tonic-gate */ 15627c478bd9Sstevel@tonic-gate if (hlp == (host_list_t *)NULL) 15637c478bd9Sstevel@tonic-gate goto out; 15647c478bd9Sstevel@tonic-gate /* 15657c478bd9Sstevel@tonic-gate * a forwarding loop is created on machines 15667c478bd9Sstevel@tonic-gate * with multiple interfaces because the 15677c478bd9Sstevel@tonic-gate * network address of the sender is different 15687c478bd9Sstevel@tonic-gate * to the receiver even though it is the 15697c478bd9Sstevel@tonic-gate * same machine. Instead, if the 15707c478bd9Sstevel@tonic-gate * hostname the source and target are 15717c478bd9Sstevel@tonic-gate * the same the message if thrown away 15727c478bd9Sstevel@tonic-gate */ 15737c478bd9Sstevel@tonic-gate forwardingloop = 0; 15747c478bd9Sstevel@tonic-gate for (i = 0; i < hlp->hl_cnt; i++) { 15757c478bd9Sstevel@tonic-gate if (strcmp(hlp->hl_hosts[i], 15767c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname) == 0) { 15777c478bd9Sstevel@tonic-gate DPRINT3(1, errmsg, f->f_thread, 15787c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname, 15797c478bd9Sstevel@tonic-gate hlp->hl_hosts[i]); 15807c478bd9Sstevel@tonic-gate forwardingloop = 1; 15817c478bd9Sstevel@tonic-gate break; 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate } 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate if (forwardingloop == 1) { 15867c478bd9Sstevel@tonic-gate f->f_stat.cantfwd++; 15877c478bd9Sstevel@tonic-gate goto out; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate f->f_msgflag |= CURRENT_VALID; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate /* check for dup message */ 15947c478bd9Sstevel@tonic-gate if (f->f_type != F_FORW && 15957c478bd9Sstevel@tonic-gate (f->f_msgflag & OLD_VALID) && 15967c478bd9Sstevel@tonic-gate prevofst == currofst && 15977c478bd9Sstevel@tonic-gate (strcmp(f->f_prevmsg.msg + prevofst, 15987c478bd9Sstevel@tonic-gate f->f_current.msg + currofst) == 0) && 15997c478bd9Sstevel@tonic-gate (strcmp(f->f_prevmsg.host, 16007c478bd9Sstevel@tonic-gate f->f_current.host) == 0)) { 16017c478bd9Sstevel@tonic-gate /* a dup */ 16027c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is dup - %p\n", 16030ea5e3a5Sjjj f->f_thread, (void *)mp); 16047c478bd9Sstevel@tonic-gate if (currofst == 16) { 16057c478bd9Sstevel@tonic-gate (void) strncpy(f->f_prevmsg.msg, 16067c478bd9Sstevel@tonic-gate f->f_current.msg, 15); /* update time */ 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate f->f_prevcount++; 16097c478bd9Sstevel@tonic-gate f->f_stat.dups++; 16107c478bd9Sstevel@tonic-gate f->f_stat.total++; 16117c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 16127c478bd9Sstevel@tonic-gate } else { 16137c478bd9Sstevel@tonic-gate /* new: mark or prior dups exist */ 16147c478bd9Sstevel@tonic-gate if (f->f_current.flags & MARK || f->f_prevcount > 0) { 16157c478bd9Sstevel@tonic-gate if (f->f_prevcount > 0 && f->f_type != F_FORW) { 16167c478bd9Sstevel@tonic-gate set_flush_msg(f); 16177c478bd9Sstevel@tonic-gate if (f->f_msgflag & OLD_VALID) { 16187c478bd9Sstevel@tonic-gate writemsg(SAVED, f); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate if (f->f_msgflag & CURRENT_VALID) 16227c478bd9Sstevel@tonic-gate writemsg(CURRENT, f); 16237c478bd9Sstevel@tonic-gate if (!(mp->flags & NOCOPY)) 16247c478bd9Sstevel@tonic-gate copy_msg(f); 16257c478bd9Sstevel@tonic-gate if (f->f_current.flags & MARK) { 16267c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is " 16270ea5e3a5Sjjj "mark - %p)\n", f->f_thread, 16280ea5e3a5Sjjj (void *)mp); 16297c478bd9Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID; 16307c478bd9Sstevel@tonic-gate } else { 16317c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): saving " 16320ea5e3a5Sjjj "message - %p\n", f->f_thread, 16330ea5e3a5Sjjj (void *)mp); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate f->f_stat.total++; 16367c478bd9Sstevel@tonic-gate } else { /* new message */ 16377c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is new " 16380ea5e3a5Sjjj "- %p\n", f->f_thread, (void *)mp); 16397c478bd9Sstevel@tonic-gate writemsg(CURRENT, f); 16407c478bd9Sstevel@tonic-gate if (!(mp->flags & NOCOPY)) 16417c478bd9Sstevel@tonic-gate copy_msg(f); 16427c478bd9Sstevel@tonic-gate f->f_stat.total++; 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate } 16457c478bd9Sstevel@tonic-gate /* 16467c478bd9Sstevel@tonic-gate * if message refcnt goes to zero after we decrement 16477c478bd9Sstevel@tonic-gate * it here, we are the last consumer of the message, 16487c478bd9Sstevel@tonic-gate * and we should free it. We need to hold the lock 16497c478bd9Sstevel@tonic-gate * between decrementing the count and checking for 16507c478bd9Sstevel@tonic-gate * zero so another thread doesn't beat us to it. 16517c478bd9Sstevel@tonic-gate */ 16527c478bd9Sstevel@tonic-gate out: 16530ea5e3a5Sjjj (void) pthread_mutex_lock(&mp->msg_mutex); 16547c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 16550ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 16567c478bd9Sstevel@tonic-gate if (refcnt == 0) 16577c478bd9Sstevel@tonic-gate free_msg(mp); 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate /* register our exit */ 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* 16627c478bd9Sstevel@tonic-gate * Pull out all pending messages, if they exist. 16637c478bd9Sstevel@tonic-gate */ 16647c478bd9Sstevel@tonic-gate 16650ea5e3a5Sjjj (void) pthread_mutex_lock(&f->filed_mutex); 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate while (f->f_queue_count > 0) { 16687c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0); 16697c478bd9Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue " 16707c478bd9Sstevel@tonic-gate "%p\n", 16710ea5e3a5Sjjj f->f_thread, (void *)mp, (void *)&f->f_queue); 16720ea5e3a5Sjjj (void) pthread_mutex_lock(&mp->msg_mutex); 16737c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 16740ea5e3a5Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex); 16757c478bd9Sstevel@tonic-gate if (refcnt == 0) 16767c478bd9Sstevel@tonic-gate free_msg(mp); 16777c478bd9Sstevel@tonic-gate f->f_queue_count--; 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16800ea5e3a5Sjjj (void) pthread_mutex_unlock(&f->filed_mutex); 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate if (f->f_type != F_USERS && f->f_type != F_WALL && 16837c478bd9Sstevel@tonic-gate f->f_type != F_UNUSED) { 16847c478bd9Sstevel@tonic-gate if (f->f_type == F_FORW) 16857c478bd9Sstevel@tonic-gate (void) t_close(f->f_file); 16867c478bd9Sstevel@tonic-gate else 16877c478bd9Sstevel@tonic-gate (void) close(f->f_file); 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate /* 16917c478bd9Sstevel@tonic-gate * Since f_type may have been changed before this point, we need 16927c478bd9Sstevel@tonic-gate * to test orig_type. 16937c478bd9Sstevel@tonic-gate */ 16947c478bd9Sstevel@tonic-gate if (f->f_orig_type == F_FORW) { 16957c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 16990ea5e3a5Sjjj (void) pthread_mutex_lock(&cft); 17007c478bd9Sstevel@tonic-gate --conf_threads; 17010ea5e3a5Sjjj (void) pthread_mutex_unlock(&cft); 17027c478bd9Sstevel@tonic-gate DPRINT1(5, "logit(%u): logging thread exited\n", f->f_thread); 17037c478bd9Sstevel@tonic-gate return (NULL); 17047c478bd9Sstevel@tonic-gate } 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate /* 17077c478bd9Sstevel@tonic-gate * change the previous message to a flush message, stating how 17087c478bd9Sstevel@tonic-gate * many repeats occurred since the last flush 17097c478bd9Sstevel@tonic-gate */ 17107c478bd9Sstevel@tonic-gate static void 17117c478bd9Sstevel@tonic-gate set_flush_msg(struct filed *f) 17127c478bd9Sstevel@tonic-gate { 17137c478bd9Sstevel@tonic-gate char tbuf[10]; 17147c478bd9Sstevel@tonic-gate int prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16; 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate if (f->f_prevcount == 1) 17177c478bd9Sstevel@tonic-gate (void) strncpy(tbuf, "time", sizeof (tbuf)); 17187c478bd9Sstevel@tonic-gate else 17197c478bd9Sstevel@tonic-gate (void) strncpy(tbuf, "times", sizeof (tbuf)); 17207c478bd9Sstevel@tonic-gate 17210ea5e3a5Sjjj (void) snprintf(f->f_prevmsg.msg+prevofst, 17220ea5e3a5Sjjj sizeof (f->f_prevmsg.msg) - prevofst, 17237c478bd9Sstevel@tonic-gate "last message repeated %d %s", f->f_prevcount, tbuf); 17247c478bd9Sstevel@tonic-gate f->f_prevcount = 0; 17257c478bd9Sstevel@tonic-gate f->f_msgflag |= OLD_VALID; 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate /* 17307c478bd9Sstevel@tonic-gate * the actual writing of the message is broken into a separate function 17317c478bd9Sstevel@tonic-gate * because each file has a current and saved message associated with 17327c478bd9Sstevel@tonic-gate * it (for duplicate message detection). It is necessary to be able 17337c478bd9Sstevel@tonic-gate * to write either the saved message or the current message. 17347c478bd9Sstevel@tonic-gate */ 17357c478bd9Sstevel@tonic-gate static void 17367c478bd9Sstevel@tonic-gate writemsg(int selection, struct filed *f) 17377c478bd9Sstevel@tonic-gate { 17387c478bd9Sstevel@tonic-gate char *cp, *p; 17397c478bd9Sstevel@tonic-gate int pri; 17407c478bd9Sstevel@tonic-gate int flags; 17417c478bd9Sstevel@tonic-gate int l; 17427c478bd9Sstevel@tonic-gate time_t ts; 17437c478bd9Sstevel@tonic-gate struct t_unitdata ud; 17447c478bd9Sstevel@tonic-gate char *eomp, *eomp2, *from, *text, *msg; 17457c478bd9Sstevel@tonic-gate char line[MAXLINE*2]; 17467c478bd9Sstevel@tonic-gate char head[MAXLINE+1]; 17477c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE+1]; 17487c478bd9Sstevel@tonic-gate char cbuf[30]; 17497c478bd9Sstevel@tonic-gate char *filtered; 17507c478bd9Sstevel@tonic-gate char *msgid_start, *msgid_end; 17517c478bd9Sstevel@tonic-gate pthread_t mythreadno; 17527c478bd9Sstevel@tonic-gate size_t hlen, filter_len; 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate if (Debug) { 17557c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate switch (selection) { 17597c478bd9Sstevel@tonic-gate default: 17607c478bd9Sstevel@tonic-gate case CURRENT: /* print current message */ 17617c478bd9Sstevel@tonic-gate msg = f->f_current.msg; 17627c478bd9Sstevel@tonic-gate from = f->f_current.host; 17637c478bd9Sstevel@tonic-gate pri = f->f_current.pri; 17647c478bd9Sstevel@tonic-gate flags = f->f_current.flags; 17657c478bd9Sstevel@tonic-gate ts = f->f_current.time; 17667c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 17677c478bd9Sstevel@tonic-gate break; 17687c478bd9Sstevel@tonic-gate case SAVED: /* print saved message */ 17697c478bd9Sstevel@tonic-gate msg = f->f_prevmsg.msg; 17707c478bd9Sstevel@tonic-gate from = f->f_prevmsg.host; 17717c478bd9Sstevel@tonic-gate pri = f->f_prevmsg.pri; 17727c478bd9Sstevel@tonic-gate flags = f->f_prevmsg.flags; 17737c478bd9Sstevel@tonic-gate ts = f->f_prevmsg.time; 17747c478bd9Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID; 17757c478bd9Sstevel@tonic-gate break; 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate if (msg[0] == '\0') 17797c478bd9Sstevel@tonic-gate return; 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate cp = line; 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate if (flags & ADDDATE) 17847c478bd9Sstevel@tonic-gate (void) strncpy(cp, ctime_r(&ts, cbuf) + 4, 15); 17857c478bd9Sstevel@tonic-gate else 17867c478bd9Sstevel@tonic-gate (void) strncpy(cp, msg, 15); 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate line[15] = '\0'; 17897c478bd9Sstevel@tonic-gate (void) strcat(cp, " "); 17907c478bd9Sstevel@tonic-gate (void) strcat(cp, from); 17917c478bd9Sstevel@tonic-gate (void) strcat(cp, " "); 17927c478bd9Sstevel@tonic-gate text = cp + strlen(cp); 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate if (flags & ADDDATE) 17957c478bd9Sstevel@tonic-gate (void) strcat(cp, msg); 17967c478bd9Sstevel@tonic-gate else 17977c478bd9Sstevel@tonic-gate (void) strcat(cp, msg+16); 17987c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text); 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate errno = 0; 18017c478bd9Sstevel@tonic-gate t_errno = 0; 18027c478bd9Sstevel@tonic-gate switch (f->f_type) { 18037c478bd9Sstevel@tonic-gate case F_UNUSED: 18047c478bd9Sstevel@tonic-gate DPRINT1(1, "writemsg(%u): UNUSED\n", mythreadno); 18057c478bd9Sstevel@tonic-gate break; 18067c478bd9Sstevel@tonic-gate case F_FORW: 18077c478bd9Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n", 18087c478bd9Sstevel@tonic-gate mythreadno, msg, TypeNames[f->f_type], 18097c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname); 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate hlen = snprintf(head, sizeof (head), 18127c478bd9Sstevel@tonic-gate "<%d>%.15s ", pri, cp); 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): head = \"%s\"\n", mythreadno, head); 18157c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): hlen = %d\n", mythreadno, hlen); 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate l = strlen(text); 18187c478bd9Sstevel@tonic-gate p = text; 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text); 18217c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(text) = %d\n", mythreadno, l); 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate (void) strncpy(tmpbuf, head, hlen); 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate while (l > 0) { 18267c478bd9Sstevel@tonic-gate size_t len; 18277c478bd9Sstevel@tonic-gate 18287c478bd9Sstevel@tonic-gate len = copy_frwd(tmpbuf + hlen, sizeof (tmpbuf) - hlen, 18297c478bd9Sstevel@tonic-gate p, l); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): tmpbuf = \"%s\"\n", 18327c478bd9Sstevel@tonic-gate mythreadno, tmpbuf); 18337c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): len = %d\n", mythreadno, 18347c478bd9Sstevel@tonic-gate len); 18357c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(tmpbuf) = %d\n", 18367c478bd9Sstevel@tonic-gate mythreadno, strlen(tmpbuf)); 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate ud.opt.buf = NULL; 18397c478bd9Sstevel@tonic-gate ud.opt.len = 0; 18407c478bd9Sstevel@tonic-gate ud.udata.buf = tmpbuf; 18417c478bd9Sstevel@tonic-gate ud.udata.len = len + hlen; 18427c478bd9Sstevel@tonic-gate ud.addr.maxlen = f->f_un.f_forw.f_addr.maxlen; 18437c478bd9Sstevel@tonic-gate ud.addr.buf = f->f_un.f_forw.f_addr.buf; 18447c478bd9Sstevel@tonic-gate ud.addr.len = f->f_un.f_forw.f_addr.len; 18457c478bd9Sstevel@tonic-gate if (t_sndudata(f->f_file, &ud) < 0) { 18467c478bd9Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) && 18477c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) { 18487c478bd9Sstevel@tonic-gate break; 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate (void) t_close(f->f_file); 18517c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 18527c478bd9Sstevel@tonic-gate logerror("t_sndudata"); 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate /* 18557c478bd9Sstevel@tonic-gate * Since it has already failed, it's not worth 18567c478bd9Sstevel@tonic-gate * continuing output from the middle of 18577c478bd9Sstevel@tonic-gate * message string. 18587c478bd9Sstevel@tonic-gate */ 18597c478bd9Sstevel@tonic-gate break; 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate p += len; 18627c478bd9Sstevel@tonic-gate l -= len; 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate break; 18657c478bd9Sstevel@tonic-gate case F_CONSOLE: 18667c478bd9Sstevel@tonic-gate case F_TTY: 18677c478bd9Sstevel@tonic-gate case F_FILE: 18687c478bd9Sstevel@tonic-gate case F_USERS: 18697c478bd9Sstevel@tonic-gate case F_WALL: 18707c478bd9Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n", 18717c478bd9Sstevel@tonic-gate mythreadno, msg, TypeNames[f->f_type], 18727c478bd9Sstevel@tonic-gate ((f->f_type == F_USERS) || (f->f_type == F_WALL)) ? 18737c478bd9Sstevel@tonic-gate "" : f->f_un.f_fname); 18747c478bd9Sstevel@tonic-gate /* 18757c478bd9Sstevel@tonic-gate * filter the string in preparation for writing it 18767c478bd9Sstevel@tonic-gate * save the original for possible forwarding. 18777c478bd9Sstevel@tonic-gate * In case every byte in cp is a control character, 18787c478bd9Sstevel@tonic-gate * allocates large enough buffer for filtered. 18797c478bd9Sstevel@tonic-gate */ 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate filter_len = strlen(cp) * 4 + 1; 18827c478bd9Sstevel@tonic-gate filtered = (char *)malloc(filter_len); 18837c478bd9Sstevel@tonic-gate if (!filtered) { 18847c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 18857c478bd9Sstevel@tonic-gate /* seems we can just return */ 18867c478bd9Sstevel@tonic-gate return; 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate DPRINT3(5, "writemsg(%u): " 18897c478bd9Sstevel@tonic-gate "filtered allocated (%p: %d bytes)\n", 18900ea5e3a5Sjjj mythreadno, (void *)filtered, filter_len); 18917c478bd9Sstevel@tonic-gate /* -3 : we may add "\r\n" to ecomp(filtered) later */ 18927c478bd9Sstevel@tonic-gate filter_string(cp, filtered, filter_len - 3); 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(filtered) = %d\n", 18957c478bd9Sstevel@tonic-gate mythreadno, strlen(filtered)); 18967c478bd9Sstevel@tonic-gate /* 18977c478bd9Sstevel@tonic-gate * If we're writing to the console, strip out the message ID 18987c478bd9Sstevel@tonic-gate * to reduce visual clutter. 18997c478bd9Sstevel@tonic-gate */ 19007c478bd9Sstevel@tonic-gate if ((msgid_start = strstr(filtered, "[ID ")) != NULL && 19017c478bd9Sstevel@tonic-gate (msgid_end = strstr(msgid_start, "] ")) != NULL && 19027c478bd9Sstevel@tonic-gate f->f_type == F_CONSOLE) 19037c478bd9Sstevel@tonic-gate (void) strcpy(msgid_start, msgid_end + 2); 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate eomp = filtered + strlen(filtered); 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate if ((f->f_type == F_USERS) || (f->f_type == F_WALL)) { 19087c478bd9Sstevel@tonic-gate /* CSTYLED */ 19097c478bd9Sstevel@tonic-gate (void) strcat(eomp, "\r\n"); /*lint !e669*/ 19107c478bd9Sstevel@tonic-gate /* 19117c478bd9Sstevel@tonic-gate * Since wallmsg messes with utmpx we need 19127c478bd9Sstevel@tonic-gate * to guarantee single threadedness... 19137c478bd9Sstevel@tonic-gate */ 19147c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&wmp); 19157c478bd9Sstevel@tonic-gate wallmsg(f, from, filtered); 19167c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&wmp); 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* 19197c478bd9Sstevel@tonic-gate * The contents of filtered have been copied 19207c478bd9Sstevel@tonic-gate * out to the struct walldev. We should free it here. 19217c478bd9Sstevel@tonic-gate */ 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate free(filtered); 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate /* exiting the switch */ 19267c478bd9Sstevel@tonic-gate break; 19277c478bd9Sstevel@tonic-gate } else if (f->f_type != F_FILE) { 19287c478bd9Sstevel@tonic-gate /* CSTYLED */ 19297c478bd9Sstevel@tonic-gate (void) strncpy(eomp, "\r\n", 3); /*lint !e669*/ 19307c478bd9Sstevel@tonic-gate } else { 19317c478bd9Sstevel@tonic-gate if ((eomp2 = strchr(filtered, '\r')) != NULL) { 19327c478bd9Sstevel@tonic-gate (void) strncpy(eomp2, "\n", 2); 19337c478bd9Sstevel@tonic-gate } else { 19347c478bd9Sstevel@tonic-gate /* CSTYLED */ 19357c478bd9Sstevel@tonic-gate (void) strncpy(eomp, "\n", 2); /*lint !e669*/ 19367c478bd9Sstevel@tonic-gate } 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate if (write(f->f_file, filtered, strlen(filtered)) < 0) { 19397c478bd9Sstevel@tonic-gate int e = errno; 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) && 19427c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) { 19437c478bd9Sstevel@tonic-gate free(filtered); 19447c478bd9Sstevel@tonic-gate break; 19457c478bd9Sstevel@tonic-gate } 19467c478bd9Sstevel@tonic-gate (void) close(f->f_file); 19477c478bd9Sstevel@tonic-gate /* 19487c478bd9Sstevel@tonic-gate * Check for EBADF on TTY's due 19497c478bd9Sstevel@tonic-gate * to vhangup() XXX 19507c478bd9Sstevel@tonic-gate */ 19517c478bd9Sstevel@tonic-gate if (e == EBADF && f->f_type != F_FILE) { 19527c478bd9Sstevel@tonic-gate f->f_file = open(f->f_un.f_fname, 19537c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY); 19547c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 19557c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 19567c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 19577c478bd9Sstevel@tonic-gate f->f_stat.errs++; 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate untty(); 19607c478bd9Sstevel@tonic-gate } else { 19617c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 19627c478bd9Sstevel@tonic-gate f->f_stat.errs++; 19637c478bd9Sstevel@tonic-gate errno = e; 19647c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 19657c478bd9Sstevel@tonic-gate } 19667c478bd9Sstevel@tonic-gate } else if (flags & SYNC_FILE) 19677c478bd9Sstevel@tonic-gate if (((pri & LOG_FACMASK) >> 3) == LOG_KERN) 19687c478bd9Sstevel@tonic-gate (void) fsync(f->f_file); 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): freeing filtered (%p)\n", 19710ea5e3a5Sjjj mythreadno, (void *)filtered); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate free(filtered); 19747c478bd9Sstevel@tonic-gate break; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate /* 19797c478bd9Sstevel@tonic-gate * WALLMSG -- Write a message to the world at large 19807c478bd9Sstevel@tonic-gate * 19817c478bd9Sstevel@tonic-gate * Write the specified message to either the entire 19827c478bd9Sstevel@tonic-gate * world, or a list of approved users. 19837c478bd9Sstevel@tonic-gate */ 19847c478bd9Sstevel@tonic-gate static void 19857c478bd9Sstevel@tonic-gate wallmsg(struct filed *f, char *from, char *msg) 19867c478bd9Sstevel@tonic-gate { 19877c478bd9Sstevel@tonic-gate int i; 19887c478bd9Sstevel@tonic-gate size_t len, clen; 19897c478bd9Sstevel@tonic-gate char *buf = NULL; 19907c478bd9Sstevel@tonic-gate struct utmpx *utxp; 19917c478bd9Sstevel@tonic-gate time_t now; 19927c478bd9Sstevel@tonic-gate char line[512], dev[100]; 19937c478bd9Sstevel@tonic-gate char cp[MAXLINE+1]; 19947c478bd9Sstevel@tonic-gate struct stat statbuf; 19957c478bd9Sstevel@tonic-gate walldev_t *w; 19967c478bd9Sstevel@tonic-gate char cbuf[30]; 19977c478bd9Sstevel@tonic-gate pthread_t mythreadno; 19987c478bd9Sstevel@tonic-gate 19997c478bd9Sstevel@tonic-gate if (Debug) { 20007c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate if (access(UTMPX_FILE, R_OK) != 0 || stat(UTMPX_FILE, &statbuf) != 0) { 20047c478bd9Sstevel@tonic-gate logerror(UTMPX_FILE); 20057c478bd9Sstevel@tonic-gate return; 20067c478bd9Sstevel@tonic-gate } else if (statbuf.st_uid != 0 || (statbuf.st_mode & 07777) != 0644) { 20070ea5e3a5Sjjj (void) snprintf(line, sizeof (line), "%s %s", UTMPX_FILE, 20087c478bd9Sstevel@tonic-gate "not owned by root or not mode 644.\n" 20097c478bd9Sstevel@tonic-gate "This file must be owned by root " 20107c478bd9Sstevel@tonic-gate "and not writable by\n" 20117c478bd9Sstevel@tonic-gate "anyone other than root. This alert is being " 20127c478bd9Sstevel@tonic-gate "dropped because of\n" 20137c478bd9Sstevel@tonic-gate "this problem."); 20147c478bd9Sstevel@tonic-gate logerror(line); 20157c478bd9Sstevel@tonic-gate return; 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate if (f->f_type == F_WALL) { 20197c478bd9Sstevel@tonic-gate (void) time(&now); 20207c478bd9Sstevel@tonic-gate len = snprintf(line, sizeof (line), 20217c478bd9Sstevel@tonic-gate "\r\n\7Message from syslogd@%s " 20227c478bd9Sstevel@tonic-gate "at %.24s ...\r\n", from, ctime_r(&now, cbuf)); 20237c478bd9Sstevel@tonic-gate len += strlen(msg + 16); 20247c478bd9Sstevel@tonic-gate buf = (char *)malloc(len + 1); 20257c478bd9Sstevel@tonic-gate if (!buf) { 20267c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 20277c478bd9Sstevel@tonic-gate return; 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate DPRINT3(5, "wallmsg(%u): buf allocated (%p: %d bytes)\n", 20300ea5e3a5Sjjj mythreadno, (void *)buf, len + 1); 20317c478bd9Sstevel@tonic-gate (void) strcpy(buf, line); 20327c478bd9Sstevel@tonic-gate (void) strcat(buf, msg + 16); 20337c478bd9Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), buf, len); 20347c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n", 20357c478bd9Sstevel@tonic-gate mythreadno, clen); 20367c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): freeing buf (%p)\n", 20370ea5e3a5Sjjj mythreadno, (void *)buf); 20387c478bd9Sstevel@tonic-gate free(buf); 20397c478bd9Sstevel@tonic-gate } else { 20407c478bd9Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), msg, strlen(msg)); 20417c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n", 20427c478bd9Sstevel@tonic-gate mythreadno, clen); 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate /* scan the user login file */ 20457c478bd9Sstevel@tonic-gate setutxent(); 20467c478bd9Sstevel@tonic-gate while ((utxp = getutxent()) != NULL) { 20477c478bd9Sstevel@tonic-gate /* is this slot used? */ 20487c478bd9Sstevel@tonic-gate if (utxp->ut_name[0] == '\0' || 20497c478bd9Sstevel@tonic-gate utxp->ut_line[0] == '\0' || 20507c478bd9Sstevel@tonic-gate utxp->ut_type != USER_PROCESS) 20517c478bd9Sstevel@tonic-gate continue; 20527c478bd9Sstevel@tonic-gate /* should we send the message to this user? */ 20537c478bd9Sstevel@tonic-gate if (f->f_type == F_USERS) { 20547c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES; i++) { 20557c478bd9Sstevel@tonic-gate if (!f->f_un.f_uname[i][0]) { 20567c478bd9Sstevel@tonic-gate i = MAXUNAMES; 20577c478bd9Sstevel@tonic-gate break; 20587c478bd9Sstevel@tonic-gate } 20597c478bd9Sstevel@tonic-gate if (strncmp(f->f_un.f_uname[i], 20607c478bd9Sstevel@tonic-gate utxp->ut_name, UNAMESZ) == 0) 20617c478bd9Sstevel@tonic-gate break; 20627c478bd9Sstevel@tonic-gate } 20637c478bd9Sstevel@tonic-gate if (i >= MAXUNAMES) 20647c478bd9Sstevel@tonic-gate continue; 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate /* compute the device name */ 20687c478bd9Sstevel@tonic-gate if (utxp->ut_line[0] == '/') { 20697c478bd9Sstevel@tonic-gate (void) strncpy(dev, utxp->ut_line, UDEVSZ); 20707c478bd9Sstevel@tonic-gate } else { 20717c478bd9Sstevel@tonic-gate (void) strcpy(dev, "/dev/"); 20727c478bd9Sstevel@tonic-gate (void) strncat(dev, utxp->ut_line, UDEVSZ); 20737c478bd9Sstevel@tonic-gate } 20747c478bd9Sstevel@tonic-gate DPRINT2(1, "wallmsg(%u): write to '%s'\n", mythreadno, 20757c478bd9Sstevel@tonic-gate dev); 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate if ((w = malloc(sizeof (walldev_t))) != NULL) { 20787c478bd9Sstevel@tonic-gate int rc; 20797c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&w->thread_attr); 20807c478bd9Sstevel@tonic-gate (void) pthread_attr_setdetachstate(&w->thread_attr, 20817c478bd9Sstevel@tonic-gate PTHREAD_CREATE_DETACHED); 20827c478bd9Sstevel@tonic-gate (void) strncpy(w->dev, dev, PATH_MAX); 20837c478bd9Sstevel@tonic-gate (void) strncpy(w->msg, cp, MAXLINE+1); 20847c478bd9Sstevel@tonic-gate (void) strncpy(w->ut_name, utxp->ut_name, 20857c478bd9Sstevel@tonic-gate sizeof (w->ut_name)); 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate if ((rc = pthread_create(&w->thread, &w->thread_attr, 20887c478bd9Sstevel@tonic-gate writetodev, (void *) w)) != 0) { 20897c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): wallmsg thread " 20907c478bd9Sstevel@tonic-gate "create failed rc = %d\n", 20917c478bd9Sstevel@tonic-gate mythreadno, rc); 20927c478bd9Sstevel@tonic-gate free(w); 20937c478bd9Sstevel@tonic-gate break; 20947c478bd9Sstevel@tonic-gate } 20957c478bd9Sstevel@tonic-gate } else { 20967c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message to user"); 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate } 20997c478bd9Sstevel@tonic-gate /* close the user login file */ 21007c478bd9Sstevel@tonic-gate endutxent(); 21017c478bd9Sstevel@tonic-gate } 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate /* 21047c478bd9Sstevel@tonic-gate * Each time we need to write to a tty device (a potentially expensive 21057c478bd9Sstevel@tonic-gate * or long-running operation) this routine gets called as a new 21067c478bd9Sstevel@tonic-gate * detached, unbound thread. This allows writes to many devices 21077c478bd9Sstevel@tonic-gate * to proceed nearly in parallel, without having to resort to 21087c478bd9Sstevel@tonic-gate * asynchronous I/O or forking. 21097c478bd9Sstevel@tonic-gate */ 21107c478bd9Sstevel@tonic-gate static void * 21117c478bd9Sstevel@tonic-gate writetodev(void *ap) 21127c478bd9Sstevel@tonic-gate { 21137c478bd9Sstevel@tonic-gate walldev_t *w = ap; 21147c478bd9Sstevel@tonic-gate int ttyf; 21157c478bd9Sstevel@tonic-gate int len; 21167c478bd9Sstevel@tonic-gate struct stat statb; 21177c478bd9Sstevel@tonic-gate struct passwd pw, *pwp; 21187c478bd9Sstevel@tonic-gate char pwbuf[MAXLINE]; 21197c478bd9Sstevel@tonic-gate pthread_t mythreadno; 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate if (Debug) { 21227c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread started\n", 21267c478bd9Sstevel@tonic-gate mythreadno); 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate len = strlen(w->msg); 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate ttyf = open(w->dev, O_WRONLY|O_NOCTTY|O_NDELAY); 21317c478bd9Sstevel@tonic-gate if (ttyf >= 0) { 21327c478bd9Sstevel@tonic-gate if (fstat(ttyf, &statb) != 0) { 21337c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't stat '%s'\n", 21347c478bd9Sstevel@tonic-gate mythreadno, w->dev); 21357c478bd9Sstevel@tonic-gate errno = 0; 21367c478bd9Sstevel@tonic-gate logerror("Can't stat '%s'", w->dev); 21377c478bd9Sstevel@tonic-gate } else if (!(statb.st_mode & S_IWRITE)) { 21387c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't write to " 21397c478bd9Sstevel@tonic-gate "'%s'\n", mythreadno, w->dev); 21407c478bd9Sstevel@tonic-gate } else if (!isatty(ttyf)) { 21417c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): '%s' not a tty\n", 21427c478bd9Sstevel@tonic-gate mythreadno, w->dev); 21437c478bd9Sstevel@tonic-gate /* 21447c478bd9Sstevel@tonic-gate * We might hit dtremote here. Don't generate 21457c478bd9Sstevel@tonic-gate * error message. 21467c478bd9Sstevel@tonic-gate */ 21477c478bd9Sstevel@tonic-gate } else if (getpwuid_r(statb.st_uid, &pw, pwbuf, 21487c478bd9Sstevel@tonic-gate sizeof (pwbuf), &pwp) != 0) { 21497c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't determine owner " 21507c478bd9Sstevel@tonic-gate "of '%s'\n", mythreadno, w->dev); 21517c478bd9Sstevel@tonic-gate errno = 0; 21527c478bd9Sstevel@tonic-gate logerror("Can't determine owner of '%s'", w->dev); 21537c478bd9Sstevel@tonic-gate } else if (strncmp(pw.pw_name, w->ut_name, UNAMESZ) != 0) { 21547c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Bad terminal owner '%s'" 21557c478bd9Sstevel@tonic-gate "\n", mythreadno, w->dev); 21567c478bd9Sstevel@tonic-gate errno = 0; 21577c478bd9Sstevel@tonic-gate logerror("%s %s owns '%s' %s %.*s", 21587c478bd9Sstevel@tonic-gate "Bad terminal owner;", pw.pw_name, w->dev, 21597c478bd9Sstevel@tonic-gate "but utmpx says", UNAMESZ, w->ut_name); 21607c478bd9Sstevel@tonic-gate } else if (write(ttyf, w->msg, len) != len) { 21617c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Write failed to " 21627c478bd9Sstevel@tonic-gate "'%s'\n", mythreadno, w->dev); 21637c478bd9Sstevel@tonic-gate errno = 0; 21647c478bd9Sstevel@tonic-gate logerror("Write failed to '%s'", w->dev); 21657c478bd9Sstevel@tonic-gate } 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): write to '%s' succeeded\n", 21687c478bd9Sstevel@tonic-gate mythreadno, w->dev); 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate (void) close(ttyf); 21717c478bd9Sstevel@tonic-gate } else { 21727c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't open '%s'\n", 21737c478bd9Sstevel@tonic-gate mythreadno, w->dev); 21747c478bd9Sstevel@tonic-gate } 21757c478bd9Sstevel@tonic-gate 21760ea5e3a5Sjjj (void) pthread_attr_destroy(&w->thread_attr); 21777c478bd9Sstevel@tonic-gate free(w); 21787c478bd9Sstevel@tonic-gate 21797c478bd9Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread exiting\n", 21807c478bd9Sstevel@tonic-gate mythreadno); 21817c478bd9Sstevel@tonic-gate 21827c478bd9Sstevel@tonic-gate pthread_exit(0); 21837c478bd9Sstevel@tonic-gate return (NULL); 21847c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 21857c478bd9Sstevel@tonic-gate } 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate /* 21887c478bd9Sstevel@tonic-gate * Return a printable representation of a host address. If unable to 21897c478bd9Sstevel@tonic-gate * look up hostname, format the numeric address for display instead. 21907c478bd9Sstevel@tonic-gate * 21917c478bd9Sstevel@tonic-gate * First calls hnc_lookup to see if there is valid cache entry for 21927c478bd9Sstevel@tonic-gate * given network address. If it failed, cvthname looks up hostname, 21937c478bd9Sstevel@tonic-gate * and push the results into the hostname cache. 21947c478bd9Sstevel@tonic-gate */ 21957c478bd9Sstevel@tonic-gate static host_list_t * 21967c478bd9Sstevel@tonic-gate cvthname(struct netbuf *nbp, struct netconfig *ncp, char *failsafe_addr) 21977c478bd9Sstevel@tonic-gate { 21987c478bd9Sstevel@tonic-gate int i; 21997c478bd9Sstevel@tonic-gate host_list_t *h; 22007c478bd9Sstevel@tonic-gate struct nd_hostservlist *hsp; 22017c478bd9Sstevel@tonic-gate struct nd_hostserv *hspp; 22027c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2203293d1fc4Spd155743 int hindex; 22047c478bd9Sstevel@tonic-gate char *uap; 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate if (Debug) { 22077c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 22087c478bd9Sstevel@tonic-gate } 22097c478bd9Sstevel@tonic-gate 22107c478bd9Sstevel@tonic-gate if (Debug) 22117c478bd9Sstevel@tonic-gate uap = taddr2uaddr(ncp, nbp); 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): looking up hostname for %s\n", 22147c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 22157c478bd9Sstevel@tonic-gate 2216293d1fc4Spd155743 if ((h = hnc_lookup(nbp, ncp, &hindex)) != NULL) { 22177c478bd9Sstevel@tonic-gate DPRINT4(2, "cvthname(%u): Cache found %p for %s (%s)\n", 22180ea5e3a5Sjjj mythreadno, (void *)h, uap ? uap : "<unknown>", 22197c478bd9Sstevel@tonic-gate h->hl_hosts[0]); 22207c478bd9Sstevel@tonic-gate return (h); 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): No cache found for %s\n", 22237c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate if (Debug) 22267c478bd9Sstevel@tonic-gate free(uap); 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 22297c478bd9Sstevel@tonic-gate return (NULL); 22307c478bd9Sstevel@tonic-gate } 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate /* memory allocation failure here is fatal */ 22337c478bd9Sstevel@tonic-gate if ((h = malloc(sizeof (host_list_t))) == NULL) { 22347c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 22357c478bd9Sstevel@tonic-gate return (NULL); 22367c478bd9Sstevel@tonic-gate } 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate if (netdir_getbyaddr(ncp, &hsp, nbp) == 0) { 22397c478bd9Sstevel@tonic-gate if (hsp->h_cnt <= 0) { 22407c478bd9Sstevel@tonic-gate out: netdir_free((void *)hsp, ND_HOSTSERVLIST); 22417c478bd9Sstevel@tonic-gate free(h); 22427c478bd9Sstevel@tonic-gate return (NULL); 22437c478bd9Sstevel@tonic-gate } 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate hspp = hsp->h_hostservs; 22467c478bd9Sstevel@tonic-gate h->hl_cnt = hsp->h_cnt; 22477c478bd9Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *) * (h->hl_cnt)); 22487c478bd9Sstevel@tonic-gate if (h->hl_hosts == NULL) { 22497c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 22507c478bd9Sstevel@tonic-gate goto out; 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): Found %d hostnames\n", 22547c478bd9Sstevel@tonic-gate mythreadno, h->hl_cnt); 22557c478bd9Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) { 22567c478bd9Sstevel@tonic-gate h->hl_hosts[i] = (char *) 22577c478bd9Sstevel@tonic-gate malloc(sizeof (char) * (strlen(hspp->h_host) + 1)); 22587c478bd9Sstevel@tonic-gate if (h->hl_hosts[i] == NULL) { 22597c478bd9Sstevel@tonic-gate int j; 22607c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 22617c478bd9Sstevel@tonic-gate free(h->hl_hosts[j]); 22627c478bd9Sstevel@tonic-gate } 22637c478bd9Sstevel@tonic-gate free(h->hl_hosts); 22647c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 22657c478bd9Sstevel@tonic-gate goto out; 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate (void) strcpy(h->hl_hosts[i], hspp->h_host); 22687c478bd9Sstevel@tonic-gate hspp++; 22697c478bd9Sstevel@tonic-gate } 22707c478bd9Sstevel@tonic-gate netdir_free((void *)hsp, ND_HOSTSERVLIST); 22717c478bd9Sstevel@tonic-gate } else { /* unknown address */ 22727c478bd9Sstevel@tonic-gate h->hl_cnt = 1; 22737c478bd9Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *)); 22747c478bd9Sstevel@tonic-gate if (h->hl_hosts == NULL) { 22757c478bd9Sstevel@tonic-gate free(h); 22767c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 22777c478bd9Sstevel@tonic-gate return (NULL); 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate h->hl_hosts[0] = (char *)malloc(strlen(failsafe_addr) + 3); 22807c478bd9Sstevel@tonic-gate if (h->hl_hosts[0] == NULL) { 22817c478bd9Sstevel@tonic-gate free(h->hl_hosts); 22827c478bd9Sstevel@tonic-gate free(h); 22837c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 22847c478bd9Sstevel@tonic-gate return (NULL); 22857c478bd9Sstevel@tonic-gate } 22860ea5e3a5Sjjj /*LINTED*/ 22877c478bd9Sstevel@tonic-gate (void) sprintf(h->hl_hosts[0], "[%s]", failsafe_addr); 22887c478bd9Sstevel@tonic-gate DPRINT2(1, "cvthname(%u): Hostname lookup failed " 22897c478bd9Sstevel@tonic-gate "- using address %s instead\n", 22907c478bd9Sstevel@tonic-gate mythreadno, h->hl_hosts[0]); 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate h->hl_refcnt = 1; 22947c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&h->hl_mutex, NULL) != 0) { 22957c478bd9Sstevel@tonic-gate logerror("pthread_mutex_init failed"); 22967c478bd9Sstevel@tonic-gate /* This host_list won't be shared by the cache. */ 22977c478bd9Sstevel@tonic-gate return (h); 22987c478bd9Sstevel@tonic-gate } 2299293d1fc4Spd155743 hnc_register(nbp, ncp, h, hindex); 23007c478bd9Sstevel@tonic-gate DPRINT3(2, "cvthname(%u): returning %p for %s\n", 23010ea5e3a5Sjjj mythreadno, (void *)h, h->hl_hosts[0]); 23027c478bd9Sstevel@tonic-gate return (h); 23037c478bd9Sstevel@tonic-gate } 23047c478bd9Sstevel@tonic-gate 23057c478bd9Sstevel@tonic-gate /* 23067c478bd9Sstevel@tonic-gate * Print syslogd errors some place. Need to be careful here, because 23077c478bd9Sstevel@tonic-gate * this routine is called at times when we're not initialized and 23087c478bd9Sstevel@tonic-gate * ready to log messages...in this case, fall back to using the console. 23097c478bd9Sstevel@tonic-gate */ 23107c478bd9Sstevel@tonic-gate void 23117c478bd9Sstevel@tonic-gate logerror(const char *type, ...) 23127c478bd9Sstevel@tonic-gate { 23137c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 23147c478bd9Sstevel@tonic-gate pthread_t mythreadno; 23157c478bd9Sstevel@tonic-gate int flag; 23167c478bd9Sstevel@tonic-gate va_list ap; 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate if (Debug) { 23197c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 23207c478bd9Sstevel@tonic-gate } 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate va_start(ap, type); 23237c478bd9Sstevel@tonic-gate logerror_format(type, buf, ap); 23247c478bd9Sstevel@tonic-gate va_end(ap); 23257c478bd9Sstevel@tonic-gate DPRINT2(1, "logerror(%u): %s\n", mythreadno, buf); 23267c478bd9Sstevel@tonic-gate 23270ea5e3a5Sjjj (void) pthread_mutex_lock(&logerror_lock); 23287c478bd9Sstevel@tonic-gate if (!interrorlog) { 23297c478bd9Sstevel@tonic-gate flag = 0; 23307c478bd9Sstevel@tonic-gate if (logerror_to_console(1, buf) == 0) { 23317c478bd9Sstevel@tonic-gate /* has written to the console */ 23327c478bd9Sstevel@tonic-gate flag = IGN_CONS; 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate (void) logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE|flag, 1); 23357c478bd9Sstevel@tonic-gate } else { 23367c478bd9Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE, 0) == -1) { 23377c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, buf); 23387c478bd9Sstevel@tonic-gate } 23397c478bd9Sstevel@tonic-gate } 23400ea5e3a5Sjjj (void) pthread_mutex_unlock(&logerror_lock); 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate errno = 0; 23437c478bd9Sstevel@tonic-gate t_errno = 0; 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate static void 23477c478bd9Sstevel@tonic-gate logerror_format(const char *type, char *buf, va_list ap) 23487c478bd9Sstevel@tonic-gate { 23497c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE + 1]; 23507c478bd9Sstevel@tonic-gate pthread_t mythreadno; 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate if (Debug) { 23537c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 23547c478bd9Sstevel@tonic-gate } 23557c478bd9Sstevel@tonic-gate 23567c478bd9Sstevel@tonic-gate (void) vsnprintf(tmpbuf, MAXLINE, type, ap); 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate if (t_errno == 0 || t_errno == TSYSERR) { 23597c478bd9Sstevel@tonic-gate char *errstr; 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate if (errno == 0) { 23627c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %.*s", 23637c478bd9Sstevel@tonic-gate MAXLINE, tmpbuf); 23647c478bd9Sstevel@tonic-gate } else if ((errstr = strerror(errno)) == (char *)NULL) { 23657c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: error" 23667c478bd9Sstevel@tonic-gate " %d", tmpbuf, errno); 23677c478bd9Sstevel@tonic-gate } else { 23687c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s", 23697c478bd9Sstevel@tonic-gate tmpbuf, errstr); 23707c478bd9Sstevel@tonic-gate } 23717c478bd9Sstevel@tonic-gate } else { 23727c478bd9Sstevel@tonic-gate if (t_errno > t_nerr) { 23737c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s:" 23747c478bd9Sstevel@tonic-gate " t_error %d", tmpbuf, t_errno); 23757c478bd9Sstevel@tonic-gate } else { 23767c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s", 23777c478bd9Sstevel@tonic-gate tmpbuf, t_errlist[t_errno]); 23787c478bd9Sstevel@tonic-gate } 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate DPRINT2(5, "logerror_format(%u): out %s\n", mythreadno, buf); 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate static int 23857c478bd9Sstevel@tonic-gate logerror_to_console(int nonblock, const char *buf) 23867c478bd9Sstevel@tonic-gate { 23877c478bd9Sstevel@tonic-gate int cfd, modes; 23887c478bd9Sstevel@tonic-gate pthread_t mythreadno; 23897c478bd9Sstevel@tonic-gate int ret = 0, len; 23907c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE + 1]; 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate if (Debug) { 23937c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 23947c478bd9Sstevel@tonic-gate } 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate DPRINT2(1, "logerror_to_console(%u): %s\n", mythreadno, buf); 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate /* 23997c478bd9Sstevel@tonic-gate * must use open here instead of fopen, because 24007c478bd9Sstevel@tonic-gate * we need the O_NOCTTY behavior - otherwise we 24017c478bd9Sstevel@tonic-gate * could hang the console at boot time 24027c478bd9Sstevel@tonic-gate */ 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate modes = (nonblock) ? 24057c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK : 24067c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY; 24077c478bd9Sstevel@tonic-gate 24087c478bd9Sstevel@tonic-gate if (((cfd = open(sysmsg, modes)) >= 0) || 24097c478bd9Sstevel@tonic-gate ((cfd = open(ctty, modes)) >= 0)) { 24107c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, MAXLINE, "%s\n", buf); 24117c478bd9Sstevel@tonic-gate len = strlen(tmpbuf); 24127c478bd9Sstevel@tonic-gate if (write(cfd, tmpbuf, len) != len) { 24137c478bd9Sstevel@tonic-gate ret = 1; 24147c478bd9Sstevel@tonic-gate } 24157c478bd9Sstevel@tonic-gate (void) close(cfd); 24167c478bd9Sstevel@tonic-gate } else { 24177c478bd9Sstevel@tonic-gate ret = 1; 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate /* punt */ 24207c478bd9Sstevel@tonic-gate DPRINT1(1, "logerror_console(%u): can't open console\n", 24217c478bd9Sstevel@tonic-gate mythreadno); 24227c478bd9Sstevel@tonic-gate } 24237c478bd9Sstevel@tonic-gate return (ret); 24247c478bd9Sstevel@tonic-gate } 24257c478bd9Sstevel@tonic-gate 24267c478bd9Sstevel@tonic-gate /* 24277c478bd9Sstevel@tonic-gate * copy current message to saved message in filed structure. 24287c478bd9Sstevel@tonic-gate */ 24297c478bd9Sstevel@tonic-gate static void 24307c478bd9Sstevel@tonic-gate copy_msg(struct filed *f) 24317c478bd9Sstevel@tonic-gate { 24327c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.msg, f->f_current.msg, MAXLINE+1); 24337c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.host, f->f_current.host, SYS_NMLN); 24347c478bd9Sstevel@tonic-gate f->f_prevmsg.pri = f->f_current.pri; 24357c478bd9Sstevel@tonic-gate f->f_prevmsg.flags = f->f_current.flags; 24367c478bd9Sstevel@tonic-gate f->f_prevmsg.time = f->f_current.time; 24377c478bd9Sstevel@tonic-gate f->f_msgflag |= OLD_VALID; 24387c478bd9Sstevel@tonic-gate } 24397c478bd9Sstevel@tonic-gate 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate /* 24427c478bd9Sstevel@tonic-gate * function to free a host_list_t struct that was allocated 24437c478bd9Sstevel@tonic-gate * out of cvthname(). There is a special case where we don't 24447c478bd9Sstevel@tonic-gate * free the hostname list in LocalHostName, because that's 24457c478bd9Sstevel@tonic-gate * our own addresses, and we just want to have to look it 24467c478bd9Sstevel@tonic-gate * up once and save it. Also don't free it if it's 24477c478bd9Sstevel@tonic-gate * NullHostName, because that's a special one we use if 24487c478bd9Sstevel@tonic-gate * name service lookup fails. 24497c478bd9Sstevel@tonic-gate * 24507c478bd9Sstevel@tonic-gate * By having hostname cache, now host_list_t will be shared 24517c478bd9Sstevel@tonic-gate * by messages and hostname cache. hl_refcnt is used for 24527c478bd9Sstevel@tonic-gate * the purpose. 24537c478bd9Sstevel@tonic-gate */ 24547c478bd9Sstevel@tonic-gate static void 24557c478bd9Sstevel@tonic-gate freehl(host_list_t *h) 24567c478bd9Sstevel@tonic-gate { 24577c478bd9Sstevel@tonic-gate int i, refcnt; 24587c478bd9Sstevel@tonic-gate pthread_t mythreadno; 24597c478bd9Sstevel@tonic-gate 24607c478bd9Sstevel@tonic-gate if (Debug) { 24617c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate 24640ea5e3a5Sjjj DPRINT2(2, "freehl(%u): releasing %p\n", mythreadno, (void *)h); 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate if (h == NULL || h == &LocalHostName || h == &NullHostName) { 24677c478bd9Sstevel@tonic-gate return; 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate 24700ea5e3a5Sjjj (void) pthread_mutex_lock(&h->hl_mutex); 24717c478bd9Sstevel@tonic-gate refcnt = --h->hl_refcnt; 24720ea5e3a5Sjjj (void) pthread_mutex_unlock(&h->hl_mutex); 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate if (refcnt != 0) { 24757c478bd9Sstevel@tonic-gate DPRINT3(5, "freehl(%u): %p has reference %d\n", 24760ea5e3a5Sjjj mythreadno, (void *)h, refcnt); 24777c478bd9Sstevel@tonic-gate return; 24787c478bd9Sstevel@tonic-gate } 24797c478bd9Sstevel@tonic-gate 24800ea5e3a5Sjjj (void) pthread_mutex_destroy(&h->hl_mutex); 24817c478bd9Sstevel@tonic-gate 24820ea5e3a5Sjjj DPRINT2(5, "freehl(%u): freeing %p\n", mythreadno, (void *)h); 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) { 24857c478bd9Sstevel@tonic-gate free(h->hl_hosts[i]); 24867c478bd9Sstevel@tonic-gate } 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate free(h->hl_hosts); 24897c478bd9Sstevel@tonic-gate free(h); 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate /* 24937c478bd9Sstevel@tonic-gate * Create the door file and the pid file in /var/run. If the filesystem 24947c478bd9Sstevel@tonic-gate * containing /etc is writable, create symlinks /etc/.syslog_door and 24957c478bd9Sstevel@tonic-gate * /etc/syslog.pid to them. On systems that do not support /var/run, create 24967c478bd9Sstevel@tonic-gate * /etc/.syslog_door and /etc/syslog.pid directly. 24977c478bd9Sstevel@tonic-gate * 24987c478bd9Sstevel@tonic-gate * Note: it is not considered fatal to fail to create the pid file or its 24997c478bd9Sstevel@tonic-gate * symlink. Attempts to use them in the usual way will fail, of course, but 25007c478bd9Sstevel@tonic-gate * syslogd will function nicely without it (not so for the door file). 25017c478bd9Sstevel@tonic-gate */ 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate static void 25047c478bd9Sstevel@tonic-gate open_door(void) 25057c478bd9Sstevel@tonic-gate { 25067c478bd9Sstevel@tonic-gate struct stat buf; 25077c478bd9Sstevel@tonic-gate door_info_t info; 25087c478bd9Sstevel@tonic-gate char line[MAXLINE+1]; 25097c478bd9Sstevel@tonic-gate pthread_t mythreadno; 25107c478bd9Sstevel@tonic-gate int err; 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate if (Debug) { 25137c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 25147c478bd9Sstevel@tonic-gate } 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate /* 25177c478bd9Sstevel@tonic-gate * first see if another syslogd is running by trying 25187c478bd9Sstevel@tonic-gate * a door call - if it succeeds, there is already 25197c478bd9Sstevel@tonic-gate * a syslogd process active 25207c478bd9Sstevel@tonic-gate */ 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate if (!DoorCreated) { 25237c478bd9Sstevel@tonic-gate int door; 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate if ((door = open(DoorFileName, O_RDONLY)) >= 0) { 25267c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s opened " 25277c478bd9Sstevel@tonic-gate "successfully\n", mythreadno, DoorFileName); 25287c478bd9Sstevel@tonic-gate 25297c478bd9Sstevel@tonic-gate if (door_info(door, &info) >= 0) { 25307c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): " 25317c478bd9Sstevel@tonic-gate "door_info:info.di_target = %ld\n", 25327c478bd9Sstevel@tonic-gate mythreadno, info.di_target); 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate if (info.di_target > 0) { 25357c478bd9Sstevel@tonic-gate (void) sprintf(line, "syslogd pid %ld" 25367c478bd9Sstevel@tonic-gate " already running. Cannot " 25377c478bd9Sstevel@tonic-gate "start another syslogd pid %ld", 25387c478bd9Sstevel@tonic-gate info.di_target, getpid()); 25397c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): error: " 25407c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 25417c478bd9Sstevel@tonic-gate errno = 0; 25427c478bd9Sstevel@tonic-gate logerror(line); 25437c478bd9Sstevel@tonic-gate exit(1); 25447c478bd9Sstevel@tonic-gate } 25457c478bd9Sstevel@tonic-gate } 25467c478bd9Sstevel@tonic-gate 25477c478bd9Sstevel@tonic-gate (void) close(door); 25487c478bd9Sstevel@tonic-gate } else { 25497c478bd9Sstevel@tonic-gate if (lstat(DoorFileName, &buf) < 0) { 25507c478bd9Sstevel@tonic-gate err = errno; 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): lstat() of %s " 25537c478bd9Sstevel@tonic-gate "failed, errno=%d\n", 25547c478bd9Sstevel@tonic-gate mythreadno, DoorFileName, err); 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate if ((door = creat(DoorFileName, 0644)) < 0) { 25577c478bd9Sstevel@tonic-gate err = errno; 25580ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 25590ea5e3a5Sjjj "creat() of %s failed - fatal", 25600ea5e3a5Sjjj DoorFileName); 25617c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, " 25627c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, 25637c478bd9Sstevel@tonic-gate err); 25647c478bd9Sstevel@tonic-gate errno = err; 25657c478bd9Sstevel@tonic-gate logerror(line); 25667c478bd9Sstevel@tonic-gate delete_doorfiles(); 25677c478bd9Sstevel@tonic-gate exit(1); 25687c478bd9Sstevel@tonic-gate } 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate (void) fchmod(door, 25717c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 25727c478bd9Sstevel@tonic-gate 25737c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): creat() of %s " 25747c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 25757c478bd9Sstevel@tonic-gate DoorFileName); 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate (void) close(door); 25787c478bd9Sstevel@tonic-gate } 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) { 25827c478bd9Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &buf) == 0) { 25837c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s " 25847c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 25857c478bd9Sstevel@tonic-gate OLD_DOORFILE); 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) { 25880ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 25890ea5e3a5Sjjj "%s is a directory - fatal", 25907c478bd9Sstevel@tonic-gate OLD_DOORFILE); 25917c478bd9Sstevel@tonic-gate DPRINT2(1, "open_door(%u): error: " 25927c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 25937c478bd9Sstevel@tonic-gate errno = 0; 25947c478bd9Sstevel@tonic-gate logerror(line); 25957c478bd9Sstevel@tonic-gate delete_doorfiles(); 25967c478bd9Sstevel@tonic-gate exit(1); 25977c478bd9Sstevel@tonic-gate } 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s is not a " 26007c478bd9Sstevel@tonic-gate "directory\n", 26017c478bd9Sstevel@tonic-gate mythreadno, OLD_DOORFILE); 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) { 26047c478bd9Sstevel@tonic-gate err = errno; 26050ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 26060ea5e3a5Sjjj "unlink() of %s failed", 26070ea5e3a5Sjjj OLD_DOORFILE); 26087c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", 26097c478bd9Sstevel@tonic-gate mythreadno, line); 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate if (err != EROFS) { 26127c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): " 26137c478bd9Sstevel@tonic-gate "error: %s, " 26147c478bd9Sstevel@tonic-gate "errno=%d\n", 26157c478bd9Sstevel@tonic-gate mythreadno, line, err); 26167c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 26177c478bd9Sstevel@tonic-gate errno = err; 26187c478bd9Sstevel@tonic-gate logerror(line); 26197c478bd9Sstevel@tonic-gate delete_doorfiles(); 26207c478bd9Sstevel@tonic-gate exit(1); 26217c478bd9Sstevel@tonic-gate } 26227c478bd9Sstevel@tonic-gate 26237c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink " 26247c478bd9Sstevel@tonic-gate "failure OK on RO file " 26257c478bd9Sstevel@tonic-gate "system\n", mythreadno); 26267c478bd9Sstevel@tonic-gate } 26277c478bd9Sstevel@tonic-gate } else { 26287c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't " 26297c478bd9Sstevel@tonic-gate "exist\n", mythreadno, OLD_DOORFILE); 26307c478bd9Sstevel@tonic-gate } 26317c478bd9Sstevel@tonic-gate 26327c478bd9Sstevel@tonic-gate if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) { 26337c478bd9Sstevel@tonic-gate err = errno; 26340ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 26350ea5e3a5Sjjj "symlink %s -> %s failed", OLD_DOORFILE, 26367c478bd9Sstevel@tonic-gate RELATIVE_DOORFILE); 26377c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno, 26387c478bd9Sstevel@tonic-gate line); 26397c478bd9Sstevel@tonic-gate 26407c478bd9Sstevel@tonic-gate if (err != EROFS) { 26417c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, " 26427c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, 26437c478bd9Sstevel@tonic-gate err); 26447c478bd9Sstevel@tonic-gate errno = err; 26457c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 26467c478bd9Sstevel@tonic-gate logerror(line); 26477c478bd9Sstevel@tonic-gate delete_doorfiles(); 26487c478bd9Sstevel@tonic-gate exit(1); 26497c478bd9Sstevel@tonic-gate } 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK " 26527c478bd9Sstevel@tonic-gate "on RO file system\n", mythreadno); 26537c478bd9Sstevel@tonic-gate } else { 26547c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s " 26557c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 26567c478bd9Sstevel@tonic-gate OLD_DOORFILE, RELATIVE_DOORFILE); 26577c478bd9Sstevel@tonic-gate } 26587c478bd9Sstevel@tonic-gate } 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate if ((DoorFd = door_create(server, 0, 26617c478bd9Sstevel@tonic-gate DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { 26627c478bd9Sstevel@tonic-gate err = errno; 26637c478bd9Sstevel@tonic-gate (void) sprintf(line, "door_create() failed - fatal"); 26647c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", 26657c478bd9Sstevel@tonic-gate mythreadno, line, err); 26667c478bd9Sstevel@tonic-gate errno = err; 26677c478bd9Sstevel@tonic-gate logerror(line); 26687c478bd9Sstevel@tonic-gate delete_doorfiles(); 26697c478bd9Sstevel@tonic-gate exit(1); 26707c478bd9Sstevel@tonic-gate } 26717c478bd9Sstevel@tonic-gate (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0); 26727c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): door_create() succeeded, " 26737c478bd9Sstevel@tonic-gate "DoorFd=%d\n", mythreadno, DoorFd); 26747c478bd9Sstevel@tonic-gate 26757c478bd9Sstevel@tonic-gate DoorCreated = 1; 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate (void) fdetach(DoorFileName); /* just in case... */ 26797c478bd9Sstevel@tonic-gate 2680*b13be141Snakanon (void) door_server_create(door_server_pool); 2681*b13be141Snakanon 26827c478bd9Sstevel@tonic-gate if (fattach(DoorFd, DoorFileName) < 0) { 26837c478bd9Sstevel@tonic-gate err = errno; 26840ea5e3a5Sjjj (void) snprintf(line, sizeof (line), "fattach() of fd" 26850ea5e3a5Sjjj " %d to %s failed - fatal", DoorFd, DoorFileName); 26867c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", mythreadno, 26877c478bd9Sstevel@tonic-gate line, err); 26887c478bd9Sstevel@tonic-gate errno = err; 26897c478bd9Sstevel@tonic-gate logerror(line); 26907c478bd9Sstevel@tonic-gate delete_doorfiles(); 26917c478bd9Sstevel@tonic-gate exit(1); 26927c478bd9Sstevel@tonic-gate } 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): attached server() to %s\n", mythreadno, 26957c478bd9Sstevel@tonic-gate DoorFileName); 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate /* 26987c478bd9Sstevel@tonic-gate * create pidfile anyway, so those using it to control 26997c478bd9Sstevel@tonic-gate * syslogd (with kill `cat /etc/syslog.pid` perhaps) 27007c478bd9Sstevel@tonic-gate * don't get broken. 27017c478bd9Sstevel@tonic-gate */ 27027c478bd9Sstevel@tonic-gate 27037c478bd9Sstevel@tonic-gate if (!PidfileCreated) { 27047c478bd9Sstevel@tonic-gate int pidfd; 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate PidfileCreated = 1; 27077c478bd9Sstevel@tonic-gate 27087c478bd9Sstevel@tonic-gate if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644)) 27097c478bd9Sstevel@tonic-gate < 0) { 27107c478bd9Sstevel@tonic-gate err = errno; 27110ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 27120ea5e3a5Sjjj "open() of %s failed", PidFileName); 27137c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n", 27147c478bd9Sstevel@tonic-gate mythreadno, line, err); 27157c478bd9Sstevel@tonic-gate errno = err; 27167c478bd9Sstevel@tonic-gate logerror(line); 27177c478bd9Sstevel@tonic-gate return; 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate (void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 27217c478bd9Sstevel@tonic-gate (void) sprintf(line, "%ld\n", getpid()); 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate if (write(pidfd, line, strlen(line)) < 0) { 27247c478bd9Sstevel@tonic-gate err = errno; 27250ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 27260ea5e3a5Sjjj "write to %s on fd %d failed", PidFileName, pidfd); 27277c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n", 27287c478bd9Sstevel@tonic-gate mythreadno, line, err); 27297c478bd9Sstevel@tonic-gate errno = err; 27307c478bd9Sstevel@tonic-gate logerror(line); 27317c478bd9Sstevel@tonic-gate return; 27327c478bd9Sstevel@tonic-gate } 27337c478bd9Sstevel@tonic-gate 27347c478bd9Sstevel@tonic-gate (void) close(pidfd); 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s created\n", 27377c478bd9Sstevel@tonic-gate mythreadno, PidFileName); 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) { 27407c478bd9Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &buf) == 0) { 27417c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s " 27427c478bd9Sstevel@tonic-gate "succeded\n", mythreadno, OLD_PIDFILE); 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) { 27450ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 27460ea5e3a5Sjjj "file %s is a directory", 27477c478bd9Sstevel@tonic-gate OLD_PIDFILE); 27487c478bd9Sstevel@tonic-gate DPRINT2(1, "open_door(%u): warning: " 27497c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 27507c478bd9Sstevel@tonic-gate errno = 0; 27517c478bd9Sstevel@tonic-gate logerror(line); 27527c478bd9Sstevel@tonic-gate return; 27537c478bd9Sstevel@tonic-gate } 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) { 27567c478bd9Sstevel@tonic-gate err = errno; 27570ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 27580ea5e3a5Sjjj "unlink() of %s failed", 27590ea5e3a5Sjjj OLD_PIDFILE); 27607c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", 27617c478bd9Sstevel@tonic-gate mythreadno, line); 27627c478bd9Sstevel@tonic-gate 27637c478bd9Sstevel@tonic-gate if (err != EROFS) { 27647c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door (%u): " 27657c478bd9Sstevel@tonic-gate "warning: %s, " 27667c478bd9Sstevel@tonic-gate "errno=%d\n", 27677c478bd9Sstevel@tonic-gate mythreadno, line, err); 27687c478bd9Sstevel@tonic-gate errno = err; 27697c478bd9Sstevel@tonic-gate logerror(line); 27707c478bd9Sstevel@tonic-gate return; 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink " 27747c478bd9Sstevel@tonic-gate "failure OK on RO file " 27757c478bd9Sstevel@tonic-gate "system\n", mythreadno); 27767c478bd9Sstevel@tonic-gate } 27777c478bd9Sstevel@tonic-gate } else { 27787c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't " 27797c478bd9Sstevel@tonic-gate "exist\n", mythreadno, OLD_PIDFILE); 27807c478bd9Sstevel@tonic-gate } 27817c478bd9Sstevel@tonic-gate 27827c478bd9Sstevel@tonic-gate if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) { 27837c478bd9Sstevel@tonic-gate err = errno; 27840ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 27850ea5e3a5Sjjj "symlink %s -> %s failed", OLD_PIDFILE, 27867c478bd9Sstevel@tonic-gate RELATIVE_PIDFILE); 27877c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno, 27887c478bd9Sstevel@tonic-gate line); 27897c478bd9Sstevel@tonic-gate 27907c478bd9Sstevel@tonic-gate if (err != EROFS) { 27917c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: " 27927c478bd9Sstevel@tonic-gate "%s, errno=%d\n", mythreadno, 27937c478bd9Sstevel@tonic-gate line, err); 27947c478bd9Sstevel@tonic-gate errno = err; 27957c478bd9Sstevel@tonic-gate logerror(line); 27967c478bd9Sstevel@tonic-gate return; 27977c478bd9Sstevel@tonic-gate } 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK " 28007c478bd9Sstevel@tonic-gate "on RO file system\n", mythreadno); 28017c478bd9Sstevel@tonic-gate return; 28027c478bd9Sstevel@tonic-gate } 28037c478bd9Sstevel@tonic-gate 28047c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s " 28057c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, OLD_PIDFILE, 28067c478bd9Sstevel@tonic-gate RELATIVE_PIDFILE); 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate } 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate /* 28127c478bd9Sstevel@tonic-gate * the 'server' function that we export via the door. It does 28137c478bd9Sstevel@tonic-gate * nothing but return. 28147c478bd9Sstevel@tonic-gate */ 28157c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 28167c478bd9Sstevel@tonic-gate static void 28177c478bd9Sstevel@tonic-gate server(void *cookie, char *argp, size_t arg_size, 28187c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t n) 28197c478bd9Sstevel@tonic-gate { 28207c478bd9Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 28217c478bd9Sstevel@tonic-gate /* NOTREACHED */ 28227c478bd9Sstevel@tonic-gate } 28237c478bd9Sstevel@tonic-gate 2824*b13be141Snakanon /*ARGSUSED*/ 2825*b13be141Snakanon static void * 2826*b13be141Snakanon create_door_thr(void *arg) 2827*b13be141Snakanon { 2828*b13be141Snakanon (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 2829*b13be141Snakanon (void) door_return(NULL, 0, NULL, 0); 2830*b13be141Snakanon 2831*b13be141Snakanon /* 2832*b13be141Snakanon * If there is an error in door_return(), it will return here and 2833*b13be141Snakanon * the thread will exit. Hence we need to decrement door_server_cnt. 2834*b13be141Snakanon */ 2835*b13be141Snakanon (void) pthread_mutex_lock(&door_server_cnt_lock); 2836*b13be141Snakanon door_server_cnt--; 2837*b13be141Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock); 2838*b13be141Snakanon return (NULL); 2839*b13be141Snakanon } 2840*b13be141Snakanon 2841*b13be141Snakanon /* 2842*b13be141Snakanon * Max number of door server threads for syslogd. Since door is used 2843*b13be141Snakanon * to check the health of syslogd, we don't need large number of 2844*b13be141Snakanon * server threads. 2845*b13be141Snakanon */ 2846*b13be141Snakanon #define MAX_DOOR_SERVER_THR 3 2847*b13be141Snakanon 2848*b13be141Snakanon /* 2849*b13be141Snakanon * Manage door server thread pool. 2850*b13be141Snakanon */ 2851*b13be141Snakanon /*ARGSUSED*/ 2852*b13be141Snakanon static void 2853*b13be141Snakanon door_server_pool(door_info_t *dip) 2854*b13be141Snakanon { 2855*b13be141Snakanon (void) pthread_mutex_lock(&door_server_cnt_lock); 2856*b13be141Snakanon if (door_server_cnt <= MAX_DOOR_SERVER_THR && 2857*b13be141Snakanon pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) { 2858*b13be141Snakanon door_server_cnt++; 2859*b13be141Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock); 2860*b13be141Snakanon return; 2861*b13be141Snakanon } 2862*b13be141Snakanon 2863*b13be141Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock); 2864*b13be141Snakanon } 2865*b13be141Snakanon 28667c478bd9Sstevel@tonic-gate /* 28677c478bd9Sstevel@tonic-gate * checkm4 - used to verify that the external utilities that 28687c478bd9Sstevel@tonic-gate * syslogd depends on are where we expect them to be. 28697c478bd9Sstevel@tonic-gate * Returns 0 if all utilities are found, > 0 if any are missing. 28707c478bd9Sstevel@tonic-gate * Also logs errors so user knows what's missing 28717c478bd9Sstevel@tonic-gate */ 28727c478bd9Sstevel@tonic-gate static int 28737c478bd9Sstevel@tonic-gate checkm4(void) 28747c478bd9Sstevel@tonic-gate { 28757c478bd9Sstevel@tonic-gate int notfound = 0; 28767c478bd9Sstevel@tonic-gate int saverrno; 28777c478bd9Sstevel@tonic-gate pthread_t mythreadno; 28787c478bd9Sstevel@tonic-gate 28797c478bd9Sstevel@tonic-gate if (Debug) { 28807c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 28817c478bd9Sstevel@tonic-gate } 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate if (access("/usr/ccs/bin/m4", X_OK) < 0) { 28847c478bd9Sstevel@tonic-gate saverrno = errno; 28857c478bd9Sstevel@tonic-gate logerror("/usr/ccs/bin/m4"); 28867c478bd9Sstevel@tonic-gate DPRINT2(1, "checkm4(%u): /usr/ccs/bin/m4 - access " 28877c478bd9Sstevel@tonic-gate "returned %d\n", mythreadno, saverrno); 28887c478bd9Sstevel@tonic-gate notfound++; 28897c478bd9Sstevel@tonic-gate } 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate return (notfound); 28927c478bd9Sstevel@tonic-gate } 28937c478bd9Sstevel@tonic-gate 28947c478bd9Sstevel@tonic-gate /* 28957c478bd9Sstevel@tonic-gate * INIT -- Initialize syslogd from configuration table, start up 28967c478bd9Sstevel@tonic-gate * input and logger threads. This routine is called only once. 28977c478bd9Sstevel@tonic-gate */ 28987c478bd9Sstevel@tonic-gate static void 28997c478bd9Sstevel@tonic-gate init(void) 29007c478bd9Sstevel@tonic-gate { 29017c478bd9Sstevel@tonic-gate struct utsname *up; 29027c478bd9Sstevel@tonic-gate pthread_attr_t sys_attr, net_attr, log_attr, hnl_attr; 29037c478bd9Sstevel@tonic-gate int nthread; 29047c478bd9Sstevel@tonic-gate pthread_t mythreadno; 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate if (Debug) { 29077c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate DPRINT1(2, "init(%u): initializing\n", mythreadno); 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate /* hand-craft a host_list_t entry for our local host name */ 29137c478bd9Sstevel@tonic-gate if ((up = malloc(sizeof (struct utsname))) == NULL) { 29147c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 29157c478bd9Sstevel@tonic-gate } 29167c478bd9Sstevel@tonic-gate (void) uname(up); 29177c478bd9Sstevel@tonic-gate LocalHostName.hl_cnt = 1; 29187c478bd9Sstevel@tonic-gate if ((LocalHostName.hl_hosts = malloc(sizeof (char *))) == NULL) { 29197c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 29207c478bd9Sstevel@tonic-gate } 29217c478bd9Sstevel@tonic-gate if ((LocalHostName.hl_hosts[0] = strdup(up->nodename)) == NULL) { 29227c478bd9Sstevel@tonic-gate free(LocalHostName.hl_hosts); 29237c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 29247c478bd9Sstevel@tonic-gate } 29257c478bd9Sstevel@tonic-gate free(up); 29267c478bd9Sstevel@tonic-gate /* also hand craft one for use if name resolution fails */ 29277c478bd9Sstevel@tonic-gate NullHostName.hl_cnt = 1; 29287c478bd9Sstevel@tonic-gate if ((NullHostName.hl_hosts = malloc(sizeof (char *))) == NULL) { 29297c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 29307c478bd9Sstevel@tonic-gate } 29317c478bd9Sstevel@tonic-gate if ((NullHostName.hl_hosts[0] = strdup("name lookup failed")) == NULL) { 29327c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 29337c478bd9Sstevel@tonic-gate } 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate hnc_init(0); 29367c478bd9Sstevel@tonic-gate 29377c478bd9Sstevel@tonic-gate /* 29387c478bd9Sstevel@tonic-gate * Note that getnets will allocate network resources, but won't be 29397c478bd9Sstevel@tonic-gate * binding UDP port. This is because, there could be a race 29407c478bd9Sstevel@tonic-gate * condition between door. If we bind here, one syslogd could grab 29417c478bd9Sstevel@tonic-gate * UDP port first, but later another syslogd could take over without 29427c478bd9Sstevel@tonic-gate * getting UDP port but grab the door file. The 2nd syslogd could 29437c478bd9Sstevel@tonic-gate * continue to run without listening network. 29447c478bd9Sstevel@tonic-gate * bindnet() will be called after door was successfully opened. 29457c478bd9Sstevel@tonic-gate */ 29467c478bd9Sstevel@tonic-gate getnets(); 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate /* 29497c478bd9Sstevel@tonic-gate * Start up configured theads 29507c478bd9Sstevel@tonic-gate */ 29517c478bd9Sstevel@tonic-gate conf_init(); 29527c478bd9Sstevel@tonic-gate 29537c478bd9Sstevel@tonic-gate /* 29547c478bd9Sstevel@tonic-gate * allocate thread stacks for the persistant threads 29557c478bd9Sstevel@tonic-gate */ 29567c478bd9Sstevel@tonic-gate nthread = (turnoff == 0) ? 4 : 2; 29577c478bd9Sstevel@tonic-gate 29587c478bd9Sstevel@tonic-gate if ((stack_ptr = alloc_stacks(nthread)) == NULL) { 29597c478bd9Sstevel@tonic-gate logerror("alloc_stacks failed - fatal"); 29607c478bd9Sstevel@tonic-gate exit(1); 29617c478bd9Sstevel@tonic-gate } 29627c478bd9Sstevel@tonic-gate 29637c478bd9Sstevel@tonic-gate if (Debug) { 29647c478bd9Sstevel@tonic-gate dumpstats(STDOUT_FILENO); 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate (void) dataq_init(&inputq); /* init the input queue */ 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate if (pthread_attr_init(&sys_attr) != 0 || 29707c478bd9Sstevel@tonic-gate pthread_attr_init(&log_attr) != 0 || 29717c478bd9Sstevel@tonic-gate pthread_attr_init(&net_attr) != 0 || 2972*b13be141Snakanon pthread_attr_init(&hnl_attr) != 0 || 2973*b13be141Snakanon pthread_attr_init(&door_thr_attr) != 0) { 29747c478bd9Sstevel@tonic-gate logerror("pthread_attr_init failed - fatal"); 29757c478bd9Sstevel@tonic-gate exit(1); 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate 29787c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&sys_attr, PTHREAD_SCOPE_PROCESS); 29797c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&log_attr, PTHREAD_SCOPE_PROCESS); 29807c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&net_attr, PTHREAD_SCOPE_PROCESS); 29817c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&hnl_attr, PTHREAD_SCOPE_PROCESS); 2982*b13be141Snakanon (void) pthread_attr_setscope(&door_thr_attr, PTHREAD_SCOPE_SYSTEM); 2983*b13be141Snakanon (void) pthread_attr_setdetachstate(&door_thr_attr, 2984*b13be141Snakanon PTHREAD_CREATE_DETACHED); 29857c478bd9Sstevel@tonic-gate 29867c478bd9Sstevel@tonic-gate /* 1: logmsg thread */ 29877c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&log_attr, stacksize); 29887c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&log_attr, stack_ptr); 29897c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 29907c478bd9Sstevel@tonic-gate if (pthread_create(&log_thread, &log_attr, logmsg, NULL) != 0) { 29917c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 29927c478bd9Sstevel@tonic-gate exit(1); 29937c478bd9Sstevel@tonic-gate } 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate /* 29967c478bd9Sstevel@tonic-gate * open the log device, and pull up all pending message 29977c478bd9Sstevel@tonic-gate * from the log driver. 29987c478bd9Sstevel@tonic-gate */ 29997c478bd9Sstevel@tonic-gate prepare_sys_poll(); 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate /* 30027c478bd9Sstevel@tonic-gate * Now we can deliver the pending internal error messages. 30037c478bd9Sstevel@tonic-gate */ 30047c478bd9Sstevel@tonic-gate enable_errorlog(); 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate /* 2: sys_poll thread */ 30077c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&sys_attr, stacksize); 30087c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&sys_attr, stack_ptr); 30097c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 30107c478bd9Sstevel@tonic-gate if (pthread_create(&sys_thread, &sys_attr, sys_poll, NULL) != 0) { 30117c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 30127c478bd9Sstevel@tonic-gate exit(1); 30137c478bd9Sstevel@tonic-gate } 30147c478bd9Sstevel@tonic-gate 30157c478bd9Sstevel@tonic-gate /* 30167c478bd9Sstevel@tonic-gate * We've started the sys_poll() and logmsg() threads. Now we are ready 30177c478bd9Sstevel@tonic-gate * to open the door. This cannot happen before spawning sys_poll(), 30187c478bd9Sstevel@tonic-gate * because after opening the door, syslog() will no longer take care of 30197c478bd9Sstevel@tonic-gate * LOG_CONS. Therefor, we should pull up all pending log messages and 30207c478bd9Sstevel@tonic-gate * activate sys_poll() before opening the door, so that log driver 30217c478bd9Sstevel@tonic-gate * won't drop messages. 30227c478bd9Sstevel@tonic-gate */ 30237c478bd9Sstevel@tonic-gate open_door(); 30247c478bd9Sstevel@tonic-gate 30257c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from local system\n", 30267c478bd9Sstevel@tonic-gate mythreadno); 30277c478bd9Sstevel@tonic-gate 30287c478bd9Sstevel@tonic-gate if (turnoff == 0) { 30297c478bd9Sstevel@tonic-gate /* init the hostname lookup queue */ 30307c478bd9Sstevel@tonic-gate (void) dataq_init(&hnlq); 30317c478bd9Sstevel@tonic-gate 30327c478bd9Sstevel@tonic-gate /* 3: hostname lookup thread */ 30337c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&hnl_attr, stacksize); 30347c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&hnl_attr, stack_ptr); 30357c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 30367c478bd9Sstevel@tonic-gate if (pthread_create(&hnl_thread, &hnl_attr, 30377c478bd9Sstevel@tonic-gate hostname_lookup, NULL) != 0) { 30387c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 30397c478bd9Sstevel@tonic-gate exit(1); 30407c478bd9Sstevel@tonic-gate } 30417c478bd9Sstevel@tonic-gate 30427c478bd9Sstevel@tonic-gate /* 4: net_poll thread */ 30437c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&net_attr, stacksize); 30447c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&net_attr, stack_ptr); 30457c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 30467c478bd9Sstevel@tonic-gate 30477c478bd9Sstevel@tonic-gate /* grab UDP port */ 30487c478bd9Sstevel@tonic-gate bindnet(); 30497c478bd9Sstevel@tonic-gate 30507c478bd9Sstevel@tonic-gate if (pthread_create(&net_thread, &net_attr, net_poll, 30517c478bd9Sstevel@tonic-gate NULL) != 0) { 30527c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 30537c478bd9Sstevel@tonic-gate exit(1); 30547c478bd9Sstevel@tonic-gate } 30557c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from remote\n", 30567c478bd9Sstevel@tonic-gate mythreadno); 30577c478bd9Sstevel@tonic-gate } 30587c478bd9Sstevel@tonic-gate 30597c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&sys_attr); 30607c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&net_attr); 30617c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&log_attr); 30627c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&hnl_attr); 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT; 30657c478bd9Sstevel@tonic-gate (void) alarm((unsigned)curalarm); 30667c478bd9Sstevel@tonic-gate DPRINT2(2, "init(%u): Next alarm in %d seconds\n", 30677c478bd9Sstevel@tonic-gate mythreadno, curalarm); 30687c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): syslogd: started\n", mythreadno); 30697c478bd9Sstevel@tonic-gate } 30707c478bd9Sstevel@tonic-gate 30717c478bd9Sstevel@tonic-gate /* 30727c478bd9Sstevel@tonic-gate * will print a bunch of debugging stats on 'fd' 30737c478bd9Sstevel@tonic-gate */ 30747c478bd9Sstevel@tonic-gate static void 30757c478bd9Sstevel@tonic-gate dumpstats(int fd) 30767c478bd9Sstevel@tonic-gate { 30777c478bd9Sstevel@tonic-gate FILE *out; 30787c478bd9Sstevel@tonic-gate struct filed *f; 30797c478bd9Sstevel@tonic-gate int i; 30807c478bd9Sstevel@tonic-gate char users[1024]; 30817c478bd9Sstevel@tonic-gate char cbuf[30]; 30827c478bd9Sstevel@tonic-gate char *dashes = "------------------------"; 30837c478bd9Sstevel@tonic-gate static int conversion_printed; 30847c478bd9Sstevel@tonic-gate 30857c478bd9Sstevel@tonic-gate if ((out = fdopen(fd, "w+")) == NULL) 30867c478bd9Sstevel@tonic-gate return; 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n syslogd: version %s\n", Version); 30897c478bd9Sstevel@tonic-gate (void) fprintf(out, " Started: %s", ctime_r(&start_time, cbuf)); 30907c478bd9Sstevel@tonic-gate (void) fprintf(out, "Input message count: system %d, network %d\n", 30917c478bd9Sstevel@tonic-gate sys_msg_count, net_msg_count); 30927c478bd9Sstevel@tonic-gate (void) fprintf(out, "# Outputs: %d\n\n", nlogs); 30937c478bd9Sstevel@tonic-gate 30947c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s priority = [file, facility] %s\n\n", 30957c478bd9Sstevel@tonic-gate dashes, dashes); 30967c478bd9Sstevel@tonic-gate 30977c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 30987c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", i / 10); 30997c478bd9Sstevel@tonic-gate } 31007c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 31017c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 31027c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", i % 10); 31037c478bd9Sstevel@tonic-gate } 31047c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 31057c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 31067c478bd9Sstevel@tonic-gate (void) fprintf(out, "--"); 31077c478bd9Sstevel@tonic-gate } 31087c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 31097c478bd9Sstevel@tonic-gate 31107c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 31117c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 31127c478bd9Sstevel@tonic-gate if (f->f_pmask[i] == NOPRI) 31137c478bd9Sstevel@tonic-gate (void) fprintf(out, "X "); 31147c478bd9Sstevel@tonic-gate else 31157c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", 31167c478bd9Sstevel@tonic-gate f->f_pmask[i]); 31177c478bd9Sstevel@tonic-gate } 31187c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s: ", TypeNames[f->f_type]); 31197c478bd9Sstevel@tonic-gate switch (f->f_type) { 31207c478bd9Sstevel@tonic-gate case F_FILE: 31217c478bd9Sstevel@tonic-gate case F_TTY: 31227c478bd9Sstevel@tonic-gate case F_CONSOLE: 31237c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_fname); 31247c478bd9Sstevel@tonic-gate break; 31257c478bd9Sstevel@tonic-gate case F_FORW: 31267c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_forw.f_hname); 31277c478bd9Sstevel@tonic-gate break; 31287c478bd9Sstevel@tonic-gate case F_USERS: 31297c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && 31307c478bd9Sstevel@tonic-gate *f->f_un.f_uname[i]; i++) { 31317c478bd9Sstevel@tonic-gate if (!i) 31327c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", 31337c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 31347c478bd9Sstevel@tonic-gate else 31357c478bd9Sstevel@tonic-gate (void) fprintf(out, ", %s", 31367c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 31377c478bd9Sstevel@tonic-gate } 31387c478bd9Sstevel@tonic-gate break; 31397c478bd9Sstevel@tonic-gate } 31407c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 31417c478bd9Sstevel@tonic-gate } 31427c478bd9Sstevel@tonic-gate 31437c478bd9Sstevel@tonic-gate if (!conversion_printed) { 31440ea5e3a5Sjjj (void) fprintf(out, "\nFacilities:\n"); 31457c478bd9Sstevel@tonic-gate 31467c478bd9Sstevel@tonic-gate for (i = 0; FacNames[i].c_val != -1; i++) { 31470ea5e3a5Sjjj (void) fprintf(out, " [%02d] %s: %3d\n", i, 31487c478bd9Sstevel@tonic-gate FacNames[i].c_name, FacNames[i].c_val); 31497c478bd9Sstevel@tonic-gate } 31507c478bd9Sstevel@tonic-gate 31510ea5e3a5Sjjj (void) fprintf(out, "\nPriorities:\n"); 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate for (i = 0; PriNames[i].c_val != -1; i++) { 31540ea5e3a5Sjjj (void) fprintf(out, " [%02d] %s: %3d\n", i, 31557c478bd9Sstevel@tonic-gate PriNames[i].c_name, PriNames[i].c_val); 31567c478bd9Sstevel@tonic-gate } 31577c478bd9Sstevel@tonic-gate 31587c478bd9Sstevel@tonic-gate conversion_printed = 1; 31597c478bd9Sstevel@tonic-gate } 31607c478bd9Sstevel@tonic-gate 31617c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n\n\n\t\tPer File Statistics\n"); 31627c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s\tTot\tDups\tNofwd\tErrs\n", "File"); 31637c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s\t---\t----\t-----\t----\n", "----"); 31647c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 31657c478bd9Sstevel@tonic-gate switch (f->f_type) { 31667c478bd9Sstevel@tonic-gate case F_FILE: 31677c478bd9Sstevel@tonic-gate case F_TTY: 31687c478bd9Sstevel@tonic-gate case F_CONSOLE: 31697c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_fname); 31707c478bd9Sstevel@tonic-gate break; 31717c478bd9Sstevel@tonic-gate case F_WALL: 31727c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", TypeNames[f->f_type]); 31737c478bd9Sstevel@tonic-gate break; 31747c478bd9Sstevel@tonic-gate case F_FORW: 31757c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_forw.f_hname); 31767c478bd9Sstevel@tonic-gate break; 31777c478bd9Sstevel@tonic-gate case F_USERS: 31787c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && 31797c478bd9Sstevel@tonic-gate *f->f_un.f_uname[i]; i++) { 31807c478bd9Sstevel@tonic-gate if (!i) 31817c478bd9Sstevel@tonic-gate (void) strcpy(users, 31827c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 31837c478bd9Sstevel@tonic-gate else { 31847c478bd9Sstevel@tonic-gate (void) strcat(users, ","); 31857c478bd9Sstevel@tonic-gate (void) strcat(users, 31867c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 31877c478bd9Sstevel@tonic-gate } 31887c478bd9Sstevel@tonic-gate } 31897c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", users); 31907c478bd9Sstevel@tonic-gate break; 31917c478bd9Sstevel@tonic-gate } 31927c478bd9Sstevel@tonic-gate (void) fprintf(out, "\t%d\t%d\t%d\t%d\n", 31937c478bd9Sstevel@tonic-gate f->f_stat.total, f->f_stat.dups, 31947c478bd9Sstevel@tonic-gate f->f_stat.cantfwd, f->f_stat.errs); 31957c478bd9Sstevel@tonic-gate } 31967c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n\n"); 31977c478bd9Sstevel@tonic-gate if (Debug && fd == 1) 31987c478bd9Sstevel@tonic-gate return; 31997c478bd9Sstevel@tonic-gate (void) fclose(out); 32007c478bd9Sstevel@tonic-gate } 32017c478bd9Sstevel@tonic-gate 32027c478bd9Sstevel@tonic-gate /* 32037c478bd9Sstevel@tonic-gate * conf_init - This routine is code seperated from the 32047c478bd9Sstevel@tonic-gate * init routine in order to be re-callable when we get 32057c478bd9Sstevel@tonic-gate * a SIGHUP signal. 32067c478bd9Sstevel@tonic-gate */ 32077c478bd9Sstevel@tonic-gate static void 32087c478bd9Sstevel@tonic-gate conf_init(void) 32097c478bd9Sstevel@tonic-gate { 32107c478bd9Sstevel@tonic-gate char *p; 32117c478bd9Sstevel@tonic-gate int i; 32127c478bd9Sstevel@tonic-gate struct filed *f; 32137c478bd9Sstevel@tonic-gate char *m4argv[4]; 32147c478bd9Sstevel@tonic-gate int m4argc = 0; 32157c478bd9Sstevel@tonic-gate conf_t cf; 32167c478bd9Sstevel@tonic-gate pthread_t mythreadno; 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate if (Debug) { 32197c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 32207c478bd9Sstevel@tonic-gate } 32217c478bd9Sstevel@tonic-gate 32227c478bd9Sstevel@tonic-gate DPRINT1(2, "conf_init(%u): starting logger threads\n", 32237c478bd9Sstevel@tonic-gate mythreadno); 32247c478bd9Sstevel@tonic-gate 32257c478bd9Sstevel@tonic-gate m4argv[m4argc++] = "m4"; 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate if (amiloghost() == 1) { 32287c478bd9Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): I am loghost\n", mythreadno); 32297c478bd9Sstevel@tonic-gate m4argv[m4argc++] = "-DLOGHOST=1"; 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate 32327c478bd9Sstevel@tonic-gate m4argv[m4argc++] = ConfFile; 32337c478bd9Sstevel@tonic-gate m4argv[m4argc] = NULL; 32347c478bd9Sstevel@tonic-gate 32357c478bd9Sstevel@tonic-gate /* 32367c478bd9Sstevel@tonic-gate * Make sure the configuration file and m4 exist, and then parse 32377c478bd9Sstevel@tonic-gate * the configuration file with m4. If any of these fail, resort 32387c478bd9Sstevel@tonic-gate * to our hardcoded fallback configuration. 32397c478bd9Sstevel@tonic-gate */ 32407c478bd9Sstevel@tonic-gate 32417c478bd9Sstevel@tonic-gate if (access(ConfFile, R_OK) == -1) { 32427c478bd9Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): %s does not exist\n", mythreadno, 32437c478bd9Sstevel@tonic-gate ConfFile); 32447c478bd9Sstevel@tonic-gate logerror("can't open configuration file"); 32457c478bd9Sstevel@tonic-gate /* CSTYLED */ 32467c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 32477c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 32487c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 32497c478bd9Sstevel@tonic-gate nlogs = 2; 32507c478bd9Sstevel@tonic-gate goto nofile; 32517c478bd9Sstevel@tonic-gate } 32527c478bd9Sstevel@tonic-gate 32537c478bd9Sstevel@tonic-gate if (checkm4() != 0 || conf_open(&cf, "/usr/ccs/bin/m4", m4argv) == -1) { 32547c478bd9Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): cannot open %s\n", mythreadno, 32557c478bd9Sstevel@tonic-gate ConfFile); 32567c478bd9Sstevel@tonic-gate /* CSTYLED */ 32577c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 32587c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 32597c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 32607c478bd9Sstevel@tonic-gate nlogs = 2; 32617c478bd9Sstevel@tonic-gate goto nofile; 32627c478bd9Sstevel@tonic-gate } 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate /* Count the number of lines which are not blanks or comments */ 32657c478bd9Sstevel@tonic-gate nlogs = 0; 32667c478bd9Sstevel@tonic-gate while ((p = conf_read(&cf)) != NULL) { 32677c478bd9Sstevel@tonic-gate if (p[0] != '\0' && p[0] != '#') 32687c478bd9Sstevel@tonic-gate nlogs++; 32697c478bd9Sstevel@tonic-gate } 32707c478bd9Sstevel@tonic-gate 32717c478bd9Sstevel@tonic-gate Files = (struct filed *)malloc(sizeof (struct filed) * nlogs); 32727c478bd9Sstevel@tonic-gate 32737c478bd9Sstevel@tonic-gate if (!Files) { 32747c478bd9Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): malloc failed - can't " 32757c478bd9Sstevel@tonic-gate "allocate 'Files' array\n", mythreadno); 32767c478bd9Sstevel@tonic-gate MALLOC_FAIL("loading minimum configuration"); 32777c478bd9Sstevel@tonic-gate /* CSTYLED */ 32787c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 32797c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 32807c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 32817c478bd9Sstevel@tonic-gate nlogs = 2; 32827c478bd9Sstevel@tonic-gate conf_close(&cf); 32837c478bd9Sstevel@tonic-gate goto nofile; 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate /* 32877c478bd9Sstevel@tonic-gate * Foreach line in the conf table, open that file. 32887c478bd9Sstevel@tonic-gate */ 32897c478bd9Sstevel@tonic-gate conf_rewind(&cf); 32907c478bd9Sstevel@tonic-gate f = Files; 32917c478bd9Sstevel@tonic-gate i = 0; 32927c478bd9Sstevel@tonic-gate while (((p = conf_read(&cf)) != NULL) && (f < &Files[nlogs])) { 32937c478bd9Sstevel@tonic-gate i++; 32947c478bd9Sstevel@tonic-gate /* check for end-of-section */ 32957c478bd9Sstevel@tonic-gate if (p[0] == '\0' || p[0] == '#') 32967c478bd9Sstevel@tonic-gate continue; 32977c478bd9Sstevel@tonic-gate 32987c478bd9Sstevel@tonic-gate cfline(p, i, f); 32997c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) 33007c478bd9Sstevel@tonic-gate nlogs--; 33017c478bd9Sstevel@tonic-gate else 33027c478bd9Sstevel@tonic-gate f++; 33037c478bd9Sstevel@tonic-gate } 33047c478bd9Sstevel@tonic-gate 33057c478bd9Sstevel@tonic-gate conf_close(&cf); 33067c478bd9Sstevel@tonic-gate 33077c478bd9Sstevel@tonic-gate /* 33087c478bd9Sstevel@tonic-gate * See if marks are to be written to any files. If so, set up a 33097c478bd9Sstevel@tonic-gate * timeout for marks. 33107c478bd9Sstevel@tonic-gate */ 33117c478bd9Sstevel@tonic-gate nofile: 33127c478bd9Sstevel@tonic-gate Marking = 0; 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate /* 33157c478bd9Sstevel@tonic-gate * allocate thread stacks - one for each logger thread. 33167c478bd9Sstevel@tonic-gate */ 33177c478bd9Sstevel@tonic-gate if ((cstack_ptr = alloc_stacks(nlogs)) == NULL) { 33187c478bd9Sstevel@tonic-gate logerror("alloc_stacks failed - fatal"); 33197c478bd9Sstevel@tonic-gate exit(1); 33207c478bd9Sstevel@tonic-gate } 33217c478bd9Sstevel@tonic-gate 33227c478bd9Sstevel@tonic-gate /* And now one thread for each configured file */ 33237c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 33247c478bd9Sstevel@tonic-gate if (filed_init(f) != 0) { 33257c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 33267c478bd9Sstevel@tonic-gate exit(1); 33277c478bd9Sstevel@tonic-gate } 33287c478bd9Sstevel@tonic-gate 33290ea5e3a5Sjjj (void) pthread_mutex_lock(&cft); 33307c478bd9Sstevel@tonic-gate ++conf_threads; 33310ea5e3a5Sjjj (void) pthread_mutex_unlock(&cft); 33327c478bd9Sstevel@tonic-gate 33337c478bd9Sstevel@tonic-gate if (f->f_type != F_UNUSED && 33347c478bd9Sstevel@tonic-gate f->f_pmask[LOG_NFACILITIES] != NOPRI) 33357c478bd9Sstevel@tonic-gate Marking = 1; 33367c478bd9Sstevel@tonic-gate } 33377c478bd9Sstevel@tonic-gate } 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate /* 33407c478bd9Sstevel@tonic-gate * filed init - initialize fields in a file descriptor struct 33417c478bd9Sstevel@tonic-gate * this is called before multiple threads are running, so no mutex 33427c478bd9Sstevel@tonic-gate * needs to be held at this time. 33437c478bd9Sstevel@tonic-gate */ 334478eb75caSchin static int 33457c478bd9Sstevel@tonic-gate filed_init(struct filed *f) 33467c478bd9Sstevel@tonic-gate { 33477c478bd9Sstevel@tonic-gate pthread_attr_t stack_attr; 33487c478bd9Sstevel@tonic-gate pthread_t mythreadno; 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate if (Debug) { 33517c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 33527c478bd9Sstevel@tonic-gate } 33537c478bd9Sstevel@tonic-gate 33547c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&f->filed_mutex, NULL) != 0) { 33557c478bd9Sstevel@tonic-gate logerror("pthread_mutex_init failed"); 33567c478bd9Sstevel@tonic-gate return (-1); 33577c478bd9Sstevel@tonic-gate } 33587c478bd9Sstevel@tonic-gate 33597c478bd9Sstevel@tonic-gate DPRINT2(5, "filed_init(%u): dataq_init for queue %p\n", 33600ea5e3a5Sjjj mythreadno, (void *)&f->f_queue); 33617c478bd9Sstevel@tonic-gate (void) dataq_init(&f->f_queue); 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate if (pthread_attr_init(&stack_attr) != 0) { 33647c478bd9Sstevel@tonic-gate logerror("pthread_attr_init failed"); 33657c478bd9Sstevel@tonic-gate return (-1); 33667c478bd9Sstevel@tonic-gate } 33677c478bd9Sstevel@tonic-gate 33687c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&stack_attr, stacksize); 33697c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&stack_attr, cstack_ptr); 33707c478bd9Sstevel@tonic-gate cstack_ptr += stacksize + redzonesize; 33717c478bd9Sstevel@tonic-gate 33727c478bd9Sstevel@tonic-gate f->f_msgflag = 0; 33737c478bd9Sstevel@tonic-gate f->f_prevmsg.msg[0] = '\0'; 33747c478bd9Sstevel@tonic-gate f->f_prevmsg.flags = 0; 33757c478bd9Sstevel@tonic-gate f->f_prevmsg.pri = 0; 33767c478bd9Sstevel@tonic-gate f->f_prevmsg.host[0] = '\0'; 33777c478bd9Sstevel@tonic-gate 33787c478bd9Sstevel@tonic-gate f->f_current.msg[0] = '\0'; 33797c478bd9Sstevel@tonic-gate f->f_current.flags = 0; 33807c478bd9Sstevel@tonic-gate f->f_current.pri = 0; 33817c478bd9Sstevel@tonic-gate f->f_current.host[0] = '\0'; 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate f->f_prevcount = 0; 33847c478bd9Sstevel@tonic-gate 33857c478bd9Sstevel@tonic-gate f->f_stat.flag = 0; 33867c478bd9Sstevel@tonic-gate f->f_stat.total = 0; 33877c478bd9Sstevel@tonic-gate f->f_stat.dups = 0; 33887c478bd9Sstevel@tonic-gate f->f_stat.cantfwd = 0; 33897c478bd9Sstevel@tonic-gate f->f_stat.errs = 0; 33907c478bd9Sstevel@tonic-gate 33917c478bd9Sstevel@tonic-gate if (pthread_create(&f->f_thread, NULL, logit, (void *)f) != 0) { 33927c478bd9Sstevel@tonic-gate logerror("pthread_create failed"); 33930ea5e3a5Sjjj (void) pthread_attr_destroy(&stack_attr); 33947c478bd9Sstevel@tonic-gate return (-1); 33957c478bd9Sstevel@tonic-gate } 33967c478bd9Sstevel@tonic-gate 33970ea5e3a5Sjjj (void) pthread_attr_destroy(&stack_attr); 33987c478bd9Sstevel@tonic-gate return (0); 33997c478bd9Sstevel@tonic-gate } 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate /* 34037c478bd9Sstevel@tonic-gate * Crack a configuration file line 34047c478bd9Sstevel@tonic-gate */ 34057c478bd9Sstevel@tonic-gate static void 34067c478bd9Sstevel@tonic-gate cfline(char *line, int lineno, struct filed *f) 34077c478bd9Sstevel@tonic-gate { 34087c478bd9Sstevel@tonic-gate char *p; 34097c478bd9Sstevel@tonic-gate char *q; 34107c478bd9Sstevel@tonic-gate int i; 34117c478bd9Sstevel@tonic-gate char *bp; 34127c478bd9Sstevel@tonic-gate int pri; 34137c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 34147c478bd9Sstevel@tonic-gate char ebuf[SYS_NMLN+1+40]; 34157c478bd9Sstevel@tonic-gate mode_t fmode, omode = O_WRONLY|O_APPEND|O_NOCTTY; 34167c478bd9Sstevel@tonic-gate struct stat64 sbuf; 34177c478bd9Sstevel@tonic-gate pthread_t mythreadno; 34187c478bd9Sstevel@tonic-gate 34197c478bd9Sstevel@tonic-gate if (Debug) { 34207c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 34217c478bd9Sstevel@tonic-gate } 34227c478bd9Sstevel@tonic-gate 34237c478bd9Sstevel@tonic-gate DPRINT2(1, "cfline(%u): (%s)\n", mythreadno, line); 34247c478bd9Sstevel@tonic-gate 3425ace1a5f1Sdp errno = 0; /* keep errno related stuff out of logerror messages */ 34267c478bd9Sstevel@tonic-gate 34277c478bd9Sstevel@tonic-gate /* clear out file entry */ 34287c478bd9Sstevel@tonic-gate bzero((char *)f, sizeof (*f)); 34297c478bd9Sstevel@tonic-gate for (i = 0; i <= LOG_NFACILITIES; i++) 34307c478bd9Sstevel@tonic-gate f->f_pmask[i] = NOPRI; 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate /* scan through the list of selectors */ 34337c478bd9Sstevel@tonic-gate for (p = line; *p && *p != '\t'; ) { 34347c478bd9Sstevel@tonic-gate 34357c478bd9Sstevel@tonic-gate /* find the end of this facility name list */ 34367c478bd9Sstevel@tonic-gate for (q = p; *q && *q != '\t' && *q++ != '.'; ) 34377c478bd9Sstevel@tonic-gate continue; 34387c478bd9Sstevel@tonic-gate 34397c478bd9Sstevel@tonic-gate /* collect priority name */ 34407c478bd9Sstevel@tonic-gate for (bp = buf; *q && !strchr("\t,;", *q); ) 34417c478bd9Sstevel@tonic-gate *bp++ = *q++; 34427c478bd9Sstevel@tonic-gate *bp = '\0'; 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate /* skip cruft */ 34457c478bd9Sstevel@tonic-gate while (strchr(", ;", *q)) 34467c478bd9Sstevel@tonic-gate q++; 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate /* decode priority name */ 34497c478bd9Sstevel@tonic-gate pri = decode(buf, PriNames); 34507c478bd9Sstevel@tonic-gate if (pri < 0) { 34517c478bd9Sstevel@tonic-gate logerror("line %d: unknown priority name \"%s\"", 34527c478bd9Sstevel@tonic-gate lineno, buf); 34537c478bd9Sstevel@tonic-gate return; 34547c478bd9Sstevel@tonic-gate } 34557c478bd9Sstevel@tonic-gate 34567c478bd9Sstevel@tonic-gate /* scan facilities */ 34577c478bd9Sstevel@tonic-gate while (*p && !strchr("\t.;", *p)) { 34587c478bd9Sstevel@tonic-gate for (bp = buf; *p && !strchr("\t,;.", *p); ) 34597c478bd9Sstevel@tonic-gate *bp++ = *p++; 34607c478bd9Sstevel@tonic-gate *bp = '\0'; 34617c478bd9Sstevel@tonic-gate if (*buf == '*') 34627c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES; i++) 34637c478bd9Sstevel@tonic-gate f->f_pmask[i] = (uchar_t)pri; 34647c478bd9Sstevel@tonic-gate else { 34657c478bd9Sstevel@tonic-gate i = decode(buf, FacNames); 34667c478bd9Sstevel@tonic-gate if (i < 0) { 34677c478bd9Sstevel@tonic-gate logerror("line %d: unknown facility" 34687c478bd9Sstevel@tonic-gate " name \"%s\"", lineno, buf); 34697c478bd9Sstevel@tonic-gate return; 34707c478bd9Sstevel@tonic-gate } 34717c478bd9Sstevel@tonic-gate f->f_pmask[i >> 3] = (uchar_t)pri; 34727c478bd9Sstevel@tonic-gate } 34737c478bd9Sstevel@tonic-gate while (*p == ',' || *p == ' ') 34747c478bd9Sstevel@tonic-gate p++; 34757c478bd9Sstevel@tonic-gate } 34767c478bd9Sstevel@tonic-gate 34777c478bd9Sstevel@tonic-gate p = q; 34787c478bd9Sstevel@tonic-gate } 34797c478bd9Sstevel@tonic-gate 34807c478bd9Sstevel@tonic-gate /* skip to action part */ 34817c478bd9Sstevel@tonic-gate while (*p == '\t' || *p == ' ') 34827c478bd9Sstevel@tonic-gate p++; 34837c478bd9Sstevel@tonic-gate 34847c478bd9Sstevel@tonic-gate switch (*p) { 34857c478bd9Sstevel@tonic-gate case '\0': 34867c478bd9Sstevel@tonic-gate errno = 0; 34877c478bd9Sstevel@tonic-gate logerror("line %d: no action part", lineno); 34887c478bd9Sstevel@tonic-gate break; 34897c478bd9Sstevel@tonic-gate 34907c478bd9Sstevel@tonic-gate case '@': 34917c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_forw.f_hname, ++p, SYS_NMLN); 34920ea5e3a5Sjjj if (logforward(f, ebuf, sizeof (ebuf)) != 0) { 34937c478bd9Sstevel@tonic-gate logerror("line %d: %s", lineno, ebuf); 34947c478bd9Sstevel@tonic-gate break; 34957c478bd9Sstevel@tonic-gate } 34967c478bd9Sstevel@tonic-gate f->f_type = F_FORW; 34977c478bd9Sstevel@tonic-gate break; 34987c478bd9Sstevel@tonic-gate 34997c478bd9Sstevel@tonic-gate case '/': 35007c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_fname, p, MAXPATHLEN); 35017c478bd9Sstevel@tonic-gate if (stat64(p, &sbuf) < 0) { 35027c478bd9Sstevel@tonic-gate logerror(p); 35037c478bd9Sstevel@tonic-gate break; 35047c478bd9Sstevel@tonic-gate } 35057c478bd9Sstevel@tonic-gate /* 35067c478bd9Sstevel@tonic-gate * don't block trying to open a pipe 35077c478bd9Sstevel@tonic-gate * with no reader on the other end 35087c478bd9Sstevel@tonic-gate */ 35097c478bd9Sstevel@tonic-gate fmode = 0; /* reset each pass */ 35107c478bd9Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode)) 35117c478bd9Sstevel@tonic-gate fmode = O_NONBLOCK; 35127c478bd9Sstevel@tonic-gate 35137c478bd9Sstevel@tonic-gate f->f_file = open64(p, omode|fmode); 35147c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 35157c478bd9Sstevel@tonic-gate if (fmode && errno == ENXIO) { 35167c478bd9Sstevel@tonic-gate errno = 0; 35177c478bd9Sstevel@tonic-gate logerror("%s - no reader", p); 35187c478bd9Sstevel@tonic-gate } else 35197c478bd9Sstevel@tonic-gate logerror(p); 35207c478bd9Sstevel@tonic-gate break; 35217c478bd9Sstevel@tonic-gate } 35227c478bd9Sstevel@tonic-gate 35237c478bd9Sstevel@tonic-gate /* 35247c478bd9Sstevel@tonic-gate * Fifos are initially opened NONBLOCK 35257c478bd9Sstevel@tonic-gate * to insure we don't hang, but once 35267c478bd9Sstevel@tonic-gate * we are open, we need to change the 35277c478bd9Sstevel@tonic-gate * behavior back to blocking, otherwise 35287c478bd9Sstevel@tonic-gate * we may get write errors, and the log 35297c478bd9Sstevel@tonic-gate * will get closed down the line. 35307c478bd9Sstevel@tonic-gate */ 35317c478bd9Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode)) 35327c478bd9Sstevel@tonic-gate (void) fcntl(f->f_file, F_SETFL, omode); 35337c478bd9Sstevel@tonic-gate 35347c478bd9Sstevel@tonic-gate if (isatty(f->f_file)) { 35357c478bd9Sstevel@tonic-gate f->f_type = F_TTY; 35367c478bd9Sstevel@tonic-gate untty(); 35377c478bd9Sstevel@tonic-gate } else 35387c478bd9Sstevel@tonic-gate f->f_type = F_FILE; 35397c478bd9Sstevel@tonic-gate 35407c478bd9Sstevel@tonic-gate if ((strcmp(p, ctty) == 0) || (strcmp(p, sysmsg) == 0)) 35417c478bd9Sstevel@tonic-gate f->f_type = F_CONSOLE; 35427c478bd9Sstevel@tonic-gate break; 35437c478bd9Sstevel@tonic-gate 35447c478bd9Sstevel@tonic-gate case '*': 35457c478bd9Sstevel@tonic-gate f->f_type = F_WALL; 35467c478bd9Sstevel@tonic-gate break; 35477c478bd9Sstevel@tonic-gate 35487c478bd9Sstevel@tonic-gate default: 35497c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && *p; i++) { 35507c478bd9Sstevel@tonic-gate for (q = p; *q && *q != ','; ) 35517c478bd9Sstevel@tonic-gate q++; 35527c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_uname[i], p, UNAMESZ); 35537c478bd9Sstevel@tonic-gate if ((q - p) > UNAMESZ) 35547c478bd9Sstevel@tonic-gate f->f_un.f_uname[i][UNAMESZ] = '\0'; 35557c478bd9Sstevel@tonic-gate else 35567c478bd9Sstevel@tonic-gate f->f_un.f_uname[i][q - p] = '\0'; 35577c478bd9Sstevel@tonic-gate while (*q == ',' || *q == ' ') 35587c478bd9Sstevel@tonic-gate q++; 35597c478bd9Sstevel@tonic-gate p = q; 35607c478bd9Sstevel@tonic-gate } 35617c478bd9Sstevel@tonic-gate f->f_type = F_USERS; 35627c478bd9Sstevel@tonic-gate break; 35637c478bd9Sstevel@tonic-gate } 35647c478bd9Sstevel@tonic-gate f->f_orig_type = f->f_type; 35657c478bd9Sstevel@tonic-gate } 35667c478bd9Sstevel@tonic-gate 35677c478bd9Sstevel@tonic-gate 35687c478bd9Sstevel@tonic-gate /* 35697c478bd9Sstevel@tonic-gate * Decode a symbolic name to a numeric value 35707c478bd9Sstevel@tonic-gate */ 35717c478bd9Sstevel@tonic-gate static int 35727c478bd9Sstevel@tonic-gate decode(char *name, struct code *codetab) 35737c478bd9Sstevel@tonic-gate { 35747c478bd9Sstevel@tonic-gate struct code *c; 35757c478bd9Sstevel@tonic-gate char *p; 35767c478bd9Sstevel@tonic-gate char buf[40]; 35777c478bd9Sstevel@tonic-gate 35787c478bd9Sstevel@tonic-gate if (isdigit(*name)) 35797c478bd9Sstevel@tonic-gate return (atoi(name)); 35807c478bd9Sstevel@tonic-gate 35817c478bd9Sstevel@tonic-gate (void) strncpy(buf, name, sizeof (buf) - 1); 35827c478bd9Sstevel@tonic-gate for (p = buf; *p; p++) 35837c478bd9Sstevel@tonic-gate if (isupper(*p)) 35847c478bd9Sstevel@tonic-gate *p = tolower(*p); 35857c478bd9Sstevel@tonic-gate for (c = codetab; c->c_name; c++) 35867c478bd9Sstevel@tonic-gate if (!(strcmp(buf, c->c_name))) 35877c478bd9Sstevel@tonic-gate return (c->c_val); 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate return (-1); 35907c478bd9Sstevel@tonic-gate } 35917c478bd9Sstevel@tonic-gate 35927c478bd9Sstevel@tonic-gate static int 35937c478bd9Sstevel@tonic-gate ismyaddr(struct netbuf *nbp) 35947c478bd9Sstevel@tonic-gate { 35957c478bd9Sstevel@tonic-gate int i; 35967c478bd9Sstevel@tonic-gate 35977c478bd9Sstevel@tonic-gate if (nbp == NULL) 35987c478bd9Sstevel@tonic-gate return (0); 35997c478bd9Sstevel@tonic-gate 36007c478bd9Sstevel@tonic-gate for (i = 1; i < Ninputs; i++) { 36017c478bd9Sstevel@tonic-gate if (same_addr(nbp, Myaddrs[i])) 36027c478bd9Sstevel@tonic-gate return (1); 36037c478bd9Sstevel@tonic-gate } 36047c478bd9Sstevel@tonic-gate return (0); 36057c478bd9Sstevel@tonic-gate } 36067c478bd9Sstevel@tonic-gate 36077c478bd9Sstevel@tonic-gate static void 36087c478bd9Sstevel@tonic-gate getnets(void) 36097c478bd9Sstevel@tonic-gate { 36107c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 36117c478bd9Sstevel@tonic-gate struct netconfig *ncp; 36127c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 36137c478bd9Sstevel@tonic-gate struct netbuf *nbp; 36147c478bd9Sstevel@tonic-gate int i, inputs; 36157c478bd9Sstevel@tonic-gate void *handle; 36167c478bd9Sstevel@tonic-gate char *uap; 36177c478bd9Sstevel@tonic-gate pthread_t mythreadno; 36187c478bd9Sstevel@tonic-gate 36197c478bd9Sstevel@tonic-gate if (Debug) { 36207c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 36217c478bd9Sstevel@tonic-gate } 36227c478bd9Sstevel@tonic-gate 36237c478bd9Sstevel@tonic-gate if (turnoff) { 36247c478bd9Sstevel@tonic-gate DPRINT1(1, "getnets(%u): network is being turned off\n", 36257c478bd9Sstevel@tonic-gate mythreadno); 36267c478bd9Sstevel@tonic-gate return; 36277c478bd9Sstevel@tonic-gate } 36287c478bd9Sstevel@tonic-gate 36297c478bd9Sstevel@tonic-gate hs.h_host = HOST_SELF; 36307c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 36317c478bd9Sstevel@tonic-gate 36327c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 36337c478bd9Sstevel@tonic-gate return; 36347c478bd9Sstevel@tonic-gate } 36357c478bd9Sstevel@tonic-gate 36367c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 36377c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 36387c478bd9Sstevel@tonic-gate continue; 36397c478bd9Sstevel@tonic-gate } 36407c478bd9Sstevel@tonic-gate 36417c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) { 36427c478bd9Sstevel@tonic-gate continue; 36437c478bd9Sstevel@tonic-gate } 36447c478bd9Sstevel@tonic-gate 36457c478bd9Sstevel@tonic-gate if (nap == NULL || nap->n_cnt <= 0) { 36467c478bd9Sstevel@tonic-gate DPRINT1(1, "getnets(%u): found no address\n", 36477c478bd9Sstevel@tonic-gate mythreadno); 36487c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 36497c478bd9Sstevel@tonic-gate continue; 36507c478bd9Sstevel@tonic-gate } 36517c478bd9Sstevel@tonic-gate 36527c478bd9Sstevel@tonic-gate if (Debug) { 36537c478bd9Sstevel@tonic-gate DPRINT2(1, "getnets(%u): found %d addresses", 36547c478bd9Sstevel@tonic-gate mythreadno, nap->n_cnt); 36557c478bd9Sstevel@tonic-gate DPRINT0(1, ", they are: "); 36567c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) { 36597c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) { 36607c478bd9Sstevel@tonic-gate DPRINT1(1, "%s ", uap); 36617c478bd9Sstevel@tonic-gate free(uap); 36627c478bd9Sstevel@tonic-gate } 36637c478bd9Sstevel@tonic-gate nbp++; 36647c478bd9Sstevel@tonic-gate } 36657c478bd9Sstevel@tonic-gate 36667c478bd9Sstevel@tonic-gate DPRINT0(1, "\n"); 36677c478bd9Sstevel@tonic-gate } 36687c478bd9Sstevel@tonic-gate 36697c478bd9Sstevel@tonic-gate inputs = Ninputs + nap->n_cnt; 36707c478bd9Sstevel@tonic-gate 36717c478bd9Sstevel@tonic-gate Nfd = realloc(Nfd, inputs * sizeof (struct pollfd)); 36727c478bd9Sstevel@tonic-gate Ncf = realloc(Ncf, inputs * sizeof (struct netconfig)); 36737c478bd9Sstevel@tonic-gate Myaddrs = realloc(Myaddrs, inputs * sizeof (struct netbuf *)); 36747c478bd9Sstevel@tonic-gate Udp = realloc(Udp, inputs * sizeof (struct t_unitdata *)); 36757c478bd9Sstevel@tonic-gate Errp = realloc(Errp, inputs * sizeof (struct t_uderr *)); 36767c478bd9Sstevel@tonic-gate 36777c478bd9Sstevel@tonic-gate /* 36787c478bd9Sstevel@tonic-gate * all malloc failures here are fatal 36797c478bd9Sstevel@tonic-gate */ 36807c478bd9Sstevel@tonic-gate if (Nfd == NULL || Ncf == NULL || Myaddrs == NULL || 36817c478bd9Sstevel@tonic-gate Udp == NULL || Errp == NULL) { 36827c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 36837c478bd9Sstevel@tonic-gate } 36847c478bd9Sstevel@tonic-gate 36857c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 36867c478bd9Sstevel@tonic-gate 36877c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++, nbp++) { 36887c478bd9Sstevel@tonic-gate char ebuf[128]; 36897c478bd9Sstevel@tonic-gate 36907c478bd9Sstevel@tonic-gate if (addnet(ncp, nbp) == 0) { 36917c478bd9Sstevel@tonic-gate /* no error */ 36927c478bd9Sstevel@tonic-gate continue; 36937c478bd9Sstevel@tonic-gate } 36947c478bd9Sstevel@tonic-gate 36957c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to configure syslog port"); 36967c478bd9Sstevel@tonic-gate 36977c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) { 36987c478bd9Sstevel@tonic-gate size_t l = strlen(ebuf); 36997c478bd9Sstevel@tonic-gate (void) snprintf(ebuf + l, sizeof (ebuf) - l, 37007c478bd9Sstevel@tonic-gate " for %s", uap); 37017c478bd9Sstevel@tonic-gate } 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate DPRINT2(1, "getnets(%u): %s", 37047c478bd9Sstevel@tonic-gate mythreadno, ebuf); 37057c478bd9Sstevel@tonic-gate 37067c478bd9Sstevel@tonic-gate if (uap) { 37077c478bd9Sstevel@tonic-gate free(uap); 37087c478bd9Sstevel@tonic-gate } 37097c478bd9Sstevel@tonic-gate 37107c478bd9Sstevel@tonic-gate logerror(ebuf); 37117c478bd9Sstevel@tonic-gate /* 37127c478bd9Sstevel@tonic-gate * Here maybe syslogd can quit. However, syslogd 37137c478bd9Sstevel@tonic-gate * has been ignoring this error and keep running. 37147c478bd9Sstevel@tonic-gate * So we won't break it. 37157c478bd9Sstevel@tonic-gate */ 37167c478bd9Sstevel@tonic-gate } 37177c478bd9Sstevel@tonic-gate 37187c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 37197c478bd9Sstevel@tonic-gate } 37207c478bd9Sstevel@tonic-gate 37217c478bd9Sstevel@tonic-gate (void) endnetconfig(handle); 37227c478bd9Sstevel@tonic-gate } 37237c478bd9Sstevel@tonic-gate 37247c478bd9Sstevel@tonic-gate /* 37257c478bd9Sstevel@tonic-gate * Open the network device, and allocate necessary resources. 37267c478bd9Sstevel@tonic-gate * Myaddrs will also be filled, so that we can call ismyaddr() before 37277c478bd9Sstevel@tonic-gate * being bound to the network. 37287c478bd9Sstevel@tonic-gate */ 37297c478bd9Sstevel@tonic-gate static int 37307c478bd9Sstevel@tonic-gate addnet(struct netconfig *ncp, struct netbuf *nbp) 37317c478bd9Sstevel@tonic-gate { 37327c478bd9Sstevel@tonic-gate int fd; 37337c478bd9Sstevel@tonic-gate struct netbuf *bp; 37347c478bd9Sstevel@tonic-gate 37357c478bd9Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL); 37367c478bd9Sstevel@tonic-gate 37377c478bd9Sstevel@tonic-gate if (fd < 0) { 37387c478bd9Sstevel@tonic-gate return (1); 37397c478bd9Sstevel@tonic-gate } 37407c478bd9Sstevel@tonic-gate 37417c478bd9Sstevel@tonic-gate (void) memcpy(&Ncf[Ninputs], ncp, sizeof (struct netconfig)); 37427c478bd9Sstevel@tonic-gate 37437c478bd9Sstevel@tonic-gate /*LINTED*/ 37447c478bd9Sstevel@tonic-gate Udp[Ninputs] = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR); 37457c478bd9Sstevel@tonic-gate 37467c478bd9Sstevel@tonic-gate if (Udp[Ninputs] == NULL) { 37470ea5e3a5Sjjj (void) t_close(fd); 37487c478bd9Sstevel@tonic-gate return (1); 37497c478bd9Sstevel@tonic-gate } 37507c478bd9Sstevel@tonic-gate 37517c478bd9Sstevel@tonic-gate /*LINTED*/ 37527c478bd9Sstevel@tonic-gate Errp[Ninputs] = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ADDR); 37537c478bd9Sstevel@tonic-gate 37547c478bd9Sstevel@tonic-gate if (Errp[Ninputs] == NULL) { 37550ea5e3a5Sjjj (void) t_close(fd); 37560ea5e3a5Sjjj (void) t_free((char *)Udp[Ninputs], T_UNITDATA); 37577c478bd9Sstevel@tonic-gate return (1); 37587c478bd9Sstevel@tonic-gate } 37597c478bd9Sstevel@tonic-gate 37607c478bd9Sstevel@tonic-gate if ((bp = malloc(sizeof (struct netbuf))) == NULL || 37617c478bd9Sstevel@tonic-gate (bp->buf = malloc(nbp->len)) == NULL) { 37627c478bd9Sstevel@tonic-gate MALLOC_FAIL("allocating address buffer"); 37630ea5e3a5Sjjj (void) t_close(fd); 37640ea5e3a5Sjjj (void) t_free((char *)Udp[Ninputs], T_UNITDATA); 37650ea5e3a5Sjjj (void) t_free((char *)Errp[Ninputs], T_UDERROR); 37667c478bd9Sstevel@tonic-gate 37677c478bd9Sstevel@tonic-gate if (bp) { 37687c478bd9Sstevel@tonic-gate free(bp); 37697c478bd9Sstevel@tonic-gate } 37707c478bd9Sstevel@tonic-gate 37717c478bd9Sstevel@tonic-gate return (1); 37727c478bd9Sstevel@tonic-gate } 37737c478bd9Sstevel@tonic-gate 37747c478bd9Sstevel@tonic-gate bp->len = nbp->len; 37757c478bd9Sstevel@tonic-gate (void) memcpy(bp->buf, nbp->buf, nbp->len); 37767c478bd9Sstevel@tonic-gate Myaddrs[Ninputs] = bp; 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate Nfd[Ninputs].fd = fd; 37797c478bd9Sstevel@tonic-gate Nfd[Ninputs].events = POLLIN; 37807c478bd9Sstevel@tonic-gate Ninputs++; 37817c478bd9Sstevel@tonic-gate return (0); 37827c478bd9Sstevel@tonic-gate } 37837c478bd9Sstevel@tonic-gate 37847c478bd9Sstevel@tonic-gate /* 37857c478bd9Sstevel@tonic-gate * Allocate UDP buffer to minimize packet loss. 37867c478bd9Sstevel@tonic-gate */ 37877c478bd9Sstevel@tonic-gate static void 37887c478bd9Sstevel@tonic-gate set_udp_buffer(int fd) 37897c478bd9Sstevel@tonic-gate { 37907c478bd9Sstevel@tonic-gate struct t_optmgmt req, resp; 37917c478bd9Sstevel@tonic-gate struct opthdr *opt; 37927c478bd9Sstevel@tonic-gate size_t optsize, bsize = 256 * 1024; 37937c478bd9Sstevel@tonic-gate pthread_t mythreadno; 37947c478bd9Sstevel@tonic-gate 37957c478bd9Sstevel@tonic-gate if (Debug) { 37967c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 37977c478bd9Sstevel@tonic-gate } 37987c478bd9Sstevel@tonic-gate 37997c478bd9Sstevel@tonic-gate optsize = sizeof (struct opthdr) + sizeof (int); 38007c478bd9Sstevel@tonic-gate if ((opt = malloc(optsize)) == NULL) { 38017c478bd9Sstevel@tonic-gate MALLOC_FAIL("will have no udp buffer"); 38027c478bd9Sstevel@tonic-gate return; 38037c478bd9Sstevel@tonic-gate } 38047c478bd9Sstevel@tonic-gate opt->level = SOL_SOCKET; 38057c478bd9Sstevel@tonic-gate opt->name = SO_RCVBUF; 38067c478bd9Sstevel@tonic-gate opt->len = sizeof (int); 38077c478bd9Sstevel@tonic-gate *(int *)(opt + 1) = bsize; 38087c478bd9Sstevel@tonic-gate 38097c478bd9Sstevel@tonic-gate req.flags = T_NEGOTIATE; 38107c478bd9Sstevel@tonic-gate req.opt.len = optsize; 38117c478bd9Sstevel@tonic-gate req.opt.buf = (char *)opt; 38127c478bd9Sstevel@tonic-gate 38137c478bd9Sstevel@tonic-gate resp.flags = 0; 38147c478bd9Sstevel@tonic-gate resp.opt.maxlen = optsize; 38157c478bd9Sstevel@tonic-gate resp.opt.buf = (char *)opt; 38167c478bd9Sstevel@tonic-gate 38177c478bd9Sstevel@tonic-gate while (t_optmgmt(fd, &req, &resp) == -1 || resp.flags != T_SUCCESS) { 38187c478bd9Sstevel@tonic-gate if (t_errno != TSYSERR || errno != ENOBUFS) { 38197c478bd9Sstevel@tonic-gate bsize = 0; 38207c478bd9Sstevel@tonic-gate break; 38217c478bd9Sstevel@tonic-gate } 38227c478bd9Sstevel@tonic-gate bsize >>= 1; 38237c478bd9Sstevel@tonic-gate if (bsize < 8192) { 38247c478bd9Sstevel@tonic-gate break; 38257c478bd9Sstevel@tonic-gate } 38267c478bd9Sstevel@tonic-gate *(int *)(opt + 1) = bsize; 38277c478bd9Sstevel@tonic-gate } 38287c478bd9Sstevel@tonic-gate if (bsize == 0) { 38297c478bd9Sstevel@tonic-gate logerror("failed to allocate UDP buffer"); 38307c478bd9Sstevel@tonic-gate } 38317c478bd9Sstevel@tonic-gate DPRINT3(1, "set_udp_buffer(%u): allocate %d for fd %d\n", 38327c478bd9Sstevel@tonic-gate mythreadno, bsize, fd); 38337c478bd9Sstevel@tonic-gate free(opt); 38347c478bd9Sstevel@tonic-gate } 38357c478bd9Sstevel@tonic-gate 38367c478bd9Sstevel@tonic-gate /* 38377c478bd9Sstevel@tonic-gate * Attach the network, and allocate UDP buffer for the interface. 38387c478bd9Sstevel@tonic-gate */ 38397c478bd9Sstevel@tonic-gate static void 38407c478bd9Sstevel@tonic-gate bindnet(void) 38417c478bd9Sstevel@tonic-gate { 38427c478bd9Sstevel@tonic-gate struct t_bind bind, *bound; 38437c478bd9Sstevel@tonic-gate int cnt, i; 38447c478bd9Sstevel@tonic-gate char *uap; 38457c478bd9Sstevel@tonic-gate pthread_t mythreadno; 38467c478bd9Sstevel@tonic-gate 38477c478bd9Sstevel@tonic-gate if (Debug) { 38487c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 38497c478bd9Sstevel@tonic-gate } 38507c478bd9Sstevel@tonic-gate 38517c478bd9Sstevel@tonic-gate cnt = 0; 38527c478bd9Sstevel@tonic-gate 38537c478bd9Sstevel@tonic-gate while (cnt < Ninputs) { 38547c478bd9Sstevel@tonic-gate char ebuf[128]; 38557c478bd9Sstevel@tonic-gate 38567c478bd9Sstevel@tonic-gate /*LINTED*/ 38577c478bd9Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(Nfd[cnt].fd, T_BIND, T_ADDR); 38587c478bd9Sstevel@tonic-gate bind.addr = *Myaddrs[cnt]; 38597c478bd9Sstevel@tonic-gate bind.qlen = 0; 38607c478bd9Sstevel@tonic-gate 38617c478bd9Sstevel@tonic-gate if (t_bind(Nfd[cnt].fd, &bind, bound) == 0) { 38627c478bd9Sstevel@tonic-gate if (same_addr(&bind.addr, &bound->addr)) { 38630ea5e3a5Sjjj (void) t_free((char *)bound, T_BIND); 38647c478bd9Sstevel@tonic-gate set_udp_buffer(Nfd[cnt].fd); 38657c478bd9Sstevel@tonic-gate cnt++; 38667c478bd9Sstevel@tonic-gate continue; 38677c478bd9Sstevel@tonic-gate } 38687c478bd9Sstevel@tonic-gate } 38697c478bd9Sstevel@tonic-gate 38707c478bd9Sstevel@tonic-gate /* failed to bind port */ 38710ea5e3a5Sjjj (void) t_free((char *)bound, T_BIND); 38727c478bd9Sstevel@tonic-gate 38737c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to bind syslog port"); 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[cnt], Myaddrs[cnt]); 38767c478bd9Sstevel@tonic-gate if (uap) { 38777c478bd9Sstevel@tonic-gate i = strlen(ebuf); 38787c478bd9Sstevel@tonic-gate (void) snprintf(ebuf + i, sizeof (ebuf) - i, 38797c478bd9Sstevel@tonic-gate " for %s", uap); 38807c478bd9Sstevel@tonic-gate } 38817c478bd9Sstevel@tonic-gate 38827c478bd9Sstevel@tonic-gate DPRINT2(1, "bindnet(%u): failed to bind port (%s)\n", 38837c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate if (uap) { 38867c478bd9Sstevel@tonic-gate free(uap); 38877c478bd9Sstevel@tonic-gate } 38887c478bd9Sstevel@tonic-gate 38897c478bd9Sstevel@tonic-gate errno = 0; 38907c478bd9Sstevel@tonic-gate logerror(ebuf); 38917c478bd9Sstevel@tonic-gate 38920ea5e3a5Sjjj (void) t_close(Nfd[cnt].fd); 38937c478bd9Sstevel@tonic-gate free(Myaddrs[cnt]->buf); 38947c478bd9Sstevel@tonic-gate free(Myaddrs[cnt]); 38950ea5e3a5Sjjj (void) t_free((char *)Udp[cnt], T_UNITDATA); 38960ea5e3a5Sjjj (void) t_free((char *)Errp[cnt], T_UDERROR); 38977c478bd9Sstevel@tonic-gate 38987c478bd9Sstevel@tonic-gate for (i = cnt; i < (Ninputs-1); i++) { 38997c478bd9Sstevel@tonic-gate Nfd[i] = Nfd[i + 1]; 39007c478bd9Sstevel@tonic-gate Ncf[i] = Ncf[i + 1]; 39017c478bd9Sstevel@tonic-gate Myaddrs[i] = Myaddrs[i + 1]; 39027c478bd9Sstevel@tonic-gate Udp[i] = Udp[i + 1]; 39037c478bd9Sstevel@tonic-gate Errp[i] = Errp[i + 1]; 39047c478bd9Sstevel@tonic-gate } 39057c478bd9Sstevel@tonic-gate 39067c478bd9Sstevel@tonic-gate Ninputs--; 39077c478bd9Sstevel@tonic-gate } 39087c478bd9Sstevel@tonic-gate } 39097c478bd9Sstevel@tonic-gate 39107c478bd9Sstevel@tonic-gate static int 39110ea5e3a5Sjjj logforward(struct filed *f, char *ebuf, size_t elen) 39127c478bd9Sstevel@tonic-gate { 39137c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 39147c478bd9Sstevel@tonic-gate struct netbuf *nbp; 39157c478bd9Sstevel@tonic-gate struct netconfig *ncp; 39167c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 39177c478bd9Sstevel@tonic-gate void *handle; 39187c478bd9Sstevel@tonic-gate char *hp; 39197c478bd9Sstevel@tonic-gate 39207c478bd9Sstevel@tonic-gate hp = f->f_un.f_forw.f_hname; 39217c478bd9Sstevel@tonic-gate hs.h_host = hp; 39227c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 39237c478bd9Sstevel@tonic-gate 39247c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 39250ea5e3a5Sjjj (void) strlcpy(ebuf, 39260ea5e3a5Sjjj "unable to rewind the netconfig database", elen); 39277c478bd9Sstevel@tonic-gate errno = 0; 39287c478bd9Sstevel@tonic-gate return (-1); 39297c478bd9Sstevel@tonic-gate } 39307c478bd9Sstevel@tonic-gate nap = (struct nd_addrlist *)NULL; 39317c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 39327c478bd9Sstevel@tonic-gate if (ncp->nc_semantics == NC_TPI_CLTS) { 39337c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) == 0) { 39347c478bd9Sstevel@tonic-gate if (!nap) 39357c478bd9Sstevel@tonic-gate continue; 39367c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 39377c478bd9Sstevel@tonic-gate break; 39387c478bd9Sstevel@tonic-gate } 39397c478bd9Sstevel@tonic-gate } 39407c478bd9Sstevel@tonic-gate } 39417c478bd9Sstevel@tonic-gate if (ncp == NULL) { 39420ea5e3a5Sjjj (void) endnetconfig(handle); 39430ea5e3a5Sjjj (void) snprintf(ebuf, elen, 39440ea5e3a5Sjjj "WARNING: %s could not be resolved", hp); 39457c478bd9Sstevel@tonic-gate errno = 0; 39467c478bd9Sstevel@tonic-gate return (-1); 39477c478bd9Sstevel@tonic-gate } 39487c478bd9Sstevel@tonic-gate if (nap == (struct nd_addrlist *)NULL) { 39490ea5e3a5Sjjj (void) endnetconfig(handle); 39500ea5e3a5Sjjj (void) snprintf(ebuf, elen, "unknown host %s", hp); 39517c478bd9Sstevel@tonic-gate errno = 0; 39527c478bd9Sstevel@tonic-gate return (-1); 39537c478bd9Sstevel@tonic-gate } 39547c478bd9Sstevel@tonic-gate /* CSTYLED */ 39557c478bd9Sstevel@tonic-gate if (ismyaddr(nbp)) { /*lint !e644 */ 39567c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 39570ea5e3a5Sjjj (void) endnetconfig(handle); 39580ea5e3a5Sjjj (void) snprintf(ebuf, elen, 39590ea5e3a5Sjjj "host %s is this host - logging loop", hp); 39607c478bd9Sstevel@tonic-gate errno = 0; 39617c478bd9Sstevel@tonic-gate return (-1); 39627c478bd9Sstevel@tonic-gate } 39637c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_addr.buf = malloc(nbp->len); 39647c478bd9Sstevel@tonic-gate if (f->f_un.f_forw.f_addr.buf == NULL) { 39657c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 39660ea5e3a5Sjjj (void) endnetconfig(handle); 39670ea5e3a5Sjjj (void) strlcpy(ebuf, "malloc failed", elen); 39687c478bd9Sstevel@tonic-gate return (-1); 39697c478bd9Sstevel@tonic-gate } 39707c478bd9Sstevel@tonic-gate bcopy(nbp->buf, f->f_un.f_forw.f_addr.buf, nbp->len); 39717c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_addr.len = nbp->len; 39727c478bd9Sstevel@tonic-gate f->f_file = t_open(ncp->nc_device, O_RDWR, NULL); 39737c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 39747c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 39750ea5e3a5Sjjj (void) endnetconfig(handle); 39767c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 39770ea5e3a5Sjjj (void) strlcpy(ebuf, "t_open", elen); 39787c478bd9Sstevel@tonic-gate return (-1); 39797c478bd9Sstevel@tonic-gate } 39807c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 39810ea5e3a5Sjjj (void) endnetconfig(handle); 39827c478bd9Sstevel@tonic-gate if (t_bind(f->f_file, NULL, NULL) < 0) { 39830ea5e3a5Sjjj (void) strlcpy(ebuf, "t_bind", elen); 39847c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 39850ea5e3a5Sjjj (void) t_close(f->f_file); 39867c478bd9Sstevel@tonic-gate return (-1); 39877c478bd9Sstevel@tonic-gate } 39887c478bd9Sstevel@tonic-gate return (0); 39897c478bd9Sstevel@tonic-gate } 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate static int 39927c478bd9Sstevel@tonic-gate amiloghost(void) 39937c478bd9Sstevel@tonic-gate { 39947c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 39957c478bd9Sstevel@tonic-gate struct netconfig *ncp; 39967c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 39977c478bd9Sstevel@tonic-gate struct netbuf *nbp; 39987c478bd9Sstevel@tonic-gate int i, fd; 39997c478bd9Sstevel@tonic-gate void *handle; 40007c478bd9Sstevel@tonic-gate char *uap; 40017c478bd9Sstevel@tonic-gate struct t_bind bind, *bound; 40027c478bd9Sstevel@tonic-gate pthread_t mythreadno; 40037c478bd9Sstevel@tonic-gate 40047c478bd9Sstevel@tonic-gate if (Debug) { 40057c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 40067c478bd9Sstevel@tonic-gate } 40077c478bd9Sstevel@tonic-gate 40087c478bd9Sstevel@tonic-gate /* 40097c478bd9Sstevel@tonic-gate * we need to know if we are running on the loghost. This is 40107c478bd9Sstevel@tonic-gate * checked by binding to the address associated with "loghost" 40117c478bd9Sstevel@tonic-gate * and "syslogd" service over the connectionless transport 40127c478bd9Sstevel@tonic-gate */ 40137c478bd9Sstevel@tonic-gate hs.h_host = "loghost"; 40147c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 40157c478bd9Sstevel@tonic-gate 40167c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 40177c478bd9Sstevel@tonic-gate return (0); 40187c478bd9Sstevel@tonic-gate } 40197c478bd9Sstevel@tonic-gate 40207c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 40217c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 40227c478bd9Sstevel@tonic-gate continue; 40237c478bd9Sstevel@tonic-gate } 40247c478bd9Sstevel@tonic-gate 40257c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) { 40267c478bd9Sstevel@tonic-gate continue; 40277c478bd9Sstevel@tonic-gate } 40287c478bd9Sstevel@tonic-gate 40297c478bd9Sstevel@tonic-gate if (nap == NULL) { 40307c478bd9Sstevel@tonic-gate continue; 40317c478bd9Sstevel@tonic-gate } 40327c478bd9Sstevel@tonic-gate 40337c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 40347c478bd9Sstevel@tonic-gate 40357c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) { 40367c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != (char *)NULL) { 40377c478bd9Sstevel@tonic-gate DPRINT2(1, "amiloghost(%u): testing %s\n", 40387c478bd9Sstevel@tonic-gate mythreadno, uap); 40397c478bd9Sstevel@tonic-gate } 40407c478bd9Sstevel@tonic-gate 40417c478bd9Sstevel@tonic-gate free(uap); 40427c478bd9Sstevel@tonic-gate 40437c478bd9Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL); 40447c478bd9Sstevel@tonic-gate 40457c478bd9Sstevel@tonic-gate if (fd < 0) { 40467c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 40470ea5e3a5Sjjj (void) endnetconfig(handle); 40487c478bd9Sstevel@tonic-gate return (0); 40497c478bd9Sstevel@tonic-gate } 40507c478bd9Sstevel@tonic-gate 40517c478bd9Sstevel@tonic-gate /*LINTED*/ 40527c478bd9Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 40537c478bd9Sstevel@tonic-gate bind.addr = *nbp; 40547c478bd9Sstevel@tonic-gate bind.qlen = 0; 40557c478bd9Sstevel@tonic-gate 40567c478bd9Sstevel@tonic-gate if (t_bind(fd, &bind, bound) == 0) { 40570ea5e3a5Sjjj (void) t_close(fd); 40580ea5e3a5Sjjj (void) t_free((char *)bound, T_BIND); 40597c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 40600ea5e3a5Sjjj (void) endnetconfig(handle); 40617c478bd9Sstevel@tonic-gate return (1); 40627c478bd9Sstevel@tonic-gate } else { 40630ea5e3a5Sjjj (void) t_close(fd); 40640ea5e3a5Sjjj (void) t_free((char *)bound, T_BIND); 40657c478bd9Sstevel@tonic-gate } 40667c478bd9Sstevel@tonic-gate 40677c478bd9Sstevel@tonic-gate nbp++; 40687c478bd9Sstevel@tonic-gate } 40697c478bd9Sstevel@tonic-gate 40707c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 40717c478bd9Sstevel@tonic-gate } 40727c478bd9Sstevel@tonic-gate 40730ea5e3a5Sjjj (void) endnetconfig(handle); 40747c478bd9Sstevel@tonic-gate return (0); 40757c478bd9Sstevel@tonic-gate } 40767c478bd9Sstevel@tonic-gate 40777c478bd9Sstevel@tonic-gate int 40787c478bd9Sstevel@tonic-gate same_addr(struct netbuf *na, struct netbuf *nb) 40797c478bd9Sstevel@tonic-gate { 40807c478bd9Sstevel@tonic-gate char *a, *b; 40817c478bd9Sstevel@tonic-gate size_t n; 40827c478bd9Sstevel@tonic-gate 40830ea5e3a5Sjjj assert(na->buf != NULL && nb->buf != NULL); 40847c478bd9Sstevel@tonic-gate 40857c478bd9Sstevel@tonic-gate if (na->len != nb->len) { 40867c478bd9Sstevel@tonic-gate return (0); 40877c478bd9Sstevel@tonic-gate } 40887c478bd9Sstevel@tonic-gate 40897c478bd9Sstevel@tonic-gate a = na->buf; 40907c478bd9Sstevel@tonic-gate b = nb->buf; 40917c478bd9Sstevel@tonic-gate n = nb->len; 40927c478bd9Sstevel@tonic-gate 40937c478bd9Sstevel@tonic-gate while (n-- > 0) { 40947c478bd9Sstevel@tonic-gate if (*a++ != *b++) { 40957c478bd9Sstevel@tonic-gate return (0); 40967c478bd9Sstevel@tonic-gate } 40977c478bd9Sstevel@tonic-gate } 40987c478bd9Sstevel@tonic-gate 40997c478bd9Sstevel@tonic-gate return (1); 41007c478bd9Sstevel@tonic-gate } 41017c478bd9Sstevel@tonic-gate 41027c478bd9Sstevel@tonic-gate /* 41037c478bd9Sstevel@tonic-gate * allocates a new message structure, initializes it 41047c478bd9Sstevel@tonic-gate * and returns a pointer to it 41057c478bd9Sstevel@tonic-gate */ 41067c478bd9Sstevel@tonic-gate static log_message_t * 41077c478bd9Sstevel@tonic-gate new_msg(void) 41087c478bd9Sstevel@tonic-gate { 41097c478bd9Sstevel@tonic-gate log_message_t *lm; 41107c478bd9Sstevel@tonic-gate pthread_t mythreadno; 41117c478bd9Sstevel@tonic-gate 41127c478bd9Sstevel@tonic-gate if (Debug) { 41137c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 41147c478bd9Sstevel@tonic-gate } 41157c478bd9Sstevel@tonic-gate 41167c478bd9Sstevel@tonic-gate if ((lm = malloc(sizeof (log_message_t))) == NULL) 41177c478bd9Sstevel@tonic-gate return ((log_message_t *)NULL); 41187c478bd9Sstevel@tonic-gate 41197c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lm)) 41207c478bd9Sstevel@tonic-gate 41217c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&lm->msg_mutex, NULL) != 0) 41227c478bd9Sstevel@tonic-gate return ((log_message_t *)NULL); 41237c478bd9Sstevel@tonic-gate lm->refcnt = 0; 41247c478bd9Sstevel@tonic-gate lm->pri = 0; 41257c478bd9Sstevel@tonic-gate lm->flags = 0; 41267c478bd9Sstevel@tonic-gate lm->hlp = NULL; 41277c478bd9Sstevel@tonic-gate lm->msg[0] = '\0'; 41287c478bd9Sstevel@tonic-gate lm->ptr = NULL; 41297c478bd9Sstevel@tonic-gate 41300ea5e3a5Sjjj DPRINT2(3, "new_msg(%u): creating msg %p\n", mythreadno, (void *)lm); 41317c478bd9Sstevel@tonic-gate return (lm); 41327c478bd9Sstevel@tonic-gate } 41337c478bd9Sstevel@tonic-gate 41347c478bd9Sstevel@tonic-gate /* 41357c478bd9Sstevel@tonic-gate * frees a message structure - should only be called if 41367c478bd9Sstevel@tonic-gate * the refcount is 0 41377c478bd9Sstevel@tonic-gate */ 41387c478bd9Sstevel@tonic-gate static void 41397c478bd9Sstevel@tonic-gate free_msg(log_message_t *lm) 41407c478bd9Sstevel@tonic-gate { 41417c478bd9Sstevel@tonic-gate pthread_t mythreadno; 41427c478bd9Sstevel@tonic-gate 41437c478bd9Sstevel@tonic-gate if (Debug) { 41447c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 41457c478bd9Sstevel@tonic-gate } 41467c478bd9Sstevel@tonic-gate 41477c478bd9Sstevel@tonic-gate assert(lm != NULL && lm->refcnt == 0); 41487c478bd9Sstevel@tonic-gate if (lm->hlp != NULL) 41497c478bd9Sstevel@tonic-gate freehl(lm->hlp); 41500ea5e3a5Sjjj DPRINT2(3, "free_msg(%u): freeing msg %p\n", mythreadno, (void *)lm); 41517c478bd9Sstevel@tonic-gate free(lm); 41527c478bd9Sstevel@tonic-gate } 41537c478bd9Sstevel@tonic-gate 41547c478bd9Sstevel@tonic-gate /* 41557c478bd9Sstevel@tonic-gate * Make sure that the message makes sense in the current locale, and 41567c478bd9Sstevel@tonic-gate * does not contain stray control characters. 41577c478bd9Sstevel@tonic-gate */ 41587c478bd9Sstevel@tonic-gate static void 41597c478bd9Sstevel@tonic-gate filter_string(char *mbstr, char *filtered, size_t max) 41607c478bd9Sstevel@tonic-gate { 41617c478bd9Sstevel@tonic-gate size_t cs = 0; 41627c478bd9Sstevel@tonic-gate size_t mb_cur_max; 41637c478bd9Sstevel@tonic-gate unsigned char *p = (unsigned char *)mbstr; 41647c478bd9Sstevel@tonic-gate pthread_t mythreadno = 0; 41657c478bd9Sstevel@tonic-gate 41667c478bd9Sstevel@tonic-gate if (Debug) { 41677c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 41687c478bd9Sstevel@tonic-gate } 41697c478bd9Sstevel@tonic-gate 41707c478bd9Sstevel@tonic-gate assert(mbstr != NULL && filtered != NULL); 41717c478bd9Sstevel@tonic-gate 41727c478bd9Sstevel@tonic-gate /* 41737c478bd9Sstevel@tonic-gate * Since the access to MB_CUR_MAX is expensive (because 41747c478bd9Sstevel@tonic-gate * MB_CUR_MAX lives in a global area), it should be 41757c478bd9Sstevel@tonic-gate * restrained for the better performance. 41767c478bd9Sstevel@tonic-gate */ 41777c478bd9Sstevel@tonic-gate mb_cur_max = (size_t)MB_CUR_MAX; 41787c478bd9Sstevel@tonic-gate if (mb_cur_max > 1) { 41797c478bd9Sstevel@tonic-gate /* multibyte locale */ 41807c478bd9Sstevel@tonic-gate int mlen; 41817c478bd9Sstevel@tonic-gate wchar_t wc; 41827c478bd9Sstevel@tonic-gate 41837c478bd9Sstevel@tonic-gate while (*p != '\0') { 41847c478bd9Sstevel@tonic-gate if ((mlen = mbtowc(&wc, (char *)p, 41857c478bd9Sstevel@tonic-gate mb_cur_max)) == -1) { 41867c478bd9Sstevel@tonic-gate /* 41877c478bd9Sstevel@tonic-gate * Invalid byte sequence found. 41887c478bd9Sstevel@tonic-gate * 41897c478bd9Sstevel@tonic-gate * try to print one byte 41907c478bd9Sstevel@tonic-gate * in ASCII format. 41917c478bd9Sstevel@tonic-gate */ 41927c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): Invalid " 41930ea5e3a5Sjjj "MB sequence: %ld\n", mythreadno, 41947c478bd9Sstevel@tonic-gate wc); 41957c478bd9Sstevel@tonic-gate 41967c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 41977c478bd9Sstevel@tonic-gate /* not enough buffer */ 41987c478bd9Sstevel@tonic-gate goto end; 41997c478bd9Sstevel@tonic-gate } else { 42007c478bd9Sstevel@tonic-gate continue; 42017c478bd9Sstevel@tonic-gate } 42027c478bd9Sstevel@tonic-gate } else { 42037c478bd9Sstevel@tonic-gate /* 42047c478bd9Sstevel@tonic-gate * Since *p is not a null byte here, 42057c478bd9Sstevel@tonic-gate * mbtowc should have never returned 0. 42067c478bd9Sstevel@tonic-gate * 42077c478bd9Sstevel@tonic-gate * A valid wide character found. 42087c478bd9Sstevel@tonic-gate */ 42097c478bd9Sstevel@tonic-gate 42107c478bd9Sstevel@tonic-gate if (wc != L'\t' && iswcntrl(wc)) { 42117c478bd9Sstevel@tonic-gate /* 42127c478bd9Sstevel@tonic-gate * non-tab, non-newline, and 42137c478bd9Sstevel@tonic-gate * control character found. 42147c478bd9Sstevel@tonic-gate * 42157c478bd9Sstevel@tonic-gate * try to print this wide character 42167c478bd9Sstevel@tonic-gate * in ASCII-format. 42177c478bd9Sstevel@tonic-gate */ 42187c478bd9Sstevel@tonic-gate char *q = filtered; 42197c478bd9Sstevel@tonic-gate 42207c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): MB" 42210ea5e3a5Sjjj " control character: %ld\n", 42227c478bd9Sstevel@tonic-gate mythreadno, wc); 42237c478bd9Sstevel@tonic-gate 42247c478bd9Sstevel@tonic-gate while (mlen--) { 42257c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, 42267c478bd9Sstevel@tonic-gate &cs, max)) { 42277c478bd9Sstevel@tonic-gate /* 42287c478bd9Sstevel@tonic-gate * not enough buffer in 42297c478bd9Sstevel@tonic-gate * filtered 42307c478bd9Sstevel@tonic-gate * 42317c478bd9Sstevel@tonic-gate * cancel already 42327c478bd9Sstevel@tonic-gate * stored bytes in 42337c478bd9Sstevel@tonic-gate * filtered for this 42347c478bd9Sstevel@tonic-gate * wide character. 42357c478bd9Sstevel@tonic-gate */ 42367c478bd9Sstevel@tonic-gate filtered = q; 42377c478bd9Sstevel@tonic-gate goto end; 42387c478bd9Sstevel@tonic-gate } 42397c478bd9Sstevel@tonic-gate } 42407c478bd9Sstevel@tonic-gate continue; 42417c478bd9Sstevel@tonic-gate } else { 42427c478bd9Sstevel@tonic-gate /* 42437c478bd9Sstevel@tonic-gate * tab, newline, or non-control 42447c478bd9Sstevel@tonic-gate * character found. 42457c478bd9Sstevel@tonic-gate */ 42467c478bd9Sstevel@tonic-gate if (cs + mlen < max) { 42477c478bd9Sstevel@tonic-gate /* enough buffer */ 42487c478bd9Sstevel@tonic-gate cs += mlen; 42497c478bd9Sstevel@tonic-gate while (mlen--) { 42507c478bd9Sstevel@tonic-gate *filtered++ = *p++; 42517c478bd9Sstevel@tonic-gate } 42527c478bd9Sstevel@tonic-gate continue; 42537c478bd9Sstevel@tonic-gate } else { 42547c478bd9Sstevel@tonic-gate /* not enough buffer */ 42557c478bd9Sstevel@tonic-gate goto end; 42567c478bd9Sstevel@tonic-gate } 42577c478bd9Sstevel@tonic-gate } 42587c478bd9Sstevel@tonic-gate } 42597c478bd9Sstevel@tonic-gate } 42607c478bd9Sstevel@tonic-gate } else { 42617c478bd9Sstevel@tonic-gate /* singlebyte locale */ 42627c478bd9Sstevel@tonic-gate 42637c478bd9Sstevel@tonic-gate while (*p != '\0') { 42647c478bd9Sstevel@tonic-gate if (*p != '\t' && iscntrl(*p)) { 42657c478bd9Sstevel@tonic-gate /* 42667c478bd9Sstevel@tonic-gate * non-tab, non-newline, 42677c478bd9Sstevel@tonic-gate * and control character found. 42687c478bd9Sstevel@tonic-gate * 42697c478bd9Sstevel@tonic-gate * try to print this singlebyte character 42707c478bd9Sstevel@tonic-gate * in ASCII format. 42717c478bd9Sstevel@tonic-gate */ 42727c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): control " 42737c478bd9Sstevel@tonic-gate "character: %d\n", mythreadno, *p); 42747c478bd9Sstevel@tonic-gate 42757c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 42767c478bd9Sstevel@tonic-gate /* not enough buffer */ 42777c478bd9Sstevel@tonic-gate goto end; 42787c478bd9Sstevel@tonic-gate } else { 42797c478bd9Sstevel@tonic-gate continue; 42807c478bd9Sstevel@tonic-gate } 42817c478bd9Sstevel@tonic-gate } else if (*p != '\t' && !isprint(*p)) { 42827c478bd9Sstevel@tonic-gate /* 42837c478bd9Sstevel@tonic-gate * non-tab and non printable character found 42847c478bd9Sstevel@tonic-gate * this check is required for the C locale 42857c478bd9Sstevel@tonic-gate */ 42867c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): non-printable " 42877c478bd9Sstevel@tonic-gate "character: %d\n", mythreadno, *p); 42887c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 42897c478bd9Sstevel@tonic-gate /* not enough buffer */ 42907c478bd9Sstevel@tonic-gate goto end; 42917c478bd9Sstevel@tonic-gate } else { 42927c478bd9Sstevel@tonic-gate continue; 42937c478bd9Sstevel@tonic-gate } 42947c478bd9Sstevel@tonic-gate } else { 42957c478bd9Sstevel@tonic-gate /* 42967c478bd9Sstevel@tonic-gate * tab, newline, non-control character, or 42977c478bd9Sstevel@tonic-gate * printable found. 42987c478bd9Sstevel@tonic-gate */ 42997c478bd9Sstevel@tonic-gate if (cs + 1 < max) { 43007c478bd9Sstevel@tonic-gate *filtered++ = *p++; 43017c478bd9Sstevel@tonic-gate cs++; 43027c478bd9Sstevel@tonic-gate continue; 43037c478bd9Sstevel@tonic-gate } else { 43047c478bd9Sstevel@tonic-gate /* not enough buffer */ 43057c478bd9Sstevel@tonic-gate goto end; 43067c478bd9Sstevel@tonic-gate } 43077c478bd9Sstevel@tonic-gate } 43087c478bd9Sstevel@tonic-gate } 43097c478bd9Sstevel@tonic-gate } 43107c478bd9Sstevel@tonic-gate 43117c478bd9Sstevel@tonic-gate end: 43127c478bd9Sstevel@tonic-gate *filtered = '\0'; 43137c478bd9Sstevel@tonic-gate 43147c478bd9Sstevel@tonic-gate if (cs >= 2 && 43157c478bd9Sstevel@tonic-gate filtered[-2] == '\\' && filtered[-1] == 'n') { 43167c478bd9Sstevel@tonic-gate filtered[-2] = '\0'; 43177c478bd9Sstevel@tonic-gate } 43187c478bd9Sstevel@tonic-gate } 43197c478bd9Sstevel@tonic-gate 43207c478bd9Sstevel@tonic-gate static char * 43217c478bd9Sstevel@tonic-gate alloc_stacks(int numstacks) 43227c478bd9Sstevel@tonic-gate { 43237c478bd9Sstevel@tonic-gate size_t pagesize, mapsize; 43247c478bd9Sstevel@tonic-gate char *stack_top; 43257c478bd9Sstevel@tonic-gate char *addr; 43267c478bd9Sstevel@tonic-gate int i; 43277c478bd9Sstevel@tonic-gate 43287c478bd9Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE); 43297c478bd9Sstevel@tonic-gate /* 43307c478bd9Sstevel@tonic-gate * stacksize and redzonesize are global so threads 43317c478bd9Sstevel@tonic-gate * can be created elsewhere and refer to the sizes 43327c478bd9Sstevel@tonic-gate */ 43337c478bd9Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) + 43347c478bd9Sstevel@tonic-gate DEFAULT_STACKSIZE, pagesize); 43357c478bd9Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize); 43367c478bd9Sstevel@tonic-gate 43377c478bd9Sstevel@tonic-gate /* 43387c478bd9Sstevel@tonic-gate * allocate an additional "redzonesize" chunk in addition 43397c478bd9Sstevel@tonic-gate * to what we require, so we can create a redzone at the 43407c478bd9Sstevel@tonic-gate * bottom of the last stack as well. 43417c478bd9Sstevel@tonic-gate */ 43427c478bd9Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize); 43437c478bd9Sstevel@tonic-gate stack_top = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, 43447c478bd9Sstevel@tonic-gate MAP_PRIVATE|MAP_ANON, -1, 0); 43457c478bd9Sstevel@tonic-gate if (stack_top == MAP_FAILED) 43467c478bd9Sstevel@tonic-gate return (NULL); 43477c478bd9Sstevel@tonic-gate 43487c478bd9Sstevel@tonic-gate addr = stack_top; 43497c478bd9Sstevel@tonic-gate /* 43507c478bd9Sstevel@tonic-gate * this loop is intentionally <= instead of <, so we can 43517c478bd9Sstevel@tonic-gate * protect the redzone at the bottom of the last stack 43527c478bd9Sstevel@tonic-gate */ 43537c478bd9Sstevel@tonic-gate for (i = 0; i <= numstacks; i++) { 43547c478bd9Sstevel@tonic-gate (void) mprotect(addr, redzonesize, PROT_NONE); 43557c478bd9Sstevel@tonic-gate addr += stacksize + redzonesize; 43567c478bd9Sstevel@tonic-gate } 43577c478bd9Sstevel@tonic-gate return ((char *)(stack_top + redzonesize)); 43587c478bd9Sstevel@tonic-gate } 43597c478bd9Sstevel@tonic-gate 43607c478bd9Sstevel@tonic-gate static void 43617c478bd9Sstevel@tonic-gate dealloc_stacks(int numstacks) 43627c478bd9Sstevel@tonic-gate { 43637c478bd9Sstevel@tonic-gate size_t pagesize, mapsize; 43647c478bd9Sstevel@tonic-gate 43657c478bd9Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE); 43667c478bd9Sstevel@tonic-gate 43677c478bd9Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) + 43687c478bd9Sstevel@tonic-gate DEFAULT_STACKSIZE, pagesize); 43697c478bd9Sstevel@tonic-gate 43707c478bd9Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize); 43717c478bd9Sstevel@tonic-gate 43727c478bd9Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize); 43737c478bd9Sstevel@tonic-gate (void) munmap(cstack_ptr - mapsize, mapsize); 43747c478bd9Sstevel@tonic-gate } 43757c478bd9Sstevel@tonic-gate 43767c478bd9Sstevel@tonic-gate static void 43777c478bd9Sstevel@tonic-gate filed_destroy(struct filed *f) 43787c478bd9Sstevel@tonic-gate { 43797c478bd9Sstevel@tonic-gate (void) dataq_destroy(&f->f_queue); 43800ea5e3a5Sjjj (void) pthread_mutex_destroy(&f->filed_mutex); 43817c478bd9Sstevel@tonic-gate } 43827c478bd9Sstevel@tonic-gate 43837c478bd9Sstevel@tonic-gate static void 43847c478bd9Sstevel@tonic-gate close_door(void) 43857c478bd9Sstevel@tonic-gate { 43867c478bd9Sstevel@tonic-gate pthread_t mythreadno; 43877c478bd9Sstevel@tonic-gate 43887c478bd9Sstevel@tonic-gate if (Debug) { 43897c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 43907c478bd9Sstevel@tonic-gate } 43917c478bd9Sstevel@tonic-gate 43927c478bd9Sstevel@tonic-gate (void) fdetach(DoorFileName); 43937c478bd9Sstevel@tonic-gate 43947c478bd9Sstevel@tonic-gate DPRINT2(5, "close_door(%u): detached server() from %s\n", 43957c478bd9Sstevel@tonic-gate mythreadno, DoorFileName); 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate 43987c478bd9Sstevel@tonic-gate static void 43997c478bd9Sstevel@tonic-gate delete_doorfiles(void) 44007c478bd9Sstevel@tonic-gate { 44017c478bd9Sstevel@tonic-gate pthread_t mythreadno; 44027c478bd9Sstevel@tonic-gate struct stat sb; 44037c478bd9Sstevel@tonic-gate int err; 44047c478bd9Sstevel@tonic-gate char line[MAXLINE+1]; 44057c478bd9Sstevel@tonic-gate 44067c478bd9Sstevel@tonic-gate if (Debug) { 44077c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 44087c478bd9Sstevel@tonic-gate } 44097c478bd9Sstevel@tonic-gate 44107c478bd9Sstevel@tonic-gate 44117c478bd9Sstevel@tonic-gate if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 44127c478bd9Sstevel@tonic-gate if (unlink(DoorFileName) < 0) { 44137c478bd9Sstevel@tonic-gate err = errno; 44140ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 44150ea5e3a5Sjjj "unlink() of %s failed - fatal", DoorFileName); 44167c478bd9Sstevel@tonic-gate errno = err; 44177c478bd9Sstevel@tonic-gate logerror(line); 44187c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, " 44197c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, err); 44207c478bd9Sstevel@tonic-gate exit(1); 44217c478bd9Sstevel@tonic-gate } 44227c478bd9Sstevel@tonic-gate 44237c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 44247c478bd9Sstevel@tonic-gate mythreadno, DoorFileName); 44257c478bd9Sstevel@tonic-gate } 44267c478bd9Sstevel@tonic-gate 44277c478bd9Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) { 44287c478bd9Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 44297c478bd9Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) { 44307c478bd9Sstevel@tonic-gate err = errno; 44310ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 44320ea5e3a5Sjjj "unlink() of %s failed", OLD_DOORFILE); 44337c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s\n", 44347c478bd9Sstevel@tonic-gate mythreadno, line); 44357c478bd9Sstevel@tonic-gate 44367c478bd9Sstevel@tonic-gate if (err != EROFS) { 44377c478bd9Sstevel@tonic-gate errno = err; 44380ea5e3a5Sjjj (void) strlcat(line, " - fatal", 44390ea5e3a5Sjjj sizeof (line)); 44407c478bd9Sstevel@tonic-gate logerror(line); 44417c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): " 44427c478bd9Sstevel@tonic-gate "error: %s, errno=%d\n", 44437c478bd9Sstevel@tonic-gate mythreadno, line, err); 44447c478bd9Sstevel@tonic-gate exit(1); 44457c478bd9Sstevel@tonic-gate } 44467c478bd9Sstevel@tonic-gate 44477c478bd9Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink() " 44487c478bd9Sstevel@tonic-gate "failure OK on RO file system\n", 44497c478bd9Sstevel@tonic-gate mythreadno); 44507c478bd9Sstevel@tonic-gate } 44517c478bd9Sstevel@tonic-gate 44527c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 44537c478bd9Sstevel@tonic-gate mythreadno, OLD_DOORFILE); 44547c478bd9Sstevel@tonic-gate } 44557c478bd9Sstevel@tonic-gate } 44567c478bd9Sstevel@tonic-gate 44577c478bd9Sstevel@tonic-gate if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 44587c478bd9Sstevel@tonic-gate if (unlink(PidFileName) < 0) { 44597c478bd9Sstevel@tonic-gate err = errno; 44600ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 44610ea5e3a5Sjjj "unlink() of %s failed - fatal", PidFileName); 44627c478bd9Sstevel@tonic-gate errno = err; 44637c478bd9Sstevel@tonic-gate logerror(line); 44647c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, " 44657c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, err); 44667c478bd9Sstevel@tonic-gate exit(1); 44677c478bd9Sstevel@tonic-gate } 44687c478bd9Sstevel@tonic-gate 44697c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", mythreadno, 44707c478bd9Sstevel@tonic-gate PidFileName); 44717c478bd9Sstevel@tonic-gate } 44727c478bd9Sstevel@tonic-gate 44737c478bd9Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) { 44747c478bd9Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 44757c478bd9Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) { 44767c478bd9Sstevel@tonic-gate err = errno; 44770ea5e3a5Sjjj (void) snprintf(line, sizeof (line), 44780ea5e3a5Sjjj "unlink() of %s failed", OLD_PIDFILE); 44797c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s, \n", 44807c478bd9Sstevel@tonic-gate mythreadno, line); 44817c478bd9Sstevel@tonic-gate 44827c478bd9Sstevel@tonic-gate if (err != EROFS) { 44837c478bd9Sstevel@tonic-gate errno = err; 44840ea5e3a5Sjjj (void) strlcat(line, " - fatal", 44850ea5e3a5Sjjj sizeof (line)); 44867c478bd9Sstevel@tonic-gate logerror(line); 44877c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): " 44887c478bd9Sstevel@tonic-gate "error: %s, errno=%d\n", 44897c478bd9Sstevel@tonic-gate mythreadno, line, err); 44907c478bd9Sstevel@tonic-gate exit(1); 44917c478bd9Sstevel@tonic-gate } 44927c478bd9Sstevel@tonic-gate 44937c478bd9Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink " 44947c478bd9Sstevel@tonic-gate "failure OK on RO file system\n", 44957c478bd9Sstevel@tonic-gate mythreadno); 44967c478bd9Sstevel@tonic-gate } 44977c478bd9Sstevel@tonic-gate 44987c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 44997c478bd9Sstevel@tonic-gate mythreadno, OLD_PIDFILE); 45007c478bd9Sstevel@tonic-gate } 45017c478bd9Sstevel@tonic-gate } 45027c478bd9Sstevel@tonic-gate 45037c478bd9Sstevel@tonic-gate if (DoorFd != -1) { 45047c478bd9Sstevel@tonic-gate (void) door_revoke(DoorFd); 45057c478bd9Sstevel@tonic-gate } 45067c478bd9Sstevel@tonic-gate 45077c478bd9Sstevel@tonic-gate DPRINT2(1, "delete_doorfiles(%u): revoked door: DoorFd=%d\n", 45087c478bd9Sstevel@tonic-gate mythreadno, DoorFd); 45097c478bd9Sstevel@tonic-gate } 45107c478bd9Sstevel@tonic-gate 45117c478bd9Sstevel@tonic-gate 45127c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 45137c478bd9Sstevel@tonic-gate static void 45147c478bd9Sstevel@tonic-gate signull(int sig, siginfo_t *sip, void *utp) 45157c478bd9Sstevel@tonic-gate { 45167c478bd9Sstevel@tonic-gate DPRINT1(1, "signull(%u): THIS CALL SHOULD NEVER HAPPEN\n", 45177c478bd9Sstevel@tonic-gate pthread_self()); 45187c478bd9Sstevel@tonic-gate /* 45197c478bd9Sstevel@tonic-gate * Do nothing, as this is a place-holder used in conjunction with 45207c478bd9Sstevel@tonic-gate * sigaction()/sigwait() to ensure that the proper disposition is 45217c478bd9Sstevel@tonic-gate * given to the signals we handle in main(). 45227c478bd9Sstevel@tonic-gate */ 45237c478bd9Sstevel@tonic-gate } 45247c478bd9Sstevel@tonic-gate 45257c478bd9Sstevel@tonic-gate /* 45267c478bd9Sstevel@tonic-gate * putctrlc returns zero, if failed due to not enough buffer. 45277c478bd9Sstevel@tonic-gate * Otherwise, putctrlc returns non-zero. 45287c478bd9Sstevel@tonic-gate * 45297c478bd9Sstevel@tonic-gate * c: a byte to print in ASCII format 45307c478bd9Sstevel@tonic-gate * **buf: a pointer to the pointer to the output buffer. 45317c478bd9Sstevel@tonic-gate * *cl: current length of characters in the output buffer 45327c478bd9Sstevel@tonic-gate * max: maximum length of the buffer 45337c478bd9Sstevel@tonic-gate */ 45347c478bd9Sstevel@tonic-gate 45357c478bd9Sstevel@tonic-gate static int 45367c478bd9Sstevel@tonic-gate putctrlc(int c, char **buf, size_t *cl, size_t max) 45377c478bd9Sstevel@tonic-gate { 45387c478bd9Sstevel@tonic-gate char *p = *buf; 45397c478bd9Sstevel@tonic-gate 45407c478bd9Sstevel@tonic-gate if (c == '\n') { 45417c478bd9Sstevel@tonic-gate if (*cl + 2 < max) { 45427c478bd9Sstevel@tonic-gate *p++ = '\\'; 45437c478bd9Sstevel@tonic-gate *p++ = 'n'; 45447c478bd9Sstevel@tonic-gate *cl += 2; 45457c478bd9Sstevel@tonic-gate *buf = p; 45467c478bd9Sstevel@tonic-gate return (2); 45477c478bd9Sstevel@tonic-gate } else { 45487c478bd9Sstevel@tonic-gate return (0); 45497c478bd9Sstevel@tonic-gate } 45507c478bd9Sstevel@tonic-gate } else if (c < 0200) { 45517c478bd9Sstevel@tonic-gate /* ascii control character */ 45527c478bd9Sstevel@tonic-gate if (*cl + 2 < max) { 45537c478bd9Sstevel@tonic-gate *p++ = '^'; 45547c478bd9Sstevel@tonic-gate *p++ = c ^ 0100; 45557c478bd9Sstevel@tonic-gate *cl += 2; 45567c478bd9Sstevel@tonic-gate *buf = p; 45577c478bd9Sstevel@tonic-gate return (2); 45587c478bd9Sstevel@tonic-gate } else { 45597c478bd9Sstevel@tonic-gate return (0); 45607c478bd9Sstevel@tonic-gate } 45617c478bd9Sstevel@tonic-gate } else { 45627c478bd9Sstevel@tonic-gate if (*cl + 4 < max) { 45637c478bd9Sstevel@tonic-gate *p++ = '\\'; 45647c478bd9Sstevel@tonic-gate *p++ = ((c >> 6) & 07) + '0'; 45657c478bd9Sstevel@tonic-gate *p++ = ((c >> 3) & 07) + '0'; 45667c478bd9Sstevel@tonic-gate *p++ = (c & 07) + '0'; 45677c478bd9Sstevel@tonic-gate *cl += 4; 45687c478bd9Sstevel@tonic-gate *buf = p; 45697c478bd9Sstevel@tonic-gate return (4); 45707c478bd9Sstevel@tonic-gate } else { 45717c478bd9Sstevel@tonic-gate return (0); 45727c478bd9Sstevel@tonic-gate } 45737c478bd9Sstevel@tonic-gate } 45747c478bd9Sstevel@tonic-gate } 45757c478bd9Sstevel@tonic-gate 45767c478bd9Sstevel@tonic-gate /* 45777c478bd9Sstevel@tonic-gate * findnl_bkwd: 45787c478bd9Sstevel@tonic-gate * Scans each character in buf until it finds the last newline in buf, 45797c478bd9Sstevel@tonic-gate * or the scanned character becomes the last COMPLETE character in buf. 45807c478bd9Sstevel@tonic-gate * Returns the number of scanned bytes. 45817c478bd9Sstevel@tonic-gate * 45827c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 45837c478bd9Sstevel@tonic-gate * len - the length of the buffer 45847c478bd9Sstevel@tonic-gate */ 45857c478bd9Sstevel@tonic-gate size_t 45867c478bd9Sstevel@tonic-gate findnl_bkwd(const char *buf, const size_t len) 45877c478bd9Sstevel@tonic-gate { 45887c478bd9Sstevel@tonic-gate const char *p; 45897c478bd9Sstevel@tonic-gate size_t mb_cur_max; 45907c478bd9Sstevel@tonic-gate pthread_t mythreadno; 45917c478bd9Sstevel@tonic-gate 45927c478bd9Sstevel@tonic-gate if (Debug) { 45937c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 45947c478bd9Sstevel@tonic-gate } 45957c478bd9Sstevel@tonic-gate 45967c478bd9Sstevel@tonic-gate if (len == 0) { 45977c478bd9Sstevel@tonic-gate return (0); 45987c478bd9Sstevel@tonic-gate } 45997c478bd9Sstevel@tonic-gate 46007c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 46017c478bd9Sstevel@tonic-gate 46027c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 46037c478bd9Sstevel@tonic-gate /* single-byte locale */ 46047c478bd9Sstevel@tonic-gate for (p = buf + len - 1; p != buf; p--) { 46057c478bd9Sstevel@tonic-gate if (*p == '\n') { 46067c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 46077c478bd9Sstevel@tonic-gate } 46087c478bd9Sstevel@tonic-gate } 46097c478bd9Sstevel@tonic-gate return ((size_t)len); 46107c478bd9Sstevel@tonic-gate } else { 46117c478bd9Sstevel@tonic-gate /* multi-byte locale */ 46127c478bd9Sstevel@tonic-gate int mlen; 46137c478bd9Sstevel@tonic-gate const char *nl; 46147c478bd9Sstevel@tonic-gate size_t rem; 46157c478bd9Sstevel@tonic-gate 46167c478bd9Sstevel@tonic-gate p = buf; 46177c478bd9Sstevel@tonic-gate nl = NULL; 46187c478bd9Sstevel@tonic-gate for (rem = len; rem >= mb_cur_max; ) { 46197c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 46207c478bd9Sstevel@tonic-gate if (mlen == -1) { 46217c478bd9Sstevel@tonic-gate /* 46227c478bd9Sstevel@tonic-gate * Invalid character found. 46237c478bd9Sstevel@tonic-gate */ 46247c478bd9Sstevel@tonic-gate DPRINT1(9, "findnl_bkwd(%u): Invalid MB " 46257c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 46267c478bd9Sstevel@tonic-gate /* 46277c478bd9Sstevel@tonic-gate * handle as a single byte character. 46287c478bd9Sstevel@tonic-gate */ 46297c478bd9Sstevel@tonic-gate p++; 46307c478bd9Sstevel@tonic-gate rem--; 46317c478bd9Sstevel@tonic-gate } else { 46327c478bd9Sstevel@tonic-gate /* 46337c478bd9Sstevel@tonic-gate * It's guaranteed that *p points to 46347c478bd9Sstevel@tonic-gate * the 1st byte of a multibyte character. 46357c478bd9Sstevel@tonic-gate */ 46367c478bd9Sstevel@tonic-gate if (*p == '\n') { 46377c478bd9Sstevel@tonic-gate nl = p; 46387c478bd9Sstevel@tonic-gate } 46397c478bd9Sstevel@tonic-gate p += mlen; 46407c478bd9Sstevel@tonic-gate rem -= mlen; 46417c478bd9Sstevel@tonic-gate } 46427c478bd9Sstevel@tonic-gate } 46437c478bd9Sstevel@tonic-gate if (nl) { 46447c478bd9Sstevel@tonic-gate return ((size_t)(nl - buf)); 46457c478bd9Sstevel@tonic-gate } 46467c478bd9Sstevel@tonic-gate /* 46477c478bd9Sstevel@tonic-gate * no newline nor null byte found. 46487c478bd9Sstevel@tonic-gate * Also it's guaranteed that *p points to 46497c478bd9Sstevel@tonic-gate * the 1st byte of a (multibyte) character 46507c478bd9Sstevel@tonic-gate * at this point. 46517c478bd9Sstevel@tonic-gate */ 46527c478bd9Sstevel@tonic-gate return (len - rem); 46537c478bd9Sstevel@tonic-gate } 46547c478bd9Sstevel@tonic-gate } 46557c478bd9Sstevel@tonic-gate 46567c478bd9Sstevel@tonic-gate /* 46577c478bd9Sstevel@tonic-gate * copynl_frwd: 46587c478bd9Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf 46597c478bd9Sstevel@tonic-gate * until it finds a null byte or a newline, or 46607c478bd9Sstevel@tonic-gate * the number of the remaining bytes in obuf gets to exceed obuflen 46617c478bd9Sstevel@tonic-gate * if copying the scanned character to obuf. 46627c478bd9Sstevel@tonic-gate * Returns the number of scanned bytes. 46637c478bd9Sstevel@tonic-gate * 46647c478bd9Sstevel@tonic-gate * obuf - buffer to be copied the scanned character 46657c478bd9Sstevel@tonic-gate * obuflen - the size of obuf 46667c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 46677c478bd9Sstevel@tonic-gate * len - the length of the buffer 46687c478bd9Sstevel@tonic-gate */ 46697c478bd9Sstevel@tonic-gate size_t 46707c478bd9Sstevel@tonic-gate copynl_frwd(char *obuf, const size_t obuflen, 46717c478bd9Sstevel@tonic-gate const char *buf, const size_t len) 46727c478bd9Sstevel@tonic-gate { 46737c478bd9Sstevel@tonic-gate const char *p; 46747c478bd9Sstevel@tonic-gate char *q = obuf; 46757c478bd9Sstevel@tonic-gate size_t olen = 0; 46767c478bd9Sstevel@tonic-gate size_t mb_cur_max; 46777c478bd9Sstevel@tonic-gate pthread_t mythreadno; 46787c478bd9Sstevel@tonic-gate 46797c478bd9Sstevel@tonic-gate if (Debug) { 46807c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 46817c478bd9Sstevel@tonic-gate } 46827c478bd9Sstevel@tonic-gate 46837c478bd9Sstevel@tonic-gate if (len == 0) { 46847c478bd9Sstevel@tonic-gate return (0); 46857c478bd9Sstevel@tonic-gate } 46867c478bd9Sstevel@tonic-gate 46877c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 46887c478bd9Sstevel@tonic-gate 46897c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 46907c478bd9Sstevel@tonic-gate /* single-byte locale */ 46917c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 46927c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 46937c478bd9Sstevel@tonic-gate if (*p != '\n') { 46947c478bd9Sstevel@tonic-gate *q++ = *p++; 46957c478bd9Sstevel@tonic-gate olen++; 46967c478bd9Sstevel@tonic-gate } else { 46977c478bd9Sstevel@tonic-gate *q = '\0'; 46987c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 46997c478bd9Sstevel@tonic-gate } 47007c478bd9Sstevel@tonic-gate } else { 47017c478bd9Sstevel@tonic-gate *q = '\0'; 47027c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47037c478bd9Sstevel@tonic-gate } 47047c478bd9Sstevel@tonic-gate } 47057c478bd9Sstevel@tonic-gate *q = '\0'; 47067c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47077c478bd9Sstevel@tonic-gate } else { 47087c478bd9Sstevel@tonic-gate /* multi-byte locale */ 47097c478bd9Sstevel@tonic-gate int mlen; 47107c478bd9Sstevel@tonic-gate 47117c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 47127c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 47137c478bd9Sstevel@tonic-gate if (mlen == -1) { 47147c478bd9Sstevel@tonic-gate /* 47157c478bd9Sstevel@tonic-gate * Invalid character found. 47167c478bd9Sstevel@tonic-gate */ 47177c478bd9Sstevel@tonic-gate DPRINT1(9, "copynl_frwd(%u): Invalid MB " 47187c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 47197c478bd9Sstevel@tonic-gate /* 47207c478bd9Sstevel@tonic-gate * handle as a single byte character. 47217c478bd9Sstevel@tonic-gate */ 47227c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 47237c478bd9Sstevel@tonic-gate *q++ = *p++; 47247c478bd9Sstevel@tonic-gate olen++; 47257c478bd9Sstevel@tonic-gate } else { 47267c478bd9Sstevel@tonic-gate *q = '\0'; 47277c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47287c478bd9Sstevel@tonic-gate } 47297c478bd9Sstevel@tonic-gate } else { 47307c478bd9Sstevel@tonic-gate /* 47317c478bd9Sstevel@tonic-gate * It's guaranteed that *p points to 47327c478bd9Sstevel@tonic-gate * the 1st byte of a multibyte character. 47337c478bd9Sstevel@tonic-gate */ 47347c478bd9Sstevel@tonic-gate if (*p == '\n') { 47357c478bd9Sstevel@tonic-gate *q = '\0'; 47367c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47377c478bd9Sstevel@tonic-gate } 47387c478bd9Sstevel@tonic-gate if (obuflen > olen + mlen) { 47397c478bd9Sstevel@tonic-gate int n; 47407c478bd9Sstevel@tonic-gate for (n = 0; n < mlen; n++) { 47417c478bd9Sstevel@tonic-gate *q++ = *p++; 47427c478bd9Sstevel@tonic-gate } 47437c478bd9Sstevel@tonic-gate olen += mlen; 47447c478bd9Sstevel@tonic-gate } else { 47457c478bd9Sstevel@tonic-gate *q = '\0'; 47467c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47477c478bd9Sstevel@tonic-gate } 47487c478bd9Sstevel@tonic-gate } 47497c478bd9Sstevel@tonic-gate } 47507c478bd9Sstevel@tonic-gate /* 47517c478bd9Sstevel@tonic-gate * no newline nor null byte found. 47527c478bd9Sstevel@tonic-gate * Also it's guaranteed that *p points to 47537c478bd9Sstevel@tonic-gate * the 1st byte of a (multibyte) character 47547c478bd9Sstevel@tonic-gate * at this point. 47557c478bd9Sstevel@tonic-gate */ 47567c478bd9Sstevel@tonic-gate *q = '\0'; 47577c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 47587c478bd9Sstevel@tonic-gate } 47597c478bd9Sstevel@tonic-gate } 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate /* 47627c478bd9Sstevel@tonic-gate * copy_frwd: 47637c478bd9Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf 47647c478bd9Sstevel@tonic-gate * until the number of the remaining bytes in obuf gets to exceed obuflen 47657c478bd9Sstevel@tonic-gate * if copying the scanned character to obuf. 47667c478bd9Sstevel@tonic-gate * Returns the number of scanned (copied) bytes. 47677c478bd9Sstevel@tonic-gate * 47687c478bd9Sstevel@tonic-gate * obuf - buffer to be copied the scanned character 47697c478bd9Sstevel@tonic-gate * obuflen - the size of obuf 47707c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 47717c478bd9Sstevel@tonic-gate * len - the length of the buffer 47727c478bd9Sstevel@tonic-gate */ 47737c478bd9Sstevel@tonic-gate size_t 47747c478bd9Sstevel@tonic-gate copy_frwd(char *obuf, const size_t obuflen, 47757c478bd9Sstevel@tonic-gate const char *buf, const size_t len) 47767c478bd9Sstevel@tonic-gate { 47777c478bd9Sstevel@tonic-gate const char *p; 47787c478bd9Sstevel@tonic-gate char *q = obuf; 47797c478bd9Sstevel@tonic-gate size_t olen = 0; 47807c478bd9Sstevel@tonic-gate size_t mb_cur_max; 47817c478bd9Sstevel@tonic-gate pthread_t mythreadno; 47827c478bd9Sstevel@tonic-gate 47837c478bd9Sstevel@tonic-gate if (Debug) { 47847c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 47857c478bd9Sstevel@tonic-gate } 47867c478bd9Sstevel@tonic-gate 47877c478bd9Sstevel@tonic-gate if (len == 0) { 47887c478bd9Sstevel@tonic-gate return (0); 47897c478bd9Sstevel@tonic-gate } 47907c478bd9Sstevel@tonic-gate 47917c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 47927c478bd9Sstevel@tonic-gate 47937c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 47947c478bd9Sstevel@tonic-gate /* single-byte locale */ 47957c478bd9Sstevel@tonic-gate if (obuflen > len) { 47967c478bd9Sstevel@tonic-gate (void) memcpy(obuf, buf, len); 47977c478bd9Sstevel@tonic-gate obuf[len] = '\0'; 47987c478bd9Sstevel@tonic-gate return ((size_t)len); 47997c478bd9Sstevel@tonic-gate } else { 48007c478bd9Sstevel@tonic-gate (void) memcpy(obuf, buf, obuflen - 1); 48017c478bd9Sstevel@tonic-gate obuf[obuflen - 1] = '\0'; 48027c478bd9Sstevel@tonic-gate return (obuflen - 1); 48037c478bd9Sstevel@tonic-gate } 48047c478bd9Sstevel@tonic-gate } else { 48057c478bd9Sstevel@tonic-gate /* multi-byte locale */ 48067c478bd9Sstevel@tonic-gate int mlen; 48077c478bd9Sstevel@tonic-gate 48087c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 48097c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 48107c478bd9Sstevel@tonic-gate if (mlen == -1) { 48117c478bd9Sstevel@tonic-gate /* 48127c478bd9Sstevel@tonic-gate * Invalid character found. 48137c478bd9Sstevel@tonic-gate */ 48147c478bd9Sstevel@tonic-gate DPRINT1(9, "copy_frwd(%u): Invalid MB " 48157c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 48167c478bd9Sstevel@tonic-gate /* 48177c478bd9Sstevel@tonic-gate * handle as a single byte character. 48187c478bd9Sstevel@tonic-gate */ 48197c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 48207c478bd9Sstevel@tonic-gate *q++ = *p++; 48217c478bd9Sstevel@tonic-gate olen++; 48227c478bd9Sstevel@tonic-gate } else { 48237c478bd9Sstevel@tonic-gate *q = '\0'; 48247c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 48257c478bd9Sstevel@tonic-gate } 48267c478bd9Sstevel@tonic-gate } else { 48277c478bd9Sstevel@tonic-gate if (obuflen > olen + mlen) { 48287c478bd9Sstevel@tonic-gate int n; 48297c478bd9Sstevel@tonic-gate for (n = 0; n < mlen; n++) { 48307c478bd9Sstevel@tonic-gate *q++ = *p++; 48317c478bd9Sstevel@tonic-gate } 48327c478bd9Sstevel@tonic-gate olen += mlen; 48337c478bd9Sstevel@tonic-gate } else { 48347c478bd9Sstevel@tonic-gate *q = '\0'; 48357c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 48367c478bd9Sstevel@tonic-gate } 48377c478bd9Sstevel@tonic-gate } 48387c478bd9Sstevel@tonic-gate } 48397c478bd9Sstevel@tonic-gate *q = '\0'; 48407c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 48417c478bd9Sstevel@tonic-gate } 48427c478bd9Sstevel@tonic-gate } 48437c478bd9Sstevel@tonic-gate 48447c478bd9Sstevel@tonic-gate /* 48450ea5e3a5Sjjj * properties: 48460ea5e3a5Sjjj * Get properties from SMF framework. 48477c478bd9Sstevel@tonic-gate */ 48487c478bd9Sstevel@tonic-gate static void 48490ea5e3a5Sjjj properties(void) 48507c478bd9Sstevel@tonic-gate { 48510ea5e3a5Sjjj scf_simple_prop_t *prop; 48520ea5e3a5Sjjj uint8_t *bool; 48537c478bd9Sstevel@tonic-gate 48540ea5e3a5Sjjj if ((prop = scf_simple_prop_get(NULL, NULL, "config", 48550ea5e3a5Sjjj "log_from_remote")) != NULL) { 48560ea5e3a5Sjjj if ((bool = scf_simple_prop_next_boolean(prop)) != NULL) { 48570ea5e3a5Sjjj if (*bool == 0) 48580ea5e3a5Sjjj turnoff = 1; /* log_from_remote = false */ 48590ea5e3a5Sjjj else 48600ea5e3a5Sjjj turnoff = 0; /* log_from_remote = true */ 48617c478bd9Sstevel@tonic-gate } 48620ea5e3a5Sjjj scf_simple_prop_free(prop); 48630ea5e3a5Sjjj DPRINT1(1, "properties: setting turnoff to %s\n", 48640ea5e3a5Sjjj turnoff ? "true" : "false"); 48657c478bd9Sstevel@tonic-gate } 48667c478bd9Sstevel@tonic-gate } 48677c478bd9Sstevel@tonic-gate 48687c478bd9Sstevel@tonic-gate /* 48697c478bd9Sstevel@tonic-gate * close all the input devices. 48707c478bd9Sstevel@tonic-gate */ 48717c478bd9Sstevel@tonic-gate static void 48727c478bd9Sstevel@tonic-gate shutdown_input(void) 48737c478bd9Sstevel@tonic-gate { 48747c478bd9Sstevel@tonic-gate int cnt; 48757c478bd9Sstevel@tonic-gate 48767c478bd9Sstevel@tonic-gate shutting_down = 1; 48777c478bd9Sstevel@tonic-gate 48787c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < Ninputs; cnt++) { 48797c478bd9Sstevel@tonic-gate (void) t_close(Nfd[cnt].fd); 48807c478bd9Sstevel@tonic-gate } 48817c478bd9Sstevel@tonic-gate 48827c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 48837c478bd9Sstevel@tonic-gate } 48847c478bd9Sstevel@tonic-gate 48857c478bd9Sstevel@tonic-gate /* 48867c478bd9Sstevel@tonic-gate * This is for the one thread that dedicates to resolve the 48877c478bd9Sstevel@tonic-gate * hostname. This will get the messages from net_poll() through 48887c478bd9Sstevel@tonic-gate * hnlq, and resolve the hostname, and push the messages back 48897c478bd9Sstevel@tonic-gate * into the inputq. 48907c478bd9Sstevel@tonic-gate */ 48917c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 48927c478bd9Sstevel@tonic-gate static void * 48937c478bd9Sstevel@tonic-gate hostname_lookup(void *ap) 48947c478bd9Sstevel@tonic-gate { 48957c478bd9Sstevel@tonic-gate char *uap; 48967c478bd9Sstevel@tonic-gate log_message_t *mp; 48977c478bd9Sstevel@tonic-gate host_info_t *hip; 48987c478bd9Sstevel@tonic-gate char failsafe_addr[SYS_NMLN + 1]; 48997c478bd9Sstevel@tonic-gate pthread_t mythreadno; 49007c478bd9Sstevel@tonic-gate 49017c478bd9Sstevel@tonic-gate if (Debug) { 49027c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 49037c478bd9Sstevel@tonic-gate } 49047c478bd9Sstevel@tonic-gate 49057c478bd9Sstevel@tonic-gate DPRINT1(1, "hostname_lookup(%u): hostname_lookup started\n", 49067c478bd9Sstevel@tonic-gate mythreadno); 49077c478bd9Sstevel@tonic-gate 49087c478bd9Sstevel@tonic-gate for (;;) { 49097c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&hnlq, (void **)&mp, 0); 49107c478bd9Sstevel@tonic-gate 49117c478bd9Sstevel@tonic-gate DPRINT3(5, "hostname_lookup(%u): dequeued msg %p" 49120ea5e3a5Sjjj " from queue %p\n", mythreadno, (void *)mp, 49130ea5e3a5Sjjj (void *)&hnlq); 49147c478bd9Sstevel@tonic-gate 49157c478bd9Sstevel@tonic-gate hip = (host_info_t *)mp->ptr; 49167c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(hip->ncp, &hip->addr)) != NULL) { 49177c478bd9Sstevel@tonic-gate (void) strlcpy(failsafe_addr, uap, SYS_NMLN); 49187c478bd9Sstevel@tonic-gate free(uap); 49197c478bd9Sstevel@tonic-gate } else { 49207c478bd9Sstevel@tonic-gate (void) strlcpy(failsafe_addr, "<unknown>", SYS_NMLN); 49217c478bd9Sstevel@tonic-gate } 49227c478bd9Sstevel@tonic-gate 49237c478bd9Sstevel@tonic-gate mp->hlp = cvthname(&hip->addr, hip->ncp, failsafe_addr); 49247c478bd9Sstevel@tonic-gate 49257c478bd9Sstevel@tonic-gate if (mp->hlp == NULL) { 49267c478bd9Sstevel@tonic-gate mp->hlp = &NullHostName; 49277c478bd9Sstevel@tonic-gate } 49287c478bd9Sstevel@tonic-gate 49297c478bd9Sstevel@tonic-gate free(hip->addr.buf); 49307c478bd9Sstevel@tonic-gate free(hip); 49317c478bd9Sstevel@tonic-gate mp->ptr = NULL; 49327c478bd9Sstevel@tonic-gate 49337c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 49347c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from remote"); 49357c478bd9Sstevel@tonic-gate free_msg(mp); 49367c478bd9Sstevel@tonic-gate continue; 49377c478bd9Sstevel@tonic-gate } 49387c478bd9Sstevel@tonic-gate 49390ea5e3a5Sjjj DPRINT3(5, "hostname_lookup(%u): enqueued msg %p on queue " 49400ea5e3a5Sjjj "%p\n", mythreadno, (void *)mp, (void *)&inputq); 49417c478bd9Sstevel@tonic-gate } 49427c478bd9Sstevel@tonic-gate 49437c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 49447c478bd9Sstevel@tonic-gate return (NULL); 49457c478bd9Sstevel@tonic-gate } 49467c478bd9Sstevel@tonic-gate 49477c478bd9Sstevel@tonic-gate /* 49487c478bd9Sstevel@tonic-gate * Does all HUP(re-configuration) process. 49497c478bd9Sstevel@tonic-gate */ 49507c478bd9Sstevel@tonic-gate static void 49517c478bd9Sstevel@tonic-gate reconfigure() 49527c478bd9Sstevel@tonic-gate { 49537c478bd9Sstevel@tonic-gate int cnt, loop, drops; 49547c478bd9Sstevel@tonic-gate int really_stuck; 49557c478bd9Sstevel@tonic-gate int console_stuck = 0; 49567c478bd9Sstevel@tonic-gate struct filed *f; 49577c478bd9Sstevel@tonic-gate char buf[LINE_MAX]; 49587c478bd9Sstevel@tonic-gate struct utsname up; 49597c478bd9Sstevel@tonic-gate char cbuf[30]; 49607c478bd9Sstevel@tonic-gate time_t tim; 49617c478bd9Sstevel@tonic-gate pthread_t mythreadno; 49627c478bd9Sstevel@tonic-gate 49637c478bd9Sstevel@tonic-gate if (Debug) { 49647c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 49657c478bd9Sstevel@tonic-gate } 49667c478bd9Sstevel@tonic-gate 49677c478bd9Sstevel@tonic-gate /* If we get here then we must need to regen */ 49687c478bd9Sstevel@tonic-gate flushmsg(0); 49697c478bd9Sstevel@tonic-gate 49707c478bd9Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_INFO, "syslogd: configuration restart", 49717c478bd9Sstevel@tonic-gate ADDDATE, 0) == -1) { 49727c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 49737c478bd9Sstevel@tonic-gate } 49747c478bd9Sstevel@tonic-gate 49757c478bd9Sstevel@tonic-gate /* 49767c478bd9Sstevel@tonic-gate * make sure the logmsg thread is not in the waiting state. 49777c478bd9Sstevel@tonic-gate * Otherwise, changing hup_state will prevent the logmsg thread 49787c478bd9Sstevel@tonic-gate * getting out from the waiting loop. 49797c478bd9Sstevel@tonic-gate */ 49807c478bd9Sstevel@tonic-gate 49817c478bd9Sstevel@tonic-gate if (Debug) { 49827c478bd9Sstevel@tonic-gate tim = time(NULL); 49837c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logmsg()" 49847c478bd9Sstevel@tonic-gate " moving to the safe place\n", 49857c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 49867c478bd9Sstevel@tonic-gate } 49877c478bd9Sstevel@tonic-gate 49887c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 49897c478bd9Sstevel@tonic-gate /* we don't need the mutex to read */ 49907c478bd9Sstevel@tonic-gate if (hup_state == HUP_ACCEPTABLE) 49917c478bd9Sstevel@tonic-gate break; 49927c478bd9Sstevel@tonic-gate (void) sleep(1); 49937c478bd9Sstevel@tonic-gate } 49947c478bd9Sstevel@tonic-gate if (hup_state != HUP_ACCEPTABLE) { 49957c478bd9Sstevel@tonic-gate goto thread_stuck; 49967c478bd9Sstevel@tonic-gate } 49977c478bd9Sstevel@tonic-gate 49987c478bd9Sstevel@tonic-gate if (Debug) { 49997c478bd9Sstevel@tonic-gate tim = time(NULL); 50007c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() will accept HUP\n", 50017c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 50027c478bd9Sstevel@tonic-gate } 50037c478bd9Sstevel@tonic-gate 50047c478bd9Sstevel@tonic-gate /* 50057c478bd9Sstevel@tonic-gate * Prevent logging until we are truly done processing the HUP 50067c478bd9Sstevel@tonic-gate */ 50077c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 50087c478bd9Sstevel@tonic-gate hup_state = HUP_INPROGRESS; 50097c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 50107c478bd9Sstevel@tonic-gate 50117c478bd9Sstevel@tonic-gate /* 50127c478bd9Sstevel@tonic-gate * We will be going into a critical state. Any error message 50137c478bd9Sstevel@tonic-gate * from syslogd needs to be dumped to the console by default 50147c478bd9Sstevel@tonic-gate * immediately. Also, those error messages are quened in a temporary 50157c478bd9Sstevel@tonic-gate * queue to be able to post into the regular stream later. 50167c478bd9Sstevel@tonic-gate */ 50177c478bd9Sstevel@tonic-gate disable_errorlog(); 50187c478bd9Sstevel@tonic-gate 50197c478bd9Sstevel@tonic-gate if (Debug) { 50207c478bd9Sstevel@tonic-gate tim = time(NULL); 50217c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: sending SHUTDOWN\n", 50227c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 50237c478bd9Sstevel@tonic-gate } 50247c478bd9Sstevel@tonic-gate 50257c478bd9Sstevel@tonic-gate /* stop configured threads */ 50267c478bd9Sstevel@tonic-gate if (shutdown_msg() == -1) { 50277c478bd9Sstevel@tonic-gate /* 50287c478bd9Sstevel@tonic-gate * No memory, message will be dumped to the console. 50297c478bd9Sstevel@tonic-gate */ 50307c478bd9Sstevel@tonic-gate MALLOC_FAIL("unable to restart syslogd"); 50317c478bd9Sstevel@tonic-gate goto out; 50327c478bd9Sstevel@tonic-gate } 50337c478bd9Sstevel@tonic-gate 50347c478bd9Sstevel@tonic-gate /* make sure logmsg() is in suspended state */ 50357c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) { 50367c478bd9Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED) 50377c478bd9Sstevel@tonic-gate break; 50387c478bd9Sstevel@tonic-gate (void) sleep(1); 50397c478bd9Sstevel@tonic-gate } 50407c478bd9Sstevel@tonic-gate 50417c478bd9Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) { 50427c478bd9Sstevel@tonic-gate if (Debug) { 50437c478bd9Sstevel@tonic-gate tim = time(NULL); 50447c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() does not " 50457c478bd9Sstevel@tonic-gate "stop. enforcing\n", 50467c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 50477c478bd9Sstevel@tonic-gate } 50487c478bd9Sstevel@tonic-gate 50497c478bd9Sstevel@tonic-gate /* probably we have too long input queue, or really stuck */ 50507c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 50517c478bd9Sstevel@tonic-gate hup_state |= HUP_SUSP_LOGMSG_REQD; 50527c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 50537c478bd9Sstevel@tonic-gate 50547c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 50557c478bd9Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED) 50567c478bd9Sstevel@tonic-gate break; 50577c478bd9Sstevel@tonic-gate (void) sleep(1); 50587c478bd9Sstevel@tonic-gate } 50597c478bd9Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) { 50607c478bd9Sstevel@tonic-gate if (Debug) { 50617c478bd9Sstevel@tonic-gate tim = time(NULL); 50627c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg()" 50637c478bd9Sstevel@tonic-gate " does not stop. give up\n", 50647c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 50657c478bd9Sstevel@tonic-gate } 50667c478bd9Sstevel@tonic-gate logerror("could not suspend logmsg - fatal"); 50677c478bd9Sstevel@tonic-gate goto thread_stuck; 50687c478bd9Sstevel@tonic-gate } 50697c478bd9Sstevel@tonic-gate } 50707c478bd9Sstevel@tonic-gate 50717c478bd9Sstevel@tonic-gate if (Debug) { 50727c478bd9Sstevel@tonic-gate tim = time(NULL); 50737c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() suspended\n", 50747c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 50757c478bd9Sstevel@tonic-gate } 50767c478bd9Sstevel@tonic-gate 50777c478bd9Sstevel@tonic-gate /* 50787c478bd9Sstevel@tonic-gate * Will wait for LOOP_MAX secs with watching queue lengths for the 50797c478bd9Sstevel@tonic-gate * each logger threads. If they have backlogs, and no change in the 50807c478bd9Sstevel@tonic-gate * length of queue found in 30 seconds, those will be counted as 50817c478bd9Sstevel@tonic-gate * "really stuck". 50827c478bd9Sstevel@tonic-gate * If all running logger threads become "really stuck" state, there 50837c478bd9Sstevel@tonic-gate * should be no worth waiting for them to quit. 50847c478bd9Sstevel@tonic-gate * In that case, we will go ahead and close out file descriptors to 50857c478bd9Sstevel@tonic-gate * have them pull out from hanging system call, and give them a last 50867c478bd9Sstevel@tonic-gate * chance(LOOP_INTERVAL sec) to quit. 50877c478bd9Sstevel@tonic-gate */ 50887c478bd9Sstevel@tonic-gate 50897c478bd9Sstevel@tonic-gate if (Debug) { 50907c478bd9Sstevel@tonic-gate tim = time(NULL); 50917c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logit() to be" 50927c478bd9Sstevel@tonic-gate " shutdown\n", mythreadno, ctime_r(&tim, cbuf)+4); 50937c478bd9Sstevel@tonic-gate } 50947c478bd9Sstevel@tonic-gate 50957c478bd9Sstevel@tonic-gate cnt = 0; 50967c478bd9Sstevel@tonic-gate really_stuck = 0; 50977c478bd9Sstevel@tonic-gate while (cnt < (LOOP_MAX/LOOP_INTERVAL) && 50987c478bd9Sstevel@tonic-gate conf_threads > really_stuck) { 50997c478bd9Sstevel@tonic-gate 51007c478bd9Sstevel@tonic-gate /* save initial queue count */ 51017c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 51027c478bd9Sstevel@tonic-gate f->f_prev_queue_count = (f->f_type == F_UNUSED) ? 51037c478bd9Sstevel@tonic-gate -1 : f->f_queue_count; 51047c478bd9Sstevel@tonic-gate } 51057c478bd9Sstevel@tonic-gate 51067c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) { 51077c478bd9Sstevel@tonic-gate if (conf_threads == 0) 51087c478bd9Sstevel@tonic-gate break; 51097c478bd9Sstevel@tonic-gate (void) sleep(1); 51107c478bd9Sstevel@tonic-gate } 51117c478bd9Sstevel@tonic-gate 51127c478bd9Sstevel@tonic-gate if (conf_threads == 0) 51137c478bd9Sstevel@tonic-gate break; 51147c478bd9Sstevel@tonic-gate 51157c478bd9Sstevel@tonic-gate if (Debug) { 51167c478bd9Sstevel@tonic-gate tim = time(NULL); 51177c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: " 51187c478bd9Sstevel@tonic-gate "%d threads are still alive.\n", 51197c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, 51207c478bd9Sstevel@tonic-gate conf_threads); 51217c478bd9Sstevel@tonic-gate } 51227c478bd9Sstevel@tonic-gate 51237c478bd9Sstevel@tonic-gate really_stuck = 0; 51247c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 51257c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) { 51267c478bd9Sstevel@tonic-gate f->f_prev_queue_count = -1; 51277c478bd9Sstevel@tonic-gate continue; 51287c478bd9Sstevel@tonic-gate } 51297c478bd9Sstevel@tonic-gate if (f->f_prev_queue_count == f->f_queue_count) { 51307c478bd9Sstevel@tonic-gate really_stuck++; 51317c478bd9Sstevel@tonic-gate f->f_prev_queue_count = 1; 51327c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): " 51337c478bd9Sstevel@tonic-gate "tid=%d is really stuck.\n", 51347c478bd9Sstevel@tonic-gate mythreadno, f->f_thread); 51357c478bd9Sstevel@tonic-gate } else { 51367c478bd9Sstevel@tonic-gate f->f_prev_queue_count = 0; 51377c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): " 51387c478bd9Sstevel@tonic-gate "tid=%d is still active.\n", 51397c478bd9Sstevel@tonic-gate mythreadno, f->f_thread); 51407c478bd9Sstevel@tonic-gate } 51417c478bd9Sstevel@tonic-gate } 51427c478bd9Sstevel@tonic-gate /* 51437c478bd9Sstevel@tonic-gate * Here we have one of following values in the 51447c478bd9Sstevel@tonic-gate * f_prev_queue_count: 51457c478bd9Sstevel@tonic-gate * 0: logger thread is still actively working. 51467c478bd9Sstevel@tonic-gate * 1: logger thread is really stuck. 51477c478bd9Sstevel@tonic-gate * -1: logger thread has already died. 51487c478bd9Sstevel@tonic-gate */ 51497c478bd9Sstevel@tonic-gate 51507c478bd9Sstevel@tonic-gate cnt++; 51517c478bd9Sstevel@tonic-gate } 51527c478bd9Sstevel@tonic-gate 51537c478bd9Sstevel@tonic-gate if (Debug) { 51547c478bd9Sstevel@tonic-gate tim = time(NULL); 51557c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s:" 51567c478bd9Sstevel@tonic-gate " complete awaiting logit()\n", 51577c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 51587c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %d threads alive." 51597c478bd9Sstevel@tonic-gate " %d threads stuck\n", 51607c478bd9Sstevel@tonic-gate mythreadno, conf_threads, really_stuck); 51617c478bd9Sstevel@tonic-gate } 51627c478bd9Sstevel@tonic-gate 51637c478bd9Sstevel@tonic-gate /* 51647c478bd9Sstevel@tonic-gate * Still running? If so, mark it as UNUSED, and close 51657c478bd9Sstevel@tonic-gate * the fd so that logger threads can bail out from the loop. 51667c478bd9Sstevel@tonic-gate */ 51677c478bd9Sstevel@tonic-gate drops = 0; 51687c478bd9Sstevel@tonic-gate if (conf_threads) { 51697c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 51707c478bd9Sstevel@tonic-gate if (f->f_type == F_CONSOLE && 51717c478bd9Sstevel@tonic-gate f->f_prev_queue_count == 1) { 51727c478bd9Sstevel@tonic-gate /* console is really stuck */ 51737c478bd9Sstevel@tonic-gate console_stuck = 1; 51747c478bd9Sstevel@tonic-gate } 51757c478bd9Sstevel@tonic-gate if (f->f_type == F_USERS || f->f_type == F_WALL || 51767c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) 51777c478bd9Sstevel@tonic-gate continue; 51787c478bd9Sstevel@tonic-gate cnt = f->f_queue_count; 51797c478bd9Sstevel@tonic-gate drops += (cnt > 0) ? cnt - 1: 0; 51807c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 51817c478bd9Sstevel@tonic-gate 51827c478bd9Sstevel@tonic-gate if (f->f_orig_type == F_FORW) 51830ea5e3a5Sjjj (void) t_close(f->f_file); 51847c478bd9Sstevel@tonic-gate else 51850ea5e3a5Sjjj (void) close(f->f_file); 51867c478bd9Sstevel@tonic-gate } 51877c478bd9Sstevel@tonic-gate 51887c478bd9Sstevel@tonic-gate if (Debug) { 51897c478bd9Sstevel@tonic-gate tim = time(NULL); 51907c478bd9Sstevel@tonic-gate DPRINT1(3, "reconfigure(%u): terminating logit()\n", 51917c478bd9Sstevel@tonic-gate mythreadno); 51927c478bd9Sstevel@tonic-gate } 51937c478bd9Sstevel@tonic-gate 51947c478bd9Sstevel@tonic-gate /* last chance to exit */ 51957c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 51967c478bd9Sstevel@tonic-gate if (conf_threads == 0) 51977c478bd9Sstevel@tonic-gate break; 51987c478bd9Sstevel@tonic-gate (void) sleep(1); 51997c478bd9Sstevel@tonic-gate } 52007c478bd9Sstevel@tonic-gate 52017c478bd9Sstevel@tonic-gate if (Debug) { 52027c478bd9Sstevel@tonic-gate tim = time(NULL); 52037c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: %d alive\n", 52047c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, 52057c478bd9Sstevel@tonic-gate conf_threads); 52067c478bd9Sstevel@tonic-gate } 52077c478bd9Sstevel@tonic-gate } 52087c478bd9Sstevel@tonic-gate 52097c478bd9Sstevel@tonic-gate if (conf_threads == 0 && drops) { 52107c478bd9Sstevel@tonic-gate errno = 0; 52117c478bd9Sstevel@tonic-gate logerror("Could not completely output pending messages" 52127c478bd9Sstevel@tonic-gate " while preparing re-configuration"); 52137c478bd9Sstevel@tonic-gate logerror("discarded %d messages and restart configuration.", 52147c478bd9Sstevel@tonic-gate drops); 52157c478bd9Sstevel@tonic-gate if (Debug) { 52167c478bd9Sstevel@tonic-gate tim = time(NULL); 52177c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: " 52187c478bd9Sstevel@tonic-gate "discarded %d messages\n", 52197c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, drops); 52207c478bd9Sstevel@tonic-gate } 52217c478bd9Sstevel@tonic-gate } 52227c478bd9Sstevel@tonic-gate 52237c478bd9Sstevel@tonic-gate /* 52247c478bd9Sstevel@tonic-gate * If all threads still haven't exited 52257c478bd9Sstevel@tonic-gate * something is stuck or hosed. We just 52267c478bd9Sstevel@tonic-gate * have no option but to exit. 52277c478bd9Sstevel@tonic-gate */ 52287c478bd9Sstevel@tonic-gate if (conf_threads) { 52297c478bd9Sstevel@tonic-gate thread_stuck: 52307c478bd9Sstevel@tonic-gate if (Debug) { 52317c478bd9Sstevel@tonic-gate tim = time(NULL); 52327c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: really stuck\n", 52337c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 52347c478bd9Sstevel@tonic-gate } 52357c478bd9Sstevel@tonic-gate 52367c478bd9Sstevel@tonic-gate shutdown_input(); 52377c478bd9Sstevel@tonic-gate delete_doorfiles(); 52380ea5e3a5Sjjj (void) uname(&up); 52397c478bd9Sstevel@tonic-gate 52400ea5e3a5Sjjj (void) snprintf(buf, sizeof (buf), 52417c478bd9Sstevel@tonic-gate "syslogd(%s): some logger thread(s) " 52427c478bd9Sstevel@tonic-gate "are stuck%s; syslogd is shutting down.", 52437c478bd9Sstevel@tonic-gate up.nodename, 52447c478bd9Sstevel@tonic-gate console_stuck ? " (including the console)" : ""); 52457c478bd9Sstevel@tonic-gate 52467c478bd9Sstevel@tonic-gate if (console_stuck) { 52477c478bd9Sstevel@tonic-gate FILE *m = popen(MAILCMD, "w"); 52487c478bd9Sstevel@tonic-gate 52497c478bd9Sstevel@tonic-gate if (m != NULL) { 52500ea5e3a5Sjjj (void) fprintf(m, "%s\n", buf); 52510ea5e3a5Sjjj (void) pclose(m); 52527c478bd9Sstevel@tonic-gate } 52537c478bd9Sstevel@tonic-gate } 52547c478bd9Sstevel@tonic-gate 52557c478bd9Sstevel@tonic-gate disable_errorlog(); 52567c478bd9Sstevel@tonic-gate logerror(buf); 52577c478bd9Sstevel@tonic-gate exit(1); 52587c478bd9Sstevel@tonic-gate } 52597c478bd9Sstevel@tonic-gate 52607c478bd9Sstevel@tonic-gate /* Free up some resources */ 52617c478bd9Sstevel@tonic-gate if (Files != (struct filed *)&fallback) { 52627c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 52637c478bd9Sstevel@tonic-gate (void) pthread_join(f->f_thread, NULL); 52647c478bd9Sstevel@tonic-gate filed_destroy(f); 52657c478bd9Sstevel@tonic-gate } 52667c478bd9Sstevel@tonic-gate free(Files); 52677c478bd9Sstevel@tonic-gate } 52687c478bd9Sstevel@tonic-gate 52697c478bd9Sstevel@tonic-gate dealloc_stacks(nlogs); 52707c478bd9Sstevel@tonic-gate 52717c478bd9Sstevel@tonic-gate if (Debug) { 52727c478bd9Sstevel@tonic-gate tim = time(NULL); 52737c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: cleanup complete\n", 52747c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 52757c478bd9Sstevel@tonic-gate } 52767c478bd9Sstevel@tonic-gate 52777c478bd9Sstevel@tonic-gate hnc_init(1); /* purge hostname cache */ 52787c478bd9Sstevel@tonic-gate conf_init(); /* start reconfigure */ 52797c478bd9Sstevel@tonic-gate 52807c478bd9Sstevel@tonic-gate out:; 52817c478bd9Sstevel@tonic-gate /* Now should be ready to dispatch error messages from syslogd. */ 52827c478bd9Sstevel@tonic-gate enable_errorlog(); 52837c478bd9Sstevel@tonic-gate 52847c478bd9Sstevel@tonic-gate /* Wake up the log thread */ 52857c478bd9Sstevel@tonic-gate 52867c478bd9Sstevel@tonic-gate if (Debug) { 52877c478bd9Sstevel@tonic-gate tim = time(NULL); 52887c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: resuming logmsg()\n", 52897c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 52907c478bd9Sstevel@tonic-gate } 52917c478bd9Sstevel@tonic-gate 52927c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 52937c478bd9Sstevel@tonic-gate hup_state = HUP_COMPLETED; 52947c478bd9Sstevel@tonic-gate (void) pthread_cond_signal(&hup_done); 52957c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 52967c478bd9Sstevel@tonic-gate } 52977c478bd9Sstevel@tonic-gate 52987c478bd9Sstevel@tonic-gate /* 52997c478bd9Sstevel@tonic-gate * The following function implements simple hostname cache mechanism. 5300293d1fc4Spd155743 * Host name cache is implemented through hash table bucket chaining method. 5301293d1fc4Spd155743 * Collisions are handled by bucket chaining. 53027c478bd9Sstevel@tonic-gate * 53037c478bd9Sstevel@tonic-gate * hnc_init(): 53047c478bd9Sstevel@tonic-gate * allocate and initialize the cache. If reinit is set, 53057c478bd9Sstevel@tonic-gate * invalidate all cache entries. 53067c478bd9Sstevel@tonic-gate * hnc_look(): 5307293d1fc4Spd155743 * It hashes the ipaddress gets the index and walks thru the 5308293d1fc4Spd155743 * single linked list. if cached entry was found, it will 53097c478bd9Sstevel@tonic-gate * put in the head of the list, and return.While going through 53107c478bd9Sstevel@tonic-gate * the entries, an entry which has already expired will be invalidated. 53117c478bd9Sstevel@tonic-gate * hnc_register(): 5312293d1fc4Spd155743 * Hashes the ipaddress finds the index and puts current entry to the list. 53137c478bd9Sstevel@tonic-gate * hnc_unreg(): 5314293d1fc4Spd155743 * invalidate the cachep. 53157c478bd9Sstevel@tonic-gate */ 53167c478bd9Sstevel@tonic-gate 53177c478bd9Sstevel@tonic-gate static void 53187c478bd9Sstevel@tonic-gate hnc_init(int reinit) 53197c478bd9Sstevel@tonic-gate { 53207c478bd9Sstevel@tonic-gate struct hostname_cache **hpp; 53217c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5322293d1fc4Spd155743 int i; 53237c478bd9Sstevel@tonic-gate 53247c478bd9Sstevel@tonic-gate if (Debug) { 53257c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 53267c478bd9Sstevel@tonic-gate } 53277c478bd9Sstevel@tonic-gate 53287c478bd9Sstevel@tonic-gate if (reinit) { 53290ea5e3a5Sjjj (void) pthread_mutex_lock(&hnc_mutex); 53307c478bd9Sstevel@tonic-gate 5331293d1fc4Spd155743 for (i = 0; i < hnc_size; i++) { 5332293d1fc4Spd155743 for (hpp = &hnc_cache[i]; *hpp != NULL; ) { 53337c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 53347c478bd9Sstevel@tonic-gate } 5335293d1fc4Spd155743 } 53367c478bd9Sstevel@tonic-gate 53370ea5e3a5Sjjj (void) pthread_mutex_unlock(&hnc_mutex); 53387c478bd9Sstevel@tonic-gate DPRINT1(2, "hnc_init(%u): hostname cache re-configured\n", 53397c478bd9Sstevel@tonic-gate mythreadno); 53407c478bd9Sstevel@tonic-gate } else { 53417c478bd9Sstevel@tonic-gate 5342293d1fc4Spd155743 hnc_cache = calloc(hnc_size, sizeof (struct hostname_cache *)); 53437c478bd9Sstevel@tonic-gate 53447c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 53457c478bd9Sstevel@tonic-gate MALLOC_FAIL("hostname cache"); 53467c478bd9Sstevel@tonic-gate logerror("hostname cache disabled"); 53477c478bd9Sstevel@tonic-gate return; 53487c478bd9Sstevel@tonic-gate } 53497c478bd9Sstevel@tonic-gate 53507c478bd9Sstevel@tonic-gate DPRINT3(1, "hnc_init(%u): hostname cache configured %d entry" 53517c478bd9Sstevel@tonic-gate " ttl:%d\n", mythreadno, hnc_size, hnc_ttl); 53527c478bd9Sstevel@tonic-gate } 53537c478bd9Sstevel@tonic-gate } 53547c478bd9Sstevel@tonic-gate 53557c478bd9Sstevel@tonic-gate static host_list_t * 5356293d1fc4Spd155743 hnc_lookup(struct netbuf *nbp, struct netconfig *ncp, int *hindex) 53577c478bd9Sstevel@tonic-gate { 53587c478bd9Sstevel@tonic-gate struct hostname_cache **hpp, *hp; 53597c478bd9Sstevel@tonic-gate time_t now; 53607c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5361293d1fc4Spd155743 int index; 53627c478bd9Sstevel@tonic-gate 53637c478bd9Sstevel@tonic-gate if (Debug) { 53647c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 53657c478bd9Sstevel@tonic-gate } 53667c478bd9Sstevel@tonic-gate 53677c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 53687c478bd9Sstevel@tonic-gate return (NULL); 53697c478bd9Sstevel@tonic-gate } 53707c478bd9Sstevel@tonic-gate 53710ea5e3a5Sjjj (void) pthread_mutex_lock(&hnc_mutex); 53727c478bd9Sstevel@tonic-gate now = time(0); 53737c478bd9Sstevel@tonic-gate 5374293d1fc4Spd155743 *hindex = index = addr_hash(nbp); 5375293d1fc4Spd155743 5376293d1fc4Spd155743 for (hpp = &hnc_cache[index]; (hp = *hpp) != NULL; ) { 53777c478bd9Sstevel@tonic-gate DPRINT4(10, "hnc_lookup(%u): check %p on %p for %s\n", 53780ea5e3a5Sjjj mythreadno, (void *)hp->h, (void *)hp, 53790ea5e3a5Sjjj hp->h->hl_hosts[0]); 53807c478bd9Sstevel@tonic-gate 53817c478bd9Sstevel@tonic-gate if (hp->expire < now) { 53827c478bd9Sstevel@tonic-gate DPRINT2(9, "hnc_lookup(%u): purge %p\n", 53830ea5e3a5Sjjj mythreadno, (void *)hp); 53847c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 53857c478bd9Sstevel@tonic-gate continue; 53867c478bd9Sstevel@tonic-gate } 53877c478bd9Sstevel@tonic-gate 53887c478bd9Sstevel@tonic-gate if (ncp == hp->ncp && same_addr(&hp->addr, nbp)) { 53897c478bd9Sstevel@tonic-gate /* 53907c478bd9Sstevel@tonic-gate * found! 53917c478bd9Sstevel@tonic-gate * Put the entry at the top. 53927c478bd9Sstevel@tonic-gate */ 53937c478bd9Sstevel@tonic-gate 5394293d1fc4Spd155743 if (hp != hnc_cache[index]) { 53957c478bd9Sstevel@tonic-gate /* unlink from active list */ 53967c478bd9Sstevel@tonic-gate *hpp = (*hpp)->next; 53977c478bd9Sstevel@tonic-gate /* push it onto the top */ 5398293d1fc4Spd155743 hp->next = hnc_cache[index]; 5399293d1fc4Spd155743 hnc_cache[index] = hp; 54007c478bd9Sstevel@tonic-gate } 54017c478bd9Sstevel@tonic-gate 54020ea5e3a5Sjjj (void) pthread_mutex_lock(&hp->h->hl_mutex); 54037c478bd9Sstevel@tonic-gate hp->h->hl_refcnt++; 54040ea5e3a5Sjjj (void) pthread_mutex_unlock(&hp->h->hl_mutex); 54057c478bd9Sstevel@tonic-gate 54067c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_lookup(%u): found %p on %p for %s\n", 54070ea5e3a5Sjjj mythreadno, (void *)hp->h, (void *)hp, 54080ea5e3a5Sjjj hp->h->hl_hosts[0]); 54097c478bd9Sstevel@tonic-gate 54100ea5e3a5Sjjj (void) pthread_mutex_unlock(&hnc_mutex); 54117c478bd9Sstevel@tonic-gate return (hp->h); 54127c478bd9Sstevel@tonic-gate } 54137c478bd9Sstevel@tonic-gate 54147c478bd9Sstevel@tonic-gate hpp = &hp->next; 54157c478bd9Sstevel@tonic-gate } 54167c478bd9Sstevel@tonic-gate 54170ea5e3a5Sjjj (void) pthread_mutex_unlock(&hnc_mutex); 54187c478bd9Sstevel@tonic-gate return (NULL); 54197c478bd9Sstevel@tonic-gate } 54207c478bd9Sstevel@tonic-gate 54217c478bd9Sstevel@tonic-gate static void 5422293d1fc4Spd155743 hnc_register(struct netbuf *nbp, struct netconfig *ncp, 5423293d1fc4Spd155743 host_list_t *h, int hindex) 54247c478bd9Sstevel@tonic-gate { 5425293d1fc4Spd155743 struct hostname_cache **hpp, **tailp, *hp, *entry; 54267c478bd9Sstevel@tonic-gate void *addrbuf; 54277c478bd9Sstevel@tonic-gate time_t now; 54287c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5429293d1fc4Spd155743 int i; 54307c478bd9Sstevel@tonic-gate 54317c478bd9Sstevel@tonic-gate if (Debug) { 54327c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 54337c478bd9Sstevel@tonic-gate } 54347c478bd9Sstevel@tonic-gate 54357c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 54367c478bd9Sstevel@tonic-gate return; 54377c478bd9Sstevel@tonic-gate } 54387c478bd9Sstevel@tonic-gate 54397c478bd9Sstevel@tonic-gate if ((addrbuf = malloc(nbp->len)) == NULL) { 54407c478bd9Sstevel@tonic-gate MALLOC_FAIL("pushing hostname cache"); 54417c478bd9Sstevel@tonic-gate return; 54427c478bd9Sstevel@tonic-gate } 54437c478bd9Sstevel@tonic-gate 5444293d1fc4Spd155743 if ((entry = malloc(sizeof (struct hostname_cache))) == NULL) { 5445293d1fc4Spd155743 MALLOC_FAIL("pushing hostname entry"); 5446293d1fc4Spd155743 free(addrbuf); 5447293d1fc4Spd155743 return; 5448293d1fc4Spd155743 } 5449293d1fc4Spd155743 54500ea5e3a5Sjjj (void) pthread_mutex_lock(&hnc_mutex); 54517c478bd9Sstevel@tonic-gate 5452293d1fc4Spd155743 i = 0; 5453293d1fc4Spd155743 5454293d1fc4Spd155743 now = time(0); 54557c478bd9Sstevel@tonic-gate /* 54567c478bd9Sstevel@tonic-gate * first go through active list, and discard the 5457293d1fc4Spd155743 * caches which has been invalid. Count number of 5458293d1fc4Spd155743 * non-expired buckets. 54597c478bd9Sstevel@tonic-gate */ 5460293d1fc4Spd155743 5461293d1fc4Spd155743 for (hpp = &hnc_cache[hindex]; (hp = *hpp) != NULL; ) { 54627c478bd9Sstevel@tonic-gate tailp = hpp; 54637c478bd9Sstevel@tonic-gate 54647c478bd9Sstevel@tonic-gate if (hp->expire < now) { 54657c478bd9Sstevel@tonic-gate DPRINT2(9, "hnc_register(%u): discard %p\n", 54660ea5e3a5Sjjj mythreadno, (void *)hp); 54677c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 54687c478bd9Sstevel@tonic-gate } else { 5469293d1fc4Spd155743 i++; 54707c478bd9Sstevel@tonic-gate hpp = &hp->next; 54717c478bd9Sstevel@tonic-gate } 54727c478bd9Sstevel@tonic-gate } 54737c478bd9Sstevel@tonic-gate 54747c478bd9Sstevel@tonic-gate /* 5475293d1fc4Spd155743 * If max limit of chained hash buckets has been used up 5476293d1fc4Spd155743 * delete the least active element in the chain. 54777c478bd9Sstevel@tonic-gate */ 5478293d1fc4Spd155743 if (i == MAX_BUCKETS) { 54797c478bd9Sstevel@tonic-gate hnc_unreg(tailp); 54807c478bd9Sstevel@tonic-gate } 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate (void) memcpy(addrbuf, nbp->buf, nbp->len); 5483293d1fc4Spd155743 entry->addr.len = nbp->len; 5484293d1fc4Spd155743 entry->addr.buf = addrbuf; 5485293d1fc4Spd155743 entry->ncp = ncp; 5486293d1fc4Spd155743 entry->h = h; 5487293d1fc4Spd155743 entry->expire = time(NULL) + hnc_ttl; 5488293d1fc4Spd155743 5489293d1fc4Spd155743 /* insert it at the top */ 5490293d1fc4Spd155743 entry->next = hnc_cache[hindex]; 5491293d1fc4Spd155743 hnc_cache[hindex] = entry; 54927c478bd9Sstevel@tonic-gate 54937c478bd9Sstevel@tonic-gate /* 54947c478bd9Sstevel@tonic-gate * As far as cache is valid, corresponding host_list must 54957c478bd9Sstevel@tonic-gate * also be valid. Increments the refcnt to avoid freeing 54967c478bd9Sstevel@tonic-gate * host_list. 54977c478bd9Sstevel@tonic-gate */ 54987c478bd9Sstevel@tonic-gate h->hl_refcnt++; 54997c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_register(%u): reg %p onto %p for %s\n", 55000ea5e3a5Sjjj mythreadno, (void *)h, (void *)hp, hp->h->hl_hosts[0]); 55010ea5e3a5Sjjj (void) pthread_mutex_unlock(&hnc_mutex); 55027c478bd9Sstevel@tonic-gate } 55037c478bd9Sstevel@tonic-gate 55047c478bd9Sstevel@tonic-gate static void 55057c478bd9Sstevel@tonic-gate hnc_unreg(struct hostname_cache **hpp) 55067c478bd9Sstevel@tonic-gate { 55077c478bd9Sstevel@tonic-gate struct hostname_cache *hp = *hpp; 55087c478bd9Sstevel@tonic-gate pthread_t mythreadno; 55097c478bd9Sstevel@tonic-gate 55107c478bd9Sstevel@tonic-gate if (Debug) { 55117c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 55127c478bd9Sstevel@tonic-gate } 55137c478bd9Sstevel@tonic-gate 55147c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_unreg(%u): unreg %p on %p for %s\n", 55150ea5e3a5Sjjj mythreadno, (void *)hp->h, (void *)hp, hp->h->hl_hosts[0]); 55167c478bd9Sstevel@tonic-gate free(hp->addr.buf); 55177c478bd9Sstevel@tonic-gate freehl(hp->h); 55187c478bd9Sstevel@tonic-gate 55197c478bd9Sstevel@tonic-gate /* unlink from active list */ 55207c478bd9Sstevel@tonic-gate *hpp = (*hpp)->next; 55217c478bd9Sstevel@tonic-gate 5522293d1fc4Spd155743 free(hp); 55237c478bd9Sstevel@tonic-gate } 55247c478bd9Sstevel@tonic-gate 55257c478bd9Sstevel@tonic-gate /* 55267c478bd9Sstevel@tonic-gate * Once this is called, error messages through logerror() will go to 55277c478bd9Sstevel@tonic-gate * the console immediately. Also, messages are queued into the tmpq 55287c478bd9Sstevel@tonic-gate * to be able to later put them into inputq. 55297c478bd9Sstevel@tonic-gate */ 55307c478bd9Sstevel@tonic-gate static void 55317c478bd9Sstevel@tonic-gate disable_errorlog() 55327c478bd9Sstevel@tonic-gate { 55330ea5e3a5Sjjj (void) dataq_init(&tmpq); 55347c478bd9Sstevel@tonic-gate 55350ea5e3a5Sjjj (void) pthread_mutex_lock(&logerror_lock); 55367c478bd9Sstevel@tonic-gate interrorlog = 0; 55370ea5e3a5Sjjj (void) pthread_mutex_unlock(&logerror_lock); 55387c478bd9Sstevel@tonic-gate } 55397c478bd9Sstevel@tonic-gate 55407c478bd9Sstevel@tonic-gate /* 55417c478bd9Sstevel@tonic-gate * Turn internal error messages to regular input stream. 55427c478bd9Sstevel@tonic-gate * All pending messages are pulled and pushed into the regular 55437c478bd9Sstevel@tonic-gate * input queue. 55447c478bd9Sstevel@tonic-gate */ 55457c478bd9Sstevel@tonic-gate static void 55467c478bd9Sstevel@tonic-gate enable_errorlog() 55477c478bd9Sstevel@tonic-gate { 55487c478bd9Sstevel@tonic-gate log_message_t *mp; 55497c478bd9Sstevel@tonic-gate 55500ea5e3a5Sjjj (void) pthread_mutex_lock(&logerror_lock); 55517c478bd9Sstevel@tonic-gate interrorlog = 1; 55520ea5e3a5Sjjj (void) pthread_mutex_unlock(&logerror_lock); 55537c478bd9Sstevel@tonic-gate 55547c478bd9Sstevel@tonic-gate /* 55557c478bd9Sstevel@tonic-gate * push all the pending messages into inputq. 55567c478bd9Sstevel@tonic-gate */ 55577c478bd9Sstevel@tonic-gate while (dataq_dequeue(&tmpq, (void **)&mp, 1) == 0) { 55587c478bd9Sstevel@tonic-gate (void) dataq_enqueue(&inputq, mp); 55597c478bd9Sstevel@tonic-gate } 55600ea5e3a5Sjjj (void) dataq_destroy(&tmpq); 55617c478bd9Sstevel@tonic-gate } 5562293d1fc4Spd155743 5563293d1fc4Spd155743 /* 5564293d1fc4Spd155743 * Generate a hash value of the given address and derive 5565293d1fc4Spd155743 * an index into the hnc_cache hashtable. 5566293d1fc4Spd155743 * The hashing method is similar to what Java does for strings. 5567293d1fc4Spd155743 */ 5568293d1fc4Spd155743 static int 5569293d1fc4Spd155743 addr_hash(struct netbuf *nbp) 5570293d1fc4Spd155743 { 5571293d1fc4Spd155743 char *uap; 5572293d1fc4Spd155743 int i; 5573293d1fc4Spd155743 unsigned long hcode = 0; 5574293d1fc4Spd155743 5575293d1fc4Spd155743 uap = nbp->buf; 5576293d1fc4Spd155743 5577293d1fc4Spd155743 if (uap == NULL) { 5578293d1fc4Spd155743 return (0); 5579293d1fc4Spd155743 } 5580293d1fc4Spd155743 5581293d1fc4Spd155743 /* 5582293d1fc4Spd155743 * Compute a hashcode of the address string 5583293d1fc4Spd155743 */ 5584293d1fc4Spd155743 for (i = 0; i < nbp->len; i++) 5585293d1fc4Spd155743 hcode = (31 * hcode) + uap[i]; 5586293d1fc4Spd155743 5587293d1fc4Spd155743 /* 5588293d1fc4Spd155743 * Scramble the hashcode for better distribution 5589293d1fc4Spd155743 */ 5590293d1fc4Spd155743 hcode += ~(hcode << 9); 5591293d1fc4Spd155743 hcode ^= (hcode >> 14); 5592293d1fc4Spd155743 hcode += (hcode << 4); 5593293d1fc4Spd155743 hcode ^= (hcode >> 10); 5594293d1fc4Spd155743 5595293d1fc4Spd155743 return ((int)(hcode % hnc_size)); 5596293d1fc4Spd155743 } 5597