1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 29*7c478bd9Sstevel@tonic-gate * All Rights Reserved 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 34*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 35*7c478bd9Sstevel@tonic-gate * All Rights Reserved 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 38*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 39*7c478bd9Sstevel@tonic-gate * contributors. 40*7c478bd9Sstevel@tonic-gate */ 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* 45*7c478bd9Sstevel@tonic-gate * syslogd -- log system messages 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * This program implements a system log. It takes a series of lines. 48*7c478bd9Sstevel@tonic-gate * Each line may have a priority, signified as "<n>" as 49*7c478bd9Sstevel@tonic-gate * the first characters of the line. If this is 50*7c478bd9Sstevel@tonic-gate * not present, a default priority is used. 51*7c478bd9Sstevel@tonic-gate * 52*7c478bd9Sstevel@tonic-gate * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will 53*7c478bd9Sstevel@tonic-gate * cause it to reconfigure. 54*7c478bd9Sstevel@tonic-gate * 55*7c478bd9Sstevel@tonic-gate * Defined Constants: 56*7c478bd9Sstevel@tonic-gate * 57*7c478bd9Sstevel@tonic-gate * MAXLINE -- the maximimum line length that can be handled. 58*7c478bd9Sstevel@tonic-gate * DEFUPRI -- the default priority for user messages. 59*7c478bd9Sstevel@tonic-gate * DEFSPRI -- the default priority for kernel messages. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #include <unistd.h> 64*7c478bd9Sstevel@tonic-gate #include <note.h> 65*7c478bd9Sstevel@tonic-gate #include <errno.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 67*7c478bd9Sstevel@tonic-gate #include <stdio.h> 68*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 69*7c478bd9Sstevel@tonic-gate #include <ctype.h> 70*7c478bd9Sstevel@tonic-gate #include <signal.h> 71*7c478bd9Sstevel@tonic-gate #include <string.h> 72*7c478bd9Sstevel@tonic-gate #include <strings.h> 73*7c478bd9Sstevel@tonic-gate #include <deflt.h> 74*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 75*7c478bd9Sstevel@tonic-gate #include <netdir.h> 76*7c478bd9Sstevel@tonic-gate #include <pwd.h> 77*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 78*7c478bd9Sstevel@tonic-gate #include <tiuser.h> 79*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 80*7c478bd9Sstevel@tonic-gate #include <limits.h> 81*7c478bd9Sstevel@tonic-gate #include <pthread.h> 82*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 83*7c478bd9Sstevel@tonic-gate #include <stropts.h> 84*7c478bd9Sstevel@tonic-gate #include <assert.h> 85*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 88*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 89*7c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 90*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 91*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 92*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 93*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 94*7c478bd9Sstevel@tonic-gate #include <sys/poll.h> 95*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 96*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 97*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 98*7c478bd9Sstevel@tonic-gate #include <sys/note.h> 99*7c478bd9Sstevel@tonic-gate #include <door.h> 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate #include <wchar.h> 102*7c478bd9Sstevel@tonic-gate #include <locale.h> 103*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate #include "dataq.h" 106*7c478bd9Sstevel@tonic-gate #include "conf.h" 107*7c478bd9Sstevel@tonic-gate #include "syslogd.h" 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #define DOORFILE "/var/run/syslog_door" 110*7c478bd9Sstevel@tonic-gate #define RELATIVE_DOORFILE "../var/run/syslog_door" 111*7c478bd9Sstevel@tonic-gate #define OLD_DOORFILE "/etc/.syslog_door" 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate #define PIDFILE "/var/run/syslog.pid" 114*7c478bd9Sstevel@tonic-gate #define RELATIVE_PIDFILE "../var/run/syslog.pid" 115*7c478bd9Sstevel@tonic-gate #define OLD_PIDFILE "/etc/syslog.pid" 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static char *Version = "%I%"; 118*7c478bd9Sstevel@tonic-gate static char *LogName = "/dev/log"; 119*7c478bd9Sstevel@tonic-gate static char *ConfFile = "/etc/syslog.conf"; 120*7c478bd9Sstevel@tonic-gate static char *DflFile = "/etc/default/syslogd"; 121*7c478bd9Sstevel@tonic-gate static char ctty[] = "/dev/console"; 122*7c478bd9Sstevel@tonic-gate static char sysmsg[] = "/dev/sysmsg"; 123*7c478bd9Sstevel@tonic-gate static int DoorFd = -1; 124*7c478bd9Sstevel@tonic-gate static int DoorCreated = 0; 125*7c478bd9Sstevel@tonic-gate static int PidfileCreated = 0; 126*7c478bd9Sstevel@tonic-gate static char *DoorFileName = DOORFILE; 127*7c478bd9Sstevel@tonic-gate static char *PidFileName = PIDFILE; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* 130*7c478bd9Sstevel@tonic-gate * configuration file directives 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate static struct code PriNames[] = { 134*7c478bd9Sstevel@tonic-gate "panic", LOG_EMERG, 135*7c478bd9Sstevel@tonic-gate "emerg", LOG_EMERG, 136*7c478bd9Sstevel@tonic-gate "alert", LOG_ALERT, 137*7c478bd9Sstevel@tonic-gate "crit", LOG_CRIT, 138*7c478bd9Sstevel@tonic-gate "err", LOG_ERR, 139*7c478bd9Sstevel@tonic-gate "error", LOG_ERR, 140*7c478bd9Sstevel@tonic-gate "warn", LOG_WARNING, 141*7c478bd9Sstevel@tonic-gate "warning", LOG_WARNING, 142*7c478bd9Sstevel@tonic-gate "notice", LOG_NOTICE, 143*7c478bd9Sstevel@tonic-gate "info", LOG_INFO, 144*7c478bd9Sstevel@tonic-gate "debug", LOG_DEBUG, 145*7c478bd9Sstevel@tonic-gate "none", NOPRI, 146*7c478bd9Sstevel@tonic-gate NULL, -1 147*7c478bd9Sstevel@tonic-gate }; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static struct code FacNames[] = { 150*7c478bd9Sstevel@tonic-gate "kern", LOG_KERN, 151*7c478bd9Sstevel@tonic-gate "user", LOG_USER, 152*7c478bd9Sstevel@tonic-gate "mail", LOG_MAIL, 153*7c478bd9Sstevel@tonic-gate "daemon", LOG_DAEMON, 154*7c478bd9Sstevel@tonic-gate "auth", LOG_AUTH, 155*7c478bd9Sstevel@tonic-gate "security", LOG_AUTH, 156*7c478bd9Sstevel@tonic-gate "mark", LOG_MARK, 157*7c478bd9Sstevel@tonic-gate "syslog", LOG_SYSLOG, 158*7c478bd9Sstevel@tonic-gate "lpr", LOG_LPR, 159*7c478bd9Sstevel@tonic-gate "news", LOG_NEWS, 160*7c478bd9Sstevel@tonic-gate "uucp", LOG_UUCP, 161*7c478bd9Sstevel@tonic-gate "audit", LOG_AUDIT, 162*7c478bd9Sstevel@tonic-gate "cron", LOG_CRON, 163*7c478bd9Sstevel@tonic-gate "local0", LOG_LOCAL0, 164*7c478bd9Sstevel@tonic-gate "local1", LOG_LOCAL1, 165*7c478bd9Sstevel@tonic-gate "local2", LOG_LOCAL2, 166*7c478bd9Sstevel@tonic-gate "local3", LOG_LOCAL3, 167*7c478bd9Sstevel@tonic-gate "local4", LOG_LOCAL4, 168*7c478bd9Sstevel@tonic-gate "local5", LOG_LOCAL5, 169*7c478bd9Sstevel@tonic-gate "local6", LOG_LOCAL6, 170*7c478bd9Sstevel@tonic-gate "local7", LOG_LOCAL7, 171*7c478bd9Sstevel@tonic-gate NULL, -1 172*7c478bd9Sstevel@tonic-gate }; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate static char *TypeNames[7] = { 175*7c478bd9Sstevel@tonic-gate "UNUSED", "FILE", "TTY", "CONSOLE", 176*7c478bd9Sstevel@tonic-gate "FORW", "USERS", "WALL" 177*7c478bd9Sstevel@tonic-gate }; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * we allocate our own thread stacks so we can create them 181*7c478bd9Sstevel@tonic-gate * without the MAP_NORESERVE option. We need to be sure 182*7c478bd9Sstevel@tonic-gate * we have stack space even if the machine runs out of swap 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate #define DEFAULT_STACKSIZE (100 * 1024) /* 100 k stack */ 186*7c478bd9Sstevel@tonic-gate #define DEFAULT_REDZONESIZE (8 * 1024) /* 8k redzone */ 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate static pthread_mutex_t wmp = PTHREAD_MUTEX_INITIALIZER; /* wallmsg lock */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate static pthread_mutex_t cft = PTHREAD_MUTEX_INITIALIZER; 191*7c478bd9Sstevel@tonic-gate static int conf_threads = 0; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static pthread_mutex_t hup_lock = PTHREAD_MUTEX_INITIALIZER; 194*7c478bd9Sstevel@tonic-gate static pthread_cond_t hup_done = PTHREAD_COND_INITIALIZER; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate static pthread_mutex_t logerror_lock = PTHREAD_MUTEX_INITIALIZER; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate #define HUP_ACCEPTABLE 0x0000 /* can start SIGHUP process */ 199*7c478bd9Sstevel@tonic-gate #define HUP_INPROGRESS 0x0001 /* SIGHUP process in progress */ 200*7c478bd9Sstevel@tonic-gate #define HUP_COMPLETED 0x0002 /* SIGHUP process completed */ 201*7c478bd9Sstevel@tonic-gate #define HUP_SUSP_LOGMSG_REQD 0x1000 /* request to suspend */ 202*7c478bd9Sstevel@tonic-gate #define HUP_LOGMSG_SUSPENDED 0x2000 /* logmsg is suspended */ 203*7c478bd9Sstevel@tonic-gate static int hup_state = HUP_ACCEPTABLE; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate static size_t stacksize; /* thread stack size */ 206*7c478bd9Sstevel@tonic-gate static size_t redzonesize; /* thread stack redzone size */ 207*7c478bd9Sstevel@tonic-gate static char *stack_ptr; /* ptr to allocated stacks */ 208*7c478bd9Sstevel@tonic-gate static char *cstack_ptr; /* ptr to conf_thr stacks */ 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate static time_t start_time; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate static pthread_t sys_thread; /* queues messages from us */ 213*7c478bd9Sstevel@tonic-gate static pthread_t net_thread; /* queues messages from the net */ 214*7c478bd9Sstevel@tonic-gate static pthread_t log_thread; /* message processing thread */ 215*7c478bd9Sstevel@tonic-gate static pthread_t hnl_thread; /* hostname lookup thread */ 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate static dataq_t inputq; /* the input queue */ 218*7c478bd9Sstevel@tonic-gate static dataq_t tmpq; /* temporary queue for err msg */ 219*7c478bd9Sstevel@tonic-gate static dataq_t hnlq; /* hostname lookup queue */ 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate static struct filed fallback[2]; 222*7c478bd9Sstevel@tonic-gate static struct filed *Files; 223*7c478bd9Sstevel@tonic-gate static int nlogs; 224*7c478bd9Sstevel@tonic-gate static int Debug; /* debug flag */ 225*7c478bd9Sstevel@tonic-gate static host_list_t LocalHostName; /* our hostname */ 226*7c478bd9Sstevel@tonic-gate static host_list_t NullHostName; /* in case of lookup failure */ 227*7c478bd9Sstevel@tonic-gate static int debuglev = 1; /* debug print level */ 228*7c478bd9Sstevel@tonic-gate static int interrorlog; /* internal error logging */ 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate static int MarkInterval = 20; /* interval between marks (mins) */ 231*7c478bd9Sstevel@tonic-gate static int Marking = 0; /* non-zero if marking some file */ 232*7c478bd9Sstevel@tonic-gate static int Ninputs = 0; /* number of network inputs */ 233*7c478bd9Sstevel@tonic-gate static int curalarm = 0; /* current timeout value (secs) */ 234*7c478bd9Sstevel@tonic-gate static int sys_msg_count = 0; /* total msgs rcvd from local log */ 235*7c478bd9Sstevel@tonic-gate static int sys_init_msg_count = 0; /* initially received */ 236*7c478bd9Sstevel@tonic-gate static int net_msg_count = 0; /* total msgs rcvd from net */ 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate static struct pollfd Pfd; /* Pollfd for local the log device */ 239*7c478bd9Sstevel@tonic-gate static struct pollfd *Nfd; /* Array of pollfds for udp ports */ 240*7c478bd9Sstevel@tonic-gate static struct netconfig *Ncf; 241*7c478bd9Sstevel@tonic-gate static struct netbuf **Myaddrs; 242*7c478bd9Sstevel@tonic-gate static struct t_unitdata **Udp; 243*7c478bd9Sstevel@tonic-gate static struct t_uderr **Errp; 244*7c478bd9Sstevel@tonic-gate static int turnoff = 0; 245*7c478bd9Sstevel@tonic-gate static int shutting_down; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate static struct hostname_cache *hnc_cache, *hnc_active, *hnc_freeq; 248*7c478bd9Sstevel@tonic-gate static pthread_mutex_t hnc_mutex = PTHREAD_MUTEX_INITIALIZER; 249*7c478bd9Sstevel@tonic-gate static size_t hnc_size = DEF_HNC_SIZE; 250*7c478bd9Sstevel@tonic-gate static unsigned int hnc_ttl = DEF_HNC_TTL; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate #define DPRINT0(d, m) if ((Debug) && debuglev >= (d)) \ 253*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m) 254*7c478bd9Sstevel@tonic-gate #define DPRINT1(d, m, a) if ((Debug) && debuglev >= (d)) \ 255*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a) 256*7c478bd9Sstevel@tonic-gate #define DPRINT2(d, m, a, b) if ((Debug) && debuglev >= (d)) \ 257*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b) 258*7c478bd9Sstevel@tonic-gate #define DPRINT3(d, m, a, b, c) if ((Debug) && debuglev >= (d)) \ 259*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c) 260*7c478bd9Sstevel@tonic-gate #define DPRINT4(d, m, a, b, c, e) if ((Debug) && debuglev >= (d)) \ 261*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c, e) 262*7c478bd9Sstevel@tonic-gate #define MALLOC_FAIL(x) \ 263*7c478bd9Sstevel@tonic-gate logerror("malloc failed: " x) 264*7c478bd9Sstevel@tonic-gate #define MALLOC_FAIL_EXIT \ 265*7c478bd9Sstevel@tonic-gate logerror("malloc failed - fatal"); \ 266*7c478bd9Sstevel@tonic-gate exit(1) 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate #define MAILCMD "mailx -s \"syslogd shut down\" root" 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Number of seconds to wait before giving up on threads that won't 273*7c478bd9Sstevel@tonic-gate * shutdown: (that's right, 10 minutes!) 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate #define LOOP_MAX (10 * 60) 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate /* 278*7c478bd9Sstevel@tonic-gate * Interval(sec) to check the status of output queue while processing 279*7c478bd9Sstevel@tonic-gate * HUP signal. 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate #define LOOP_INTERVAL (15) 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate int 284*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate int i; 287*7c478bd9Sstevel@tonic-gate char *pstr; 288*7c478bd9Sstevel@tonic-gate int sig, fd; 289*7c478bd9Sstevel@tonic-gate int tflag = 0, Tflag = 0; 290*7c478bd9Sstevel@tonic-gate sigset_t sigs, allsigs; 291*7c478bd9Sstevel@tonic-gate struct rlimit rlim; 292*7c478bd9Sstevel@tonic-gate char *debugstr; 293*7c478bd9Sstevel@tonic-gate int mcount = 0; 294*7c478bd9Sstevel@tonic-gate struct sigaction act; 295*7c478bd9Sstevel@tonic-gate pthread_t mythreadno = 0; 296*7c478bd9Sstevel@tonic-gate char cbuf [30]; 297*7c478bd9Sstevel@tonic-gate struct stat sb; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 300*7c478bd9Sstevel@tonic-gate #define DEBUGDIR "/var/tmp" 301*7c478bd9Sstevel@tonic-gate if (chdir(DEBUGDIR)) 302*7c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): Unable to cd to %s\n", mythreadno, 303*7c478bd9Sstevel@tonic-gate DEBUGDIR); 304*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if ((debugstr = getenv("SYSLOGD_DEBUG")) != NULL) 309*7c478bd9Sstevel@tonic-gate if ((debuglev = atoi(debugstr)) == 0) 310*7c478bd9Sstevel@tonic-gate debuglev = 1; 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate #if ! defined(TEXT_DOMAIN) /* should be defined by cc -D */ 313*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 314*7c478bd9Sstevel@tonic-gate #endif 315*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate (void) time(&start_time); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (lstat("/var/run", &sb) != 0 || !(S_ISDIR(sb.st_mode))) { 320*7c478bd9Sstevel@tonic-gate DoorFileName = OLD_DOORFILE; 321*7c478bd9Sstevel@tonic-gate PidFileName = OLD_PIDFILE; 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate defaults(); 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate while ((i = getopt(argc, argv, "df:p:m:tT")) != EOF) { 327*7c478bd9Sstevel@tonic-gate switch (i) { 328*7c478bd9Sstevel@tonic-gate case 'f': /* configuration file */ 329*7c478bd9Sstevel@tonic-gate ConfFile = optarg; 330*7c478bd9Sstevel@tonic-gate break; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate case 'd': /* debug */ 333*7c478bd9Sstevel@tonic-gate Debug++; 334*7c478bd9Sstevel@tonic-gate break; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate case 'p': /* path */ 337*7c478bd9Sstevel@tonic-gate LogName = optarg; 338*7c478bd9Sstevel@tonic-gate break; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate case 'm': /* mark interval */ 341*7c478bd9Sstevel@tonic-gate for (pstr = optarg; *pstr; pstr++) { 342*7c478bd9Sstevel@tonic-gate if (! (isdigit(*pstr))) { 343*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 344*7c478bd9Sstevel@tonic-gate "Illegal interval\n"); 345*7c478bd9Sstevel@tonic-gate usage(); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate MarkInterval = atoi(optarg); 349*7c478bd9Sstevel@tonic-gate if (MarkInterval < 1 || MarkInterval > INT_MAX) { 350*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 351*7c478bd9Sstevel@tonic-gate "Interval must be between 1 and %d\n", 352*7c478bd9Sstevel@tonic-gate INT_MAX); 353*7c478bd9Sstevel@tonic-gate usage(); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate break; 356*7c478bd9Sstevel@tonic-gate case 't': /* turn off remote reception */ 357*7c478bd9Sstevel@tonic-gate tflag++; 358*7c478bd9Sstevel@tonic-gate turnoff++; 359*7c478bd9Sstevel@tonic-gate break; 360*7c478bd9Sstevel@tonic-gate case 'T': /* turn on remote reception */ 361*7c478bd9Sstevel@tonic-gate Tflag++; 362*7c478bd9Sstevel@tonic-gate turnoff = 0; 363*7c478bd9Sstevel@tonic-gate break; 364*7c478bd9Sstevel@tonic-gate default: 365*7c478bd9Sstevel@tonic-gate usage(); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (optind < argc) 370*7c478bd9Sstevel@tonic-gate usage(); 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate if (tflag && Tflag) { 373*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "specify only one of -t and -T\n"); 374*7c478bd9Sstevel@tonic-gate usage(); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * close all fd's except 0-2 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate closefrom(3); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate if (!Debug) { 384*7c478bd9Sstevel@tonic-gate if (fork()) 385*7c478bd9Sstevel@tonic-gate return (0); 386*7c478bd9Sstevel@tonic-gate (void) close(0); 387*7c478bd9Sstevel@tonic-gate (void) open("/", 0); 388*7c478bd9Sstevel@tonic-gate (void) dup2(0, 1); 389*7c478bd9Sstevel@tonic-gate (void) dup2(0, 2); 390*7c478bd9Sstevel@tonic-gate untty(); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (Debug) { 394*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * DO NOT call logerror() until tmpq is initialized. 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate disable_errorlog(); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * ensure that file descriptor limit is "high enough" 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate (void) getrlimit(RLIMIT_NOFILE, &rlim); 406*7c478bd9Sstevel@tonic-gate if (rlim.rlim_cur < rlim.rlim_max) 407*7c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 408*7c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) 409*7c478bd9Sstevel@tonic-gate logerror("Unable to increase file descriptor limit."); 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* block all signals from all threads initially */ 412*7c478bd9Sstevel@tonic-gate (void) sigfillset(&allsigs); 413*7c478bd9Sstevel@tonic-gate (void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): Started at time %s", mythreadno, 416*7c478bd9Sstevel@tonic-gate ctime_r(&start_time, cbuf)); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate init(); /* read configuration, start threads */ 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): off & running....\n", mythreadno); 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* now set up to catch signals we care about */ 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigs); 425*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGHUP); /* reconfigure */ 426*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGALRM); /* mark & flush timer */ 427*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGTERM); /* exit */ 428*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGINT); /* exit if debugging */ 429*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGQUIT); /* exit if debugging */ 430*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGPIPE); /* catch & discard */ 431*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigs, SIGUSR1); /* dump debug stats */ 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * We must set up to catch these signals, even though sigwait 435*7c478bd9Sstevel@tonic-gate * will get them before the isr does. Setting SA_SIGINFO ensures 436*7c478bd9Sstevel@tonic-gate * that signals will be enqueued. 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 440*7c478bd9Sstevel@tonic-gate act.sa_sigaction = signull; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &act, NULL); 443*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &act, NULL); 444*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &act, NULL); 445*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &act, NULL); 446*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGQUIT, &act, NULL); 447*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGPIPE, &act, NULL); 448*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGUSR1, &act, NULL); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* we now turn into the signal handling thread */ 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate DPRINT1(2, "main(%u): now handling signals\n", mythreadno); 453*7c478bd9Sstevel@tonic-gate for (;;) { 454*7c478bd9Sstevel@tonic-gate (void) sigwait(&sigs, &sig); 455*7c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): received signal %d\n", mythreadno, sig); 456*7c478bd9Sstevel@tonic-gate switch (sig) { 457*7c478bd9Sstevel@tonic-gate case SIGALRM: 458*7c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): Got SIGALRM\n", 459*7c478bd9Sstevel@tonic-gate mythreadno); 460*7c478bd9Sstevel@tonic-gate flushmsg(NOCOPY); 461*7c478bd9Sstevel@tonic-gate if (Marking && (++mcount % MARKCOUNT == 0)) { 462*7c478bd9Sstevel@tonic-gate if (logmymsg(LOG_INFO, "-- MARK --", 463*7c478bd9Sstevel@tonic-gate ADDDATE|MARK|NOCOPY, 0) == -1) { 464*7c478bd9Sstevel@tonic-gate MALLOC_FAIL( 465*7c478bd9Sstevel@tonic-gate "dropping MARK message"); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate mcount = 0; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT; 471*7c478bd9Sstevel@tonic-gate (void) alarm((unsigned)curalarm); 472*7c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): Next alarm in %d " 473*7c478bd9Sstevel@tonic-gate "seconds\n", mythreadno, curalarm); 474*7c478bd9Sstevel@tonic-gate break; 475*7c478bd9Sstevel@tonic-gate case SIGHUP: 476*7c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): got SIGHUP - " 477*7c478bd9Sstevel@tonic-gate "reconfiguring\n", mythreadno); 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate reconfigure(); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate DPRINT1(1, "main(%u): done processing SIGHUP\n", 482*7c478bd9Sstevel@tonic-gate mythreadno); 483*7c478bd9Sstevel@tonic-gate break; 484*7c478bd9Sstevel@tonic-gate case SIGQUIT: 485*7c478bd9Sstevel@tonic-gate case SIGINT: 486*7c478bd9Sstevel@tonic-gate if (!Debug) { 487*7c478bd9Sstevel@tonic-gate /* allow these signals if debugging */ 488*7c478bd9Sstevel@tonic-gate break; 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 491*7c478bd9Sstevel@tonic-gate case SIGTERM: 492*7c478bd9Sstevel@tonic-gate DPRINT2(1, "main(%u): going down on signal %d\n", 493*7c478bd9Sstevel@tonic-gate mythreadno, sig); 494*7c478bd9Sstevel@tonic-gate (void) alarm(0); 495*7c478bd9Sstevel@tonic-gate flushmsg(0); 496*7c478bd9Sstevel@tonic-gate errno = 0; 497*7c478bd9Sstevel@tonic-gate t_errno = 0; 498*7c478bd9Sstevel@tonic-gate logerror("going down on signal %d", sig); 499*7c478bd9Sstevel@tonic-gate disable_errorlog(); /* force msg to console */ 500*7c478bd9Sstevel@tonic-gate (void) shutdown_msg(); /* stop threads */ 501*7c478bd9Sstevel@tonic-gate shutdown_input(); 502*7c478bd9Sstevel@tonic-gate close_door(); 503*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 504*7c478bd9Sstevel@tonic-gate return (0); 505*7c478bd9Sstevel@tonic-gate break; 506*7c478bd9Sstevel@tonic-gate case SIGUSR1: /* secret debug dump mode */ 507*7c478bd9Sstevel@tonic-gate /* if in debug mode, use stdout */ 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if (Debug) { 510*7c478bd9Sstevel@tonic-gate dumpstats(STDOUT_FILENO); 511*7c478bd9Sstevel@tonic-gate break; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate /* otherwise dump to a debug file */ 514*7c478bd9Sstevel@tonic-gate if ((fd = open(DEBUGFILE, 515*7c478bd9Sstevel@tonic-gate (O_WRONLY|O_CREAT|O_TRUNC|O_EXCL), 516*7c478bd9Sstevel@tonic-gate 0644)) < 0) 517*7c478bd9Sstevel@tonic-gate break; 518*7c478bd9Sstevel@tonic-gate dumpstats(fd); 519*7c478bd9Sstevel@tonic-gate (void) close(fd); 520*7c478bd9Sstevel@tonic-gate break; 521*7c478bd9Sstevel@tonic-gate default: 522*7c478bd9Sstevel@tonic-gate DPRINT2(2, "main(%u): unexpected signal %d\n", 523*7c478bd9Sstevel@tonic-gate mythreadno, sig); 524*7c478bd9Sstevel@tonic-gate break; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * Attempts to open the local log device 531*7c478bd9Sstevel@tonic-gate * and return a file descriptor. 532*7c478bd9Sstevel@tonic-gate */ 533*7c478bd9Sstevel@tonic-gate static int 534*7c478bd9Sstevel@tonic-gate openklog(char *name, int mode) 535*7c478bd9Sstevel@tonic-gate { 536*7c478bd9Sstevel@tonic-gate int fd; 537*7c478bd9Sstevel@tonic-gate struct strioctl str; 538*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate if (Debug) { 541*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate if ((fd = open(name, mode)) < 0) { 545*7c478bd9Sstevel@tonic-gate logerror("cannot open %s", name); 546*7c478bd9Sstevel@tonic-gate DPRINT3(1, "openklog(%u): cannot create %s (%d)\n", 547*7c478bd9Sstevel@tonic-gate mythreadno, name, errno); 548*7c478bd9Sstevel@tonic-gate return (-1); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate str.ic_cmd = I_CONSLOG; 551*7c478bd9Sstevel@tonic-gate str.ic_timout = 0; 552*7c478bd9Sstevel@tonic-gate str.ic_len = 0; 553*7c478bd9Sstevel@tonic-gate str.ic_dp = NULL; 554*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) < 0) { 555*7c478bd9Sstevel@tonic-gate logerror("cannot register to log console messages"); 556*7c478bd9Sstevel@tonic-gate DPRINT2(1, "openklog(%u): cannot register to log " 557*7c478bd9Sstevel@tonic-gate "console messages (%d)\n", mythreadno, errno); 558*7c478bd9Sstevel@tonic-gate return (-1); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate return (fd); 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate /* 565*7c478bd9Sstevel@tonic-gate * Open the log device, and pull up all pending messages. 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate static void 568*7c478bd9Sstevel@tonic-gate prepare_sys_poll() 569*7c478bd9Sstevel@tonic-gate { 570*7c478bd9Sstevel@tonic-gate int nfds, funix; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if ((funix = openklog(LogName, O_RDONLY)) < 0) { 573*7c478bd9Sstevel@tonic-gate logerror("can't open kernel log device - fatal"); 574*7c478bd9Sstevel@tonic-gate exit(1); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate Pfd.fd = funix; 578*7c478bd9Sstevel@tonic-gate Pfd.events = POLLIN; 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate for (;;) { 581*7c478bd9Sstevel@tonic-gate nfds = poll(&Pfd, 1, 0); 582*7c478bd9Sstevel@tonic-gate if (nfds <= 0) { 583*7c478bd9Sstevel@tonic-gate if (sys_init_msg_count > 0) 584*7c478bd9Sstevel@tonic-gate flushmsg(SYNC_FILE); 585*7c478bd9Sstevel@tonic-gate break; 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate if (Pfd.revents & POLLIN) { 589*7c478bd9Sstevel@tonic-gate getkmsg(0); 590*7c478bd9Sstevel@tonic-gate } else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { 591*7c478bd9Sstevel@tonic-gate logerror("kernel log driver poll error"); 592*7c478bd9Sstevel@tonic-gate break; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * this thread listens to the local stream log driver for log messages 600*7c478bd9Sstevel@tonic-gate * generated by this host, formats them, and queues them to the logger 601*7c478bd9Sstevel@tonic-gate * thread. 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 604*7c478bd9Sstevel@tonic-gate static void * 605*7c478bd9Sstevel@tonic-gate sys_poll(void *ap) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate int nfds; 608*7c478bd9Sstevel@tonic-gate static int klogerrs = 0; 609*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate if (Debug) { 612*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate DPRINT1(1, "sys_poll(%u): sys_thread started\n", mythreadno); 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* 618*7c478bd9Sstevel@tonic-gate * Try to process as many messages as we can without blocking on poll. 619*7c478bd9Sstevel@tonic-gate * We count such "initial" messages with sys_init_msg_count and 620*7c478bd9Sstevel@tonic-gate * enqueue them without the SYNC_FILE flag. When no more data is 621*7c478bd9Sstevel@tonic-gate * waiting on the local log device, we set timeout to INFTIM, 622*7c478bd9Sstevel@tonic-gate * clear sys_init_msg_count, and generate a flush message to sync 623*7c478bd9Sstevel@tonic-gate * the previously counted initial messages out to disk. 624*7c478bd9Sstevel@tonic-gate */ 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate sys_init_msg_count = 0; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate for (;;) { 629*7c478bd9Sstevel@tonic-gate errno = 0; 630*7c478bd9Sstevel@tonic-gate t_errno = 0; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate nfds = poll(&Pfd, 1, INFTIM); 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate if (nfds == 0) 635*7c478bd9Sstevel@tonic-gate continue; 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate if (nfds < 0) { 638*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 639*7c478bd9Sstevel@tonic-gate logerror("poll"); 640*7c478bd9Sstevel@tonic-gate continue; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate if (Pfd.revents & POLLIN) { 643*7c478bd9Sstevel@tonic-gate getkmsg(INFTIM); 644*7c478bd9Sstevel@tonic-gate } else { 645*7c478bd9Sstevel@tonic-gate if (shutting_down) { 646*7c478bd9Sstevel@tonic-gate pthread_exit(0); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { 649*7c478bd9Sstevel@tonic-gate logerror("kernel log driver poll error"); 650*7c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 651*7c478bd9Sstevel@tonic-gate Pfd.fd = -1; 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate while (Pfd.fd == -1 && klogerrs++ < 10) { 656*7c478bd9Sstevel@tonic-gate Pfd.fd = openklog(LogName, O_RDONLY); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate if (klogerrs >= 10) { 659*7c478bd9Sstevel@tonic-gate logerror("can't reopen kernel log device - fatal"); 660*7c478bd9Sstevel@tonic-gate exit(1); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 664*7c478bd9Sstevel@tonic-gate return (NULL); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * Pull up one message from log driver. 669*7c478bd9Sstevel@tonic-gate */ 670*7c478bd9Sstevel@tonic-gate static void 671*7c478bd9Sstevel@tonic-gate getkmsg(int timeout) 672*7c478bd9Sstevel@tonic-gate { 673*7c478bd9Sstevel@tonic-gate int flags = 0, i; 674*7c478bd9Sstevel@tonic-gate char *lastline; 675*7c478bd9Sstevel@tonic-gate struct strbuf ctl, dat; 676*7c478bd9Sstevel@tonic-gate struct log_ctl hdr; 677*7c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 678*7c478bd9Sstevel@tonic-gate size_t buflen; 679*7c478bd9Sstevel@tonic-gate size_t len; 680*7c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE+1]; 681*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate if (Debug) { 684*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE; 688*7c478bd9Sstevel@tonic-gate dat.buf = buf; 689*7c478bd9Sstevel@tonic-gate ctl.maxlen = sizeof (struct log_ctl); 690*7c478bd9Sstevel@tonic-gate ctl.buf = (caddr_t)&hdr; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) { 693*7c478bd9Sstevel@tonic-gate lastline = &dat.buf[dat.len]; 694*7c478bd9Sstevel@tonic-gate *lastline = '\0'; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate DPRINT2(5, "sys_poll:(%u): getmsg: dat.len = %d\n", 697*7c478bd9Sstevel@tonic-gate mythreadno, dat.len); 698*7c478bd9Sstevel@tonic-gate buflen = strlen(buf); 699*7c478bd9Sstevel@tonic-gate len = findnl_bkwd(buf, buflen); 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate (void) memcpy(tmpbuf, buf, len); 702*7c478bd9Sstevel@tonic-gate tmpbuf[len] = '\0'; 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate /* 705*7c478bd9Sstevel@tonic-gate * Format sys will enqueue the log message. 706*7c478bd9Sstevel@tonic-gate * Set the sync flag if timeout != 0, which 707*7c478bd9Sstevel@tonic-gate * means that we're done handling all the 708*7c478bd9Sstevel@tonic-gate * initial messages ready during startup. 709*7c478bd9Sstevel@tonic-gate */ 710*7c478bd9Sstevel@tonic-gate if (timeout == 0) { 711*7c478bd9Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 0); 712*7c478bd9Sstevel@tonic-gate sys_init_msg_count++; 713*7c478bd9Sstevel@tonic-gate } else { 714*7c478bd9Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 1); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate sys_msg_count++; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if (len != buflen) { 719*7c478bd9Sstevel@tonic-gate /* If anything remains in buf */ 720*7c478bd9Sstevel@tonic-gate size_t remlen; 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate if (buf[len] == '\n') { 723*7c478bd9Sstevel@tonic-gate /* skip newline */ 724*7c478bd9Sstevel@tonic-gate len++; 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate /* 728*7c478bd9Sstevel@tonic-gate * Move the remaining bytes to 729*7c478bd9Sstevel@tonic-gate * the beginnning of buf. 730*7c478bd9Sstevel@tonic-gate */ 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate remlen = buflen - len; 733*7c478bd9Sstevel@tonic-gate (void) memcpy(buf, &buf[len], remlen); 734*7c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE - remlen; 735*7c478bd9Sstevel@tonic-gate dat.buf = &buf[remlen]; 736*7c478bd9Sstevel@tonic-gate } else { 737*7c478bd9Sstevel@tonic-gate dat.maxlen = MAXLINE; 738*7c478bd9Sstevel@tonic-gate dat.buf = buf; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (i == 0 && dat.len > 0) { 743*7c478bd9Sstevel@tonic-gate dat.buf[dat.len] = '\0'; 744*7c478bd9Sstevel@tonic-gate /* 745*7c478bd9Sstevel@tonic-gate * Format sys will enqueue the log message. 746*7c478bd9Sstevel@tonic-gate * Set the sync flag if timeout != 0, which 747*7c478bd9Sstevel@tonic-gate * means that we're done handling all the 748*7c478bd9Sstevel@tonic-gate * initial messages ready during startup. 749*7c478bd9Sstevel@tonic-gate */ 750*7c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.maxlen = %d\n", 751*7c478bd9Sstevel@tonic-gate mythreadno, dat.maxlen); 752*7c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.len = %d\n", 753*7c478bd9Sstevel@tonic-gate mythreadno, dat.len); 754*7c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: strlen(dat.buf) = %d\n", 755*7c478bd9Sstevel@tonic-gate mythreadno, strlen(dat.buf)); 756*7c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.buf = \"%s\"\n", 757*7c478bd9Sstevel@tonic-gate mythreadno, dat.buf); 758*7c478bd9Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): buf len = %d\n", 759*7c478bd9Sstevel@tonic-gate mythreadno, strlen(buf)); 760*7c478bd9Sstevel@tonic-gate if (timeout == 0) { 761*7c478bd9Sstevel@tonic-gate formatsys(&hdr, buf, 0); 762*7c478bd9Sstevel@tonic-gate sys_init_msg_count++; 763*7c478bd9Sstevel@tonic-gate } else { 764*7c478bd9Sstevel@tonic-gate formatsys(&hdr, buf, 1); 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate sys_msg_count++; 767*7c478bd9Sstevel@tonic-gate } else if (i < 0 && errno != EINTR) { 768*7c478bd9Sstevel@tonic-gate if (!shutting_down) { 769*7c478bd9Sstevel@tonic-gate logerror("kernel log driver read error"); 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 772*7c478bd9Sstevel@tonic-gate Pfd.fd = -1; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* 777*7c478bd9Sstevel@tonic-gate * this thread polls all the network interfaces for syslog messages 778*7c478bd9Sstevel@tonic-gate * forwarded to us, tags them with the hostname they are received 779*7c478bd9Sstevel@tonic-gate * from, and queues them to the logger thread. 780*7c478bd9Sstevel@tonic-gate */ 781*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 782*7c478bd9Sstevel@tonic-gate static void * 783*7c478bd9Sstevel@tonic-gate net_poll(void *ap) 784*7c478bd9Sstevel@tonic-gate { 785*7c478bd9Sstevel@tonic-gate int nfds, i; 786*7c478bd9Sstevel@tonic-gate int flags = 0; 787*7c478bd9Sstevel@tonic-gate struct t_unitdata *udp; 788*7c478bd9Sstevel@tonic-gate struct t_uderr *errp; 789*7c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 790*7c478bd9Sstevel@tonic-gate char *uap; 791*7c478bd9Sstevel@tonic-gate log_message_t *mp; 792*7c478bd9Sstevel@tonic-gate host_info_t *hinfo; 793*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate if (Debug) { 796*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): net_thread started\n", mythreadno); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate for (;;) { 804*7c478bd9Sstevel@tonic-gate errno = 0; 805*7c478bd9Sstevel@tonic-gate t_errno = 0; 806*7c478bd9Sstevel@tonic-gate nfds = poll(Nfd, Ninputs, -1); 807*7c478bd9Sstevel@tonic-gate if (nfds == 0) 808*7c478bd9Sstevel@tonic-gate continue; 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate if (nfds < 0) { 811*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 812*7c478bd9Sstevel@tonic-gate logerror("poll"); 813*7c478bd9Sstevel@tonic-gate continue; 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate for (i = 0; nfds > 0 && i < Ninputs; i++) { 816*7c478bd9Sstevel@tonic-gate if ((Nfd[i].revents & POLLIN) == 0) { 817*7c478bd9Sstevel@tonic-gate if (shutting_down) { 818*7c478bd9Sstevel@tonic-gate pthread_exit(0); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate if (Nfd[i].revents & 821*7c478bd9Sstevel@tonic-gate (POLLNVAL|POLLHUP|POLLERR)) { 822*7c478bd9Sstevel@tonic-gate logerror("POLLNVAL|POLLHUP|POLLERR"); 823*7c478bd9Sstevel@tonic-gate (void) t_close(Nfd[i].fd); 824*7c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 825*7c478bd9Sstevel@tonic-gate nfds--; 826*7c478bd9Sstevel@tonic-gate } 827*7c478bd9Sstevel@tonic-gate continue; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate udp = Udp[i]; 831*7c478bd9Sstevel@tonic-gate udp->udata.buf = buf; 832*7c478bd9Sstevel@tonic-gate udp->udata.maxlen = MAXLINE; 833*7c478bd9Sstevel@tonic-gate udp->udata.len = 0; 834*7c478bd9Sstevel@tonic-gate flags = 0; 835*7c478bd9Sstevel@tonic-gate if (t_rcvudata(Nfd[i].fd, udp, &flags) < 0) { 836*7c478bd9Sstevel@tonic-gate errp = Errp[i]; 837*7c478bd9Sstevel@tonic-gate if (t_errno == TLOOK) { 838*7c478bd9Sstevel@tonic-gate if (t_rcvuderr(Nfd[i].fd, errp) < 0) { 839*7c478bd9Sstevel@tonic-gate if (!shutting_down) { 840*7c478bd9Sstevel@tonic-gate logerror("t_rcvuderr"); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate t_close(Nfd[i].fd); 843*7c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate } else { 846*7c478bd9Sstevel@tonic-gate if (!shutting_down) { 847*7c478bd9Sstevel@tonic-gate logerror("t_rcvudata"); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate t_close(Nfd[i].fd); 850*7c478bd9Sstevel@tonic-gate Nfd[i].fd = -1; 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate nfds--; 853*7c478bd9Sstevel@tonic-gate if (shutting_down) { 854*7c478bd9Sstevel@tonic-gate pthread_exit(0); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate continue; 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate nfds--; 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate if (udp->udata.len == 0) { 861*7c478bd9Sstevel@tonic-gate if (Debug) { 862*7c478bd9Sstevel@tonic-gate uap = NULL; 863*7c478bd9Sstevel@tonic-gate if (udp->addr.len > 0) { 864*7c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i], 865*7c478bd9Sstevel@tonic-gate &udp->addr); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate DPRINT2(1, "net_poll(%u):" 868*7c478bd9Sstevel@tonic-gate " received empty packet" 869*7c478bd9Sstevel@tonic-gate " from %s\n", mythreadno, 870*7c478bd9Sstevel@tonic-gate uap ? uap : "<unknown>"); 871*7c478bd9Sstevel@tonic-gate if (uap) 872*7c478bd9Sstevel@tonic-gate free(uap); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate continue; /* No data */ 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate if (udp->addr.len == 0) { 877*7c478bd9Sstevel@tonic-gate /* 878*7c478bd9Sstevel@tonic-gate * The previous message was larger than 879*7c478bd9Sstevel@tonic-gate * MAXLINE, and T_MORE should have been set. 880*7c478bd9Sstevel@tonic-gate * Further data needs to be discarded as 881*7c478bd9Sstevel@tonic-gate * we've already received MAXLINE. 882*7c478bd9Sstevel@tonic-gate */ 883*7c478bd9Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): discarding packet " 884*7c478bd9Sstevel@tonic-gate "exceeds max line size\n", mythreadno); 885*7c478bd9Sstevel@tonic-gate continue; 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate net_msg_count++; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 891*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 892*7c478bd9Sstevel@tonic-gate "remote"); 893*7c478bd9Sstevel@tonic-gate continue; 894*7c478bd9Sstevel@tonic-gate } 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate buf[udp->udata.len] = '\0'; 897*7c478bd9Sstevel@tonic-gate formatnet(&udp->udata, mp); 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate if (Debug) { 900*7c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i], &udp->addr); 901*7c478bd9Sstevel@tonic-gate DPRINT2(1, "net_poll(%u): received message" 902*7c478bd9Sstevel@tonic-gate " from %s\n", mythreadno, 903*7c478bd9Sstevel@tonic-gate uap ? uap : "<unknown>"); 904*7c478bd9Sstevel@tonic-gate free(uap); 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate if ((hinfo = malloc(sizeof (*hinfo))) == NULL || 907*7c478bd9Sstevel@tonic-gate (hinfo->addr.buf = 908*7c478bd9Sstevel@tonic-gate malloc(udp->addr.len)) == NULL) { 909*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 910*7c478bd9Sstevel@tonic-gate "remote"); 911*7c478bd9Sstevel@tonic-gate if (hinfo) { 912*7c478bd9Sstevel@tonic-gate free(hinfo); 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate free_msg(mp); 915*7c478bd9Sstevel@tonic-gate continue; 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate hinfo->ncp = &Ncf[i]; 919*7c478bd9Sstevel@tonic-gate hinfo->addr.len = udp->addr.len; 920*7c478bd9Sstevel@tonic-gate (void) memcpy(hinfo->addr.buf, udp->addr.buf, 921*7c478bd9Sstevel@tonic-gate udp->addr.len); 922*7c478bd9Sstevel@tonic-gate mp->ptr = hinfo; 923*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&hnlq, (void *)mp) == -1) { 924*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from " 925*7c478bd9Sstevel@tonic-gate "remote"); 926*7c478bd9Sstevel@tonic-gate free_msg(mp); 927*7c478bd9Sstevel@tonic-gate free(hinfo->addr.buf); 928*7c478bd9Sstevel@tonic-gate free(hinfo); 929*7c478bd9Sstevel@tonic-gate continue; 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate DPRINT3(5, "net_poll(%u): enqueued msg %p " 932*7c478bd9Sstevel@tonic-gate "on queue %p\n", mythreadno, mp, &hnlq); 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 936*7c478bd9Sstevel@tonic-gate return (NULL); 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate static void 940*7c478bd9Sstevel@tonic-gate usage(void) 941*7c478bd9Sstevel@tonic-gate { 942*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 943*7c478bd9Sstevel@tonic-gate "usage: syslogd [-d] [-t|-T] [-mmarkinterval] [-ppath]" 944*7c478bd9Sstevel@tonic-gate " [-fconffile]\n"); 945*7c478bd9Sstevel@tonic-gate exit(1); 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate static void 949*7c478bd9Sstevel@tonic-gate untty(void) 950*7c478bd9Sstevel@tonic-gate { 951*7c478bd9Sstevel@tonic-gate if (!Debug) 952*7c478bd9Sstevel@tonic-gate (void) setsid(); 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate /* 956*7c478bd9Sstevel@tonic-gate * generate a log message internally. The original version of syslogd 957*7c478bd9Sstevel@tonic-gate * simply called logmsg directly, but because everything is now based 958*7c478bd9Sstevel@tonic-gate * on message passing, we need an internal way to generate and queue 959*7c478bd9Sstevel@tonic-gate * log messages from within syslogd itself. 960*7c478bd9Sstevel@tonic-gate */ 961*7c478bd9Sstevel@tonic-gate static int 962*7c478bd9Sstevel@tonic-gate logmymsg(int pri, char *msg, int flags, int pending) 963*7c478bd9Sstevel@tonic-gate { 964*7c478bd9Sstevel@tonic-gate log_message_t *mp; 965*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 966*7c478bd9Sstevel@tonic-gate dataq_t *qptr; 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate if (Debug) { 969*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 973*7c478bd9Sstevel@tonic-gate return (-1); 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 977*7c478bd9Sstevel@tonic-gate mp->pri = pri; 978*7c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 979*7c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, msg, MAXLINE+1); 980*7c478bd9Sstevel@tonic-gate mp->flags = flags; 981*7c478bd9Sstevel@tonic-gate (void) time(&mp->ts); 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate qptr = pending ? &tmpq : &inputq; 984*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(qptr, (void *)mp) == -1) { 985*7c478bd9Sstevel@tonic-gate free_msg(mp); 986*7c478bd9Sstevel@tonic-gate return (-1); 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logmymsg(%u): enqueued msg %p on queue %p\n", 990*7c478bd9Sstevel@tonic-gate mythreadno, mp, qptr); 991*7c478bd9Sstevel@tonic-gate DPRINT2(5, "logmymsg(%u): Message content: %s\n", mythreadno, msg); 992*7c478bd9Sstevel@tonic-gate return (0); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate /* 996*7c478bd9Sstevel@tonic-gate * Generate an internal shutdown message 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate static int 999*7c478bd9Sstevel@tonic-gate shutdown_msg(void) 1000*7c478bd9Sstevel@tonic-gate { 1001*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1002*7c478bd9Sstevel@tonic-gate log_message_t *mp; 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate if (Debug) { 1005*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1006*7c478bd9Sstevel@tonic-gate } 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 1009*7c478bd9Sstevel@tonic-gate return (-1); 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 1013*7c478bd9Sstevel@tonic-gate mp->flags = SHUTDOWN; 1014*7c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 1017*7c478bd9Sstevel@tonic-gate free_msg(mp); 1018*7c478bd9Sstevel@tonic-gate return (-1); 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate DPRINT3(5, "shutdown_msg(%u): enqueued msg %p on queue %p\n", 1022*7c478bd9Sstevel@tonic-gate mythreadno, mp, &inputq); 1023*7c478bd9Sstevel@tonic-gate return (0); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate /* 1027*7c478bd9Sstevel@tonic-gate * Generate an internal flush message 1028*7c478bd9Sstevel@tonic-gate */ 1029*7c478bd9Sstevel@tonic-gate static void 1030*7c478bd9Sstevel@tonic-gate flushmsg(int flags) 1031*7c478bd9Sstevel@tonic-gate { 1032*7c478bd9Sstevel@tonic-gate log_message_t *mp; 1033*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate if (Debug) { 1036*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 1040*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg"); 1041*7c478bd9Sstevel@tonic-gate return; 1042*7c478bd9Sstevel@tonic-gate } 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 1045*7c478bd9Sstevel@tonic-gate mp->flags = FLUSHMSG | flags; 1046*7c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 1049*7c478bd9Sstevel@tonic-gate free_msg(mp); 1050*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg"); 1051*7c478bd9Sstevel@tonic-gate return; 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate DPRINT4(5, "flush_msg(%u): enqueued msg %p on queue %p, flags " 1055*7c478bd9Sstevel@tonic-gate "0x%x\n", mythreadno, mp, &inputq, flags); 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate /* 1059*7c478bd9Sstevel@tonic-gate * Do some processing on messages received from the net 1060*7c478bd9Sstevel@tonic-gate */ 1061*7c478bd9Sstevel@tonic-gate static void 1062*7c478bd9Sstevel@tonic-gate formatnet(struct netbuf *nbp, log_message_t *mp) 1063*7c478bd9Sstevel@tonic-gate { 1064*7c478bd9Sstevel@tonic-gate char *p; 1065*7c478bd9Sstevel@tonic-gate int pri; 1066*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate if (Debug) { 1069*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1070*7c478bd9Sstevel@tonic-gate } 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate DPRINT2(5, "formatnet(%u): called for msg %p\n", mythreadno, mp); 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate mp->flags = NETWORK; 1075*7c478bd9Sstevel@tonic-gate (void) time(&mp->ts); 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate /* test for special codes */ 1078*7c478bd9Sstevel@tonic-gate pri = DEFUPRI; 1079*7c478bd9Sstevel@tonic-gate p = nbp->buf; 1080*7c478bd9Sstevel@tonic-gate DPRINT2(9, "formatnet(%u): Message content:\n>%s<\n", mythreadno, 1081*7c478bd9Sstevel@tonic-gate p); 1082*7c478bd9Sstevel@tonic-gate if (*p == '<' && isdigit(*(p+1))) { 1083*7c478bd9Sstevel@tonic-gate pri = 0; 1084*7c478bd9Sstevel@tonic-gate while (isdigit(*++p)) 1085*7c478bd9Sstevel@tonic-gate pri = 10 * pri + (*p - '0'); 1086*7c478bd9Sstevel@tonic-gate if (*p == '>') 1087*7c478bd9Sstevel@tonic-gate ++p; 1088*7c478bd9Sstevel@tonic-gate if (pri <= 0 || pri >= (LOG_NFACILITIES << 3)) 1089*7c478bd9Sstevel@tonic-gate pri = DEFUPRI; 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate mp->pri = pri; 1093*7c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, p, MAXLINE+1); 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate /* 1097*7c478bd9Sstevel@tonic-gate * Do some processing on messages generated by this host 1098*7c478bd9Sstevel@tonic-gate * and then enqueue the log message. 1099*7c478bd9Sstevel@tonic-gate */ 1100*7c478bd9Sstevel@tonic-gate static void 1101*7c478bd9Sstevel@tonic-gate formatsys(struct log_ctl *lp, char *msg, int sync) 1102*7c478bd9Sstevel@tonic-gate { 1103*7c478bd9Sstevel@tonic-gate char *p, *q; 1104*7c478bd9Sstevel@tonic-gate char line[MAXLINE + 1]; 1105*7c478bd9Sstevel@tonic-gate size_t msglen; 1106*7c478bd9Sstevel@tonic-gate log_message_t *mp; 1107*7c478bd9Sstevel@tonic-gate char cbuf[30]; 1108*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate if (Debug) { 1111*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate DPRINT3(3, "formatsys(%u): log_ctl.mid = %d, log_ctl.sid = %d\n", 1115*7c478bd9Sstevel@tonic-gate mythreadno, lp->mid, lp->sid); 1116*7c478bd9Sstevel@tonic-gate DPRINT2(9, "formatsys(%u): Message Content:\n>%s<\n", mythreadno, 1117*7c478bd9Sstevel@tonic-gate msg); 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate /* msglen includes the null termination */ 1120*7c478bd9Sstevel@tonic-gate msglen = strlen(msg) + 1; 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate for (p = msg; *p != '\0'; ) { 1123*7c478bd9Sstevel@tonic-gate size_t linelen; 1124*7c478bd9Sstevel@tonic-gate size_t len; 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate /* 1127*7c478bd9Sstevel@tonic-gate * Allocate a log_message_t structure. 1128*7c478bd9Sstevel@tonic-gate * We should do it here since a single message (msg) 1129*7c478bd9Sstevel@tonic-gate * could be composed of many lines. 1130*7c478bd9Sstevel@tonic-gate */ 1131*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)); 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 1134*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1135*7c478bd9Sstevel@tonic-gate /* 1136*7c478bd9Sstevel@tonic-gate * Should bail out from the loop. 1137*7c478bd9Sstevel@tonic-gate */ 1138*7c478bd9Sstevel@tonic-gate break; 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate mp->flags &= ~NETWORK; 1142*7c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 1143*7c478bd9Sstevel@tonic-gate mp->ts = lp->ttime; 1144*7c478bd9Sstevel@tonic-gate if (lp->flags & SL_LOGONLY) 1145*7c478bd9Sstevel@tonic-gate mp->flags |= IGN_CONS; 1146*7c478bd9Sstevel@tonic-gate if (lp->flags & SL_CONSONLY) 1147*7c478bd9Sstevel@tonic-gate mp->flags |= IGN_FILE; 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate /* extract facility */ 1150*7c478bd9Sstevel@tonic-gate if ((lp->pri & LOG_FACMASK) == LOG_KERN) { 1151*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "%.15s ", 1152*7c478bd9Sstevel@tonic-gate ctime_r(&mp->ts, cbuf) + 4); 1153*7c478bd9Sstevel@tonic-gate } else { 1154*7c478bd9Sstevel@tonic-gate (void) sprintf(line, ""); 1155*7c478bd9Sstevel@tonic-gate } 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate linelen = strlen(line); 1158*7c478bd9Sstevel@tonic-gate q = line + linelen; 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): msglen = %d\n", mythreadno, msglen); 1161*7c478bd9Sstevel@tonic-gate len = copynl_frwd(q, MAXLINE + 1 - linelen, p, msglen); 1162*7c478bd9Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): len (copynl_frwd) = %d\n", 1163*7c478bd9Sstevel@tonic-gate mythreadno, len); 1164*7c478bd9Sstevel@tonic-gate 1165*7c478bd9Sstevel@tonic-gate p += len; 1166*7c478bd9Sstevel@tonic-gate msglen -= len; 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate if (*p == '\n') { 1169*7c478bd9Sstevel@tonic-gate /* skip newline */ 1170*7c478bd9Sstevel@tonic-gate p++; 1171*7c478bd9Sstevel@tonic-gate } 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate if (sync && ((lp->pri & LOG_FACMASK) == LOG_KERN)) 1174*7c478bd9Sstevel@tonic-gate mp->flags |= SYNC_FILE; /* fsync file after write */ 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate if (len != 0) { 1177*7c478bd9Sstevel@tonic-gate (void) strlcpy(mp->msg, line, MAXLINE+1); 1178*7c478bd9Sstevel@tonic-gate mp->pri = lp->pri; 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 1181*7c478bd9Sstevel@tonic-gate free_msg(mp); 1182*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1183*7c478bd9Sstevel@tonic-gate break; 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate DPRINT3(5, "formatsys(%u): sys_thread enqueued msg " 1187*7c478bd9Sstevel@tonic-gate "%p on queue %p\n", mythreadno, mp, &inputq); 1188*7c478bd9Sstevel@tonic-gate } else 1189*7c478bd9Sstevel@tonic-gate free_msg(mp); 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate /* 1194*7c478bd9Sstevel@tonic-gate * Log a message to the appropriate log files, users, etc. based on 1195*7c478bd9Sstevel@tonic-gate * the priority. 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1198*7c478bd9Sstevel@tonic-gate static void * 1199*7c478bd9Sstevel@tonic-gate logmsg(void *ap) 1200*7c478bd9Sstevel@tonic-gate { 1201*7c478bd9Sstevel@tonic-gate struct filed *f; 1202*7c478bd9Sstevel@tonic-gate int fac, prilev, flags, refcnt; 1203*7c478bd9Sstevel@tonic-gate int fake_shutdown, skip_shutdown; 1204*7c478bd9Sstevel@tonic-gate log_message_t *mp, *save_mp; 1205*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate if (Debug) { 1208*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate DPRINT1(1, "logmsg(%u): msg dispatcher started\n", mythreadno); 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate fake_shutdown = skip_shutdown = 0; 1214*7c478bd9Sstevel@tonic-gate save_mp = NULL; 1215*7c478bd9Sstevel@tonic-gate for (;;) { 1216*7c478bd9Sstevel@tonic-gate if (save_mp) { 1217*7c478bd9Sstevel@tonic-gate /* 1218*7c478bd9Sstevel@tonic-gate * If we have set aside a message in order to fake a 1219*7c478bd9Sstevel@tonic-gate * SHUTDOWN, use that message before picking from the 1220*7c478bd9Sstevel@tonic-gate * queue again. 1221*7c478bd9Sstevel@tonic-gate */ 1222*7c478bd9Sstevel@tonic-gate mp = save_mp; 1223*7c478bd9Sstevel@tonic-gate save_mp = NULL; 1224*7c478bd9Sstevel@tonic-gate } else { 1225*7c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&inputq, (void **)&mp, 0); 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp)) 1228*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): msg dispatcher dequeued %p from " 1229*7c478bd9Sstevel@tonic-gate "queue %p\n", mythreadno, mp, &inputq); 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate /* 1232*7c478bd9Sstevel@tonic-gate * In most cases, if the message traffic is low, logmsg() wakes 1233*7c478bd9Sstevel@tonic-gate * up when it receives the SHUTDOWN msg, and will sleep until 1234*7c478bd9Sstevel@tonic-gate * HUP process is complete. However, if the inputq is too 1235*7c478bd9Sstevel@tonic-gate * long, logmsg() may not receive SHUTDOWN before reconfigure() 1236*7c478bd9Sstevel@tonic-gate * releases the logger fds, filed and logit threads. That, in 1237*7c478bd9Sstevel@tonic-gate * turn, will cause logmsg to refer to invalid fileds. 1238*7c478bd9Sstevel@tonic-gate * 1239*7c478bd9Sstevel@tonic-gate * logmsg() needs to respond to the SHUTDOWN message within 1240*7c478bd9Sstevel@tonic-gate * LOOP_INTERVAL seconds when reconfigure() enqueues it. It 1241*7c478bd9Sstevel@tonic-gate * does so in most cases. When it does not respond in time, 1242*7c478bd9Sstevel@tonic-gate * logmsg() needs to be in suspended state immediately, since 1243*7c478bd9Sstevel@tonic-gate * filed may have been invalidated. reconfigure() will set the 1244*7c478bd9Sstevel@tonic-gate * HUP_SUSP_LOGMSG_REQD bit in hup_state and wait another 1245*7c478bd9Sstevel@tonic-gate * LOOP_INTERVAL seconds before proceeding. 1246*7c478bd9Sstevel@tonic-gate * 1247*7c478bd9Sstevel@tonic-gate * When HUP_SUSP_LOGMSG_REQD is set, we will create a fake 1248*7c478bd9Sstevel@tonic-gate * SHUTDOWN message, and dispatch it to the various logit 1249*7c478bd9Sstevel@tonic-gate * threads, and logmsg() itself will suspend. In order to 1250*7c478bd9Sstevel@tonic-gate * ignore the real SHUTDOWN which will arrive later, we keep a 1251*7c478bd9Sstevel@tonic-gate * counter (skip_shutdown) and decrement it when the SHUTDOWN 1252*7c478bd9Sstevel@tonic-gate * message arrives. 1253*7c478bd9Sstevel@tonic-gate */ 1254*7c478bd9Sstevel@tonic-gate if ((hup_state & HUP_SUSP_LOGMSG_REQD) && 1255*7c478bd9Sstevel@tonic-gate (mp->flags & SHUTDOWN) == 0) { 1256*7c478bd9Sstevel@tonic-gate DPRINT1(3, "logmsg(%u): suspend request\n", 1257*7c478bd9Sstevel@tonic-gate mythreadno); 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate save_mp = mp; 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate /* create a fake SHUTDOWN msg */ 1262*7c478bd9Sstevel@tonic-gate if ((mp = new_msg()) == NULL) { 1263*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1264*7c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 1265*7c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, 1266*7c478bd9Sstevel@tonic-gate "unable to shutdown " 1267*7c478bd9Sstevel@tonic-gate "logger thread"); 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate continue; 1270*7c478bd9Sstevel@tonic-gate } 1271*7c478bd9Sstevel@tonic-gate mp->flags = SHUTDOWN; 1272*7c478bd9Sstevel@tonic-gate mp->hlp = &LocalHostName; 1273*7c478bd9Sstevel@tonic-gate fake_shutdown = 1; 1274*7c478bd9Sstevel@tonic-gate skip_shutdown++; 1275*7c478bd9Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): pending SHUTDOWN %d\n", 1276*7c478bd9Sstevel@tonic-gate mythreadno, skip_shutdown); 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate /* 1280*7c478bd9Sstevel@tonic-gate * is it a shutdown or flush message ? 1281*7c478bd9Sstevel@tonic-gate */ 1282*7c478bd9Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) || (mp->flags & FLUSHMSG)) { 1283*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&mp->msg_mutex); 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) && 1286*7c478bd9Sstevel@tonic-gate !fake_shutdown && skip_shutdown > 0) { 1287*7c478bd9Sstevel@tonic-gate skip_shutdown--; 1288*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1289*7c478bd9Sstevel@tonic-gate free_msg(mp); 1290*7c478bd9Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): released late " 1291*7c478bd9Sstevel@tonic-gate "arrived SHUTDOWN. pending %d\n", 1292*7c478bd9Sstevel@tonic-gate mythreadno, skip_shutdown); 1293*7c478bd9Sstevel@tonic-gate continue; 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 1297*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&f->filed_mutex); 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) { 1300*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1301*7c478bd9Sstevel@tonic-gate continue; 1302*7c478bd9Sstevel@tonic-gate } 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate f->f_queue_count++; 1305*7c478bd9Sstevel@tonic-gate mp->refcnt++; 1306*7c478bd9Sstevel@tonic-gate 1307*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue, 1308*7c478bd9Sstevel@tonic-gate (void *)mp) == -1) { 1309*7c478bd9Sstevel@tonic-gate f->f_queue_count--; 1310*7c478bd9Sstevel@tonic-gate mp->refcnt--; 1311*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1312*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 1315*7c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, 1316*7c478bd9Sstevel@tonic-gate "unable to shutdown " 1317*7c478bd9Sstevel@tonic-gate "logger thread"); 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate continue; 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p " 1323*7c478bd9Sstevel@tonic-gate "on queue %p\n", mythreadno, mp, 1324*7c478bd9Sstevel@tonic-gate &f->f_queue); 1325*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1326*7c478bd9Sstevel@tonic-gate } 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate /* 1329*7c478bd9Sstevel@tonic-gate * flags value needs to be saved because mp may 1330*7c478bd9Sstevel@tonic-gate * have been freed before SHUTDOWN test below. 1331*7c478bd9Sstevel@tonic-gate */ 1332*7c478bd9Sstevel@tonic-gate flags = mp->flags; 1333*7c478bd9Sstevel@tonic-gate refcnt = mp->refcnt; 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1336*7c478bd9Sstevel@tonic-gate if (refcnt == 0) 1337*7c478bd9Sstevel@tonic-gate free_msg(mp); 1338*7c478bd9Sstevel@tonic-gate 1339*7c478bd9Sstevel@tonic-gate if (flags & SHUTDOWN) { 1340*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&hup_lock); 1341*7c478bd9Sstevel@tonic-gate while (hup_state != HUP_COMPLETED) { 1342*7c478bd9Sstevel@tonic-gate hup_state |= HUP_LOGMSG_SUSPENDED; 1343*7c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&hup_done, 1344*7c478bd9Sstevel@tonic-gate &hup_lock); 1345*7c478bd9Sstevel@tonic-gate hup_state &= ~HUP_LOGMSG_SUSPENDED; 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate hup_state = HUP_ACCEPTABLE; 1348*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hup_lock); 1349*7c478bd9Sstevel@tonic-gate fake_shutdown = 0; 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate continue; 1352*7c478bd9Sstevel@tonic-gate } 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate /* 1355*7c478bd9Sstevel@tonic-gate * Check to see if msg looks non-standard. 1356*7c478bd9Sstevel@tonic-gate */ 1357*7c478bd9Sstevel@tonic-gate if ((int)strlen(mp->msg) < 16 || mp->msg[3] != ' ' || 1358*7c478bd9Sstevel@tonic-gate mp->msg[6] != ' ' || mp->msg[9] != ':' || 1359*7c478bd9Sstevel@tonic-gate mp->msg[12] != ':' || mp->msg[15] != ' ') 1360*7c478bd9Sstevel@tonic-gate mp->flags |= ADDDATE; 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate /* extract facility and priority level */ 1363*7c478bd9Sstevel@tonic-gate fac = (mp->pri & LOG_FACMASK) >> 3; 1364*7c478bd9Sstevel@tonic-gate if (mp->flags & MARK) 1365*7c478bd9Sstevel@tonic-gate fac = LOG_NFACILITIES; 1366*7c478bd9Sstevel@tonic-gate prilev = mp->pri & LOG_PRIMASK; 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate DPRINT3(3, "logmsg(%u): fac = %d, pri = %d\n", 1369*7c478bd9Sstevel@tonic-gate mythreadno, fac, prilev); 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate /* 1372*7c478bd9Sstevel@tonic-gate * Because different devices log at different speeds, 1373*7c478bd9Sstevel@tonic-gate * it's important to hold the mutex for the current 1374*7c478bd9Sstevel@tonic-gate * message until it's been enqueued to all log files, 1375*7c478bd9Sstevel@tonic-gate * so the reference count is accurate before any 1376*7c478bd9Sstevel@tonic-gate * of the log threads can decrement it. 1377*7c478bd9Sstevel@tonic-gate */ 1378*7c478bd9Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mp)) 1379*7c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW) 1380*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&mp->msg_mutex); 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 1383*7c478bd9Sstevel@tonic-gate /* skip messages that are incorrect priority */ 1384*7c478bd9Sstevel@tonic-gate if (f->f_pmask[fac] < (unsigned)prilev || 1385*7c478bd9Sstevel@tonic-gate f->f_pmask[fac] == NOPRI) 1386*7c478bd9Sstevel@tonic-gate continue; 1387*7c478bd9Sstevel@tonic-gate if (f->f_queue_count > Q_HIGHWATER_MARK) { 1388*7c478bd9Sstevel@tonic-gate DPRINT4(5, "logmsg(%u): Dropping message " 1389*7c478bd9Sstevel@tonic-gate "%p on file %p, count = %d\n", 1390*7c478bd9Sstevel@tonic-gate mythreadno, mp, f, 1391*7c478bd9Sstevel@tonic-gate f->f_queue_count); 1392*7c478bd9Sstevel@tonic-gate continue; 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate /* 1396*7c478bd9Sstevel@tonic-gate * Need to grab filed_mutex before testing the f_type. 1397*7c478bd9Sstevel@tonic-gate * Otherwise logit() may set F_UNUSED after the test 1398*7c478bd9Sstevel@tonic-gate * below, and start pulling out the pending messages. 1399*7c478bd9Sstevel@tonic-gate */ 1400*7c478bd9Sstevel@tonic-gate 1401*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&f->filed_mutex); 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED || 1404*7c478bd9Sstevel@tonic-gate (f->f_type == F_FILE && (mp->flags & IGN_FILE)) || 1405*7c478bd9Sstevel@tonic-gate (f->f_type == F_CONSOLE && 1406*7c478bd9Sstevel@tonic-gate (mp->flags & IGN_CONS))) { 1407*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1408*7c478bd9Sstevel@tonic-gate continue; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate f->f_queue_count++; 1412*7c478bd9Sstevel@tonic-gate mp->refcnt++; 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue, (void *)mp) == -1) { 1415*7c478bd9Sstevel@tonic-gate f->f_queue_count--; 1416*7c478bd9Sstevel@tonic-gate mp->refcnt--; 1417*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1418*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1419*7c478bd9Sstevel@tonic-gate continue; 1420*7c478bd9Sstevel@tonic-gate } 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p on queue " 1423*7c478bd9Sstevel@tonic-gate "%p\n", mythreadno, mp, &f->f_queue); 1424*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate refcnt = mp->refcnt; 1427*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1428*7c478bd9Sstevel@tonic-gate if (refcnt == 0) 1429*7c478bd9Sstevel@tonic-gate free_msg(mp); 1430*7c478bd9Sstevel@tonic-gate } 1431*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1432*7c478bd9Sstevel@tonic-gate return (NULL); 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate /* 1436*7c478bd9Sstevel@tonic-gate * function to actually write the log message to the selected file. 1437*7c478bd9Sstevel@tonic-gate * each file has a logger thread that runs this routine. The function 1438*7c478bd9Sstevel@tonic-gate * is called with a pointer to its file structure. 1439*7c478bd9Sstevel@tonic-gate */ 1440*7c478bd9Sstevel@tonic-gate static void * 1441*7c478bd9Sstevel@tonic-gate logit(void *ap) 1442*7c478bd9Sstevel@tonic-gate { 1443*7c478bd9Sstevel@tonic-gate struct filed *f = ap; 1444*7c478bd9Sstevel@tonic-gate log_message_t *mp; 1445*7c478bd9Sstevel@tonic-gate int forwardingloop = 0; 1446*7c478bd9Sstevel@tonic-gate char *errmsg = "logit(%u): %s to %s forwarding loop detected\n"; 1447*7c478bd9Sstevel@tonic-gate int i, currofst, prevofst, refcnt; 1448*7c478bd9Sstevel@tonic-gate host_list_t *hlp; 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate assert(f != NULL); 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate DPRINT4(5, "logit(%u): logger started for \"%s\" (queue %p, filed " 1453*7c478bd9Sstevel@tonic-gate "%p)\n", f->f_thread, f->f_un.f_fname, &f->f_queue, f); 1454*7c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW); 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate while (f->f_type != F_UNUSED) { 1457*7c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0); 1458*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue " 1459*7c478bd9Sstevel@tonic-gate "%p\n", 1460*7c478bd9Sstevel@tonic-gate f->f_thread, mp, &f->f_queue); 1461*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&f->filed_mutex); 1462*7c478bd9Sstevel@tonic-gate assert(f->f_queue_count > 0); 1463*7c478bd9Sstevel@tonic-gate f->f_queue_count--; 1464*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1465*7c478bd9Sstevel@tonic-gate assert(mp->refcnt > 0); 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate /* 1468*7c478bd9Sstevel@tonic-gate * is it a shutdown message ? 1469*7c478bd9Sstevel@tonic-gate */ 1470*7c478bd9Sstevel@tonic-gate if (mp->flags & SHUTDOWN) { 1471*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&mp->msg_mutex); 1472*7c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 1473*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1474*7c478bd9Sstevel@tonic-gate if (refcnt == 0) 1475*7c478bd9Sstevel@tonic-gate free_msg(mp); 1476*7c478bd9Sstevel@tonic-gate break; 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate /* 1480*7c478bd9Sstevel@tonic-gate * Is it a logsync message? 1481*7c478bd9Sstevel@tonic-gate */ 1482*7c478bd9Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | LOGSYNC)) == 1483*7c478bd9Sstevel@tonic-gate (FLUSHMSG | LOGSYNC)) { 1484*7c478bd9Sstevel@tonic-gate if (f->f_type != F_FILE) 1485*7c478bd9Sstevel@tonic-gate goto out; /* nothing to do */ 1486*7c478bd9Sstevel@tonic-gate (void) close(f->f_file); 1487*7c478bd9Sstevel@tonic-gate f->f_file = open64(f->f_un.f_fname, 1488*7c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY); 1489*7c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 1490*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 1491*7c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 1492*7c478bd9Sstevel@tonic-gate f->f_stat.errs++; 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate goto out; 1495*7c478bd9Sstevel@tonic-gate } 1496*7c478bd9Sstevel@tonic-gate 1497*7c478bd9Sstevel@tonic-gate /* 1498*7c478bd9Sstevel@tonic-gate * If the message flags include both flush and sync, 1499*7c478bd9Sstevel@tonic-gate * then just sync the file out to disk if appropriate. 1500*7c478bd9Sstevel@tonic-gate */ 1501*7c478bd9Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | SYNC_FILE)) == 1502*7c478bd9Sstevel@tonic-gate (FLUSHMSG | SYNC_FILE)) { 1503*7c478bd9Sstevel@tonic-gate if (f->f_type == F_FILE) { 1504*7c478bd9Sstevel@tonic-gate DPRINT2(5, "logit(%u): got FLUSH|SYNC " 1505*7c478bd9Sstevel@tonic-gate "for filed %p\n", f->f_thread, 1506*7c478bd9Sstevel@tonic-gate f); 1507*7c478bd9Sstevel@tonic-gate (void) fsync(f->f_file); 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate goto out; 1510*7c478bd9Sstevel@tonic-gate } 1511*7c478bd9Sstevel@tonic-gate 1512*7c478bd9Sstevel@tonic-gate /* 1513*7c478bd9Sstevel@tonic-gate * Otherwise if it's a standard flush message, write 1514*7c478bd9Sstevel@tonic-gate * out any saved messages to the file. 1515*7c478bd9Sstevel@tonic-gate */ 1516*7c478bd9Sstevel@tonic-gate if ((mp->flags & FLUSHMSG) && (f->f_prevcount > 0)) { 1517*7c478bd9Sstevel@tonic-gate set_flush_msg(f); 1518*7c478bd9Sstevel@tonic-gate writemsg(SAVED, f); 1519*7c478bd9Sstevel@tonic-gate goto out; 1520*7c478bd9Sstevel@tonic-gate } 1521*7c478bd9Sstevel@tonic-gate 1522*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_current.msg, mp->msg, MAXLINE+1); 1523*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_current.host, mp->hlp->hl_hosts[0], 1524*7c478bd9Sstevel@tonic-gate SYS_NMLN); 1525*7c478bd9Sstevel@tonic-gate f->f_current.pri = mp->pri; 1526*7c478bd9Sstevel@tonic-gate f->f_current.flags = mp->flags; 1527*7c478bd9Sstevel@tonic-gate f->f_current.time = mp->ts; 1528*7c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 1529*7c478bd9Sstevel@tonic-gate hlp = mp->hlp; 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16; 1532*7c478bd9Sstevel@tonic-gate currofst = (f->f_current.flags & ADDDATE) ? 0 : 16; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate if (f->f_type == F_FORW) { 1535*7c478bd9Sstevel@tonic-gate /* 1536*7c478bd9Sstevel@tonic-gate * Should not forward MARK messages, as they are 1537*7c478bd9Sstevel@tonic-gate * not defined outside of the current system. 1538*7c478bd9Sstevel@tonic-gate */ 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate if (mp->flags & MARK) { 1541*7c478bd9Sstevel@tonic-gate DPRINT1(1, "logit(%u): cannot forward " 1542*7c478bd9Sstevel@tonic-gate "Mark\n", f->f_thread); 1543*7c478bd9Sstevel@tonic-gate goto out; 1544*7c478bd9Sstevel@tonic-gate } 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate /* 1547*7c478bd9Sstevel@tonic-gate * can not forward message if we do 1548*7c478bd9Sstevel@tonic-gate * not have a host to forward to 1549*7c478bd9Sstevel@tonic-gate */ 1550*7c478bd9Sstevel@tonic-gate if (hlp == (host_list_t *)NULL) 1551*7c478bd9Sstevel@tonic-gate goto out; 1552*7c478bd9Sstevel@tonic-gate /* 1553*7c478bd9Sstevel@tonic-gate * a forwarding loop is created on machines 1554*7c478bd9Sstevel@tonic-gate * with multiple interfaces because the 1555*7c478bd9Sstevel@tonic-gate * network address of the sender is different 1556*7c478bd9Sstevel@tonic-gate * to the receiver even though it is the 1557*7c478bd9Sstevel@tonic-gate * same machine. Instead, if the 1558*7c478bd9Sstevel@tonic-gate * hostname the source and target are 1559*7c478bd9Sstevel@tonic-gate * the same the message if thrown away 1560*7c478bd9Sstevel@tonic-gate */ 1561*7c478bd9Sstevel@tonic-gate forwardingloop = 0; 1562*7c478bd9Sstevel@tonic-gate for (i = 0; i < hlp->hl_cnt; i++) { 1563*7c478bd9Sstevel@tonic-gate if (strcmp(hlp->hl_hosts[i], 1564*7c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname) == 0) { 1565*7c478bd9Sstevel@tonic-gate DPRINT3(1, errmsg, f->f_thread, 1566*7c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname, 1567*7c478bd9Sstevel@tonic-gate hlp->hl_hosts[i]); 1568*7c478bd9Sstevel@tonic-gate forwardingloop = 1; 1569*7c478bd9Sstevel@tonic-gate break; 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate if (forwardingloop == 1) { 1574*7c478bd9Sstevel@tonic-gate f->f_stat.cantfwd++; 1575*7c478bd9Sstevel@tonic-gate goto out; 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate } 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate f->f_msgflag |= CURRENT_VALID; 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate /* check for dup message */ 1582*7c478bd9Sstevel@tonic-gate if (f->f_type != F_FORW && 1583*7c478bd9Sstevel@tonic-gate (f->f_msgflag & OLD_VALID) && 1584*7c478bd9Sstevel@tonic-gate prevofst == currofst && 1585*7c478bd9Sstevel@tonic-gate (strcmp(f->f_prevmsg.msg + prevofst, 1586*7c478bd9Sstevel@tonic-gate f->f_current.msg + currofst) == 0) && 1587*7c478bd9Sstevel@tonic-gate (strcmp(f->f_prevmsg.host, 1588*7c478bd9Sstevel@tonic-gate f->f_current.host) == 0)) { 1589*7c478bd9Sstevel@tonic-gate /* a dup */ 1590*7c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is dup - %p\n", 1591*7c478bd9Sstevel@tonic-gate f->f_thread, mp); 1592*7c478bd9Sstevel@tonic-gate if (currofst == 16) { 1593*7c478bd9Sstevel@tonic-gate (void) strncpy(f->f_prevmsg.msg, 1594*7c478bd9Sstevel@tonic-gate f->f_current.msg, 15); /* update time */ 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate f->f_prevcount++; 1597*7c478bd9Sstevel@tonic-gate f->f_stat.dups++; 1598*7c478bd9Sstevel@tonic-gate f->f_stat.total++; 1599*7c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 1600*7c478bd9Sstevel@tonic-gate } else { 1601*7c478bd9Sstevel@tonic-gate /* new: mark or prior dups exist */ 1602*7c478bd9Sstevel@tonic-gate if (f->f_current.flags & MARK || f->f_prevcount > 0) { 1603*7c478bd9Sstevel@tonic-gate if (f->f_prevcount > 0 && f->f_type != F_FORW) { 1604*7c478bd9Sstevel@tonic-gate set_flush_msg(f); 1605*7c478bd9Sstevel@tonic-gate if (f->f_msgflag & OLD_VALID) { 1606*7c478bd9Sstevel@tonic-gate writemsg(SAVED, f); 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate } 1609*7c478bd9Sstevel@tonic-gate if (f->f_msgflag & CURRENT_VALID) 1610*7c478bd9Sstevel@tonic-gate writemsg(CURRENT, f); 1611*7c478bd9Sstevel@tonic-gate if (!(mp->flags & NOCOPY)) 1612*7c478bd9Sstevel@tonic-gate copy_msg(f); 1613*7c478bd9Sstevel@tonic-gate if (f->f_current.flags & MARK) { 1614*7c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is " 1615*7c478bd9Sstevel@tonic-gate "mark - %p)\n", 1616*7c478bd9Sstevel@tonic-gate f->f_thread, mp); 1617*7c478bd9Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID; 1618*7c478bd9Sstevel@tonic-gate } else { 1619*7c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): saving " 1620*7c478bd9Sstevel@tonic-gate "message - %p\n", 1621*7c478bd9Sstevel@tonic-gate f->f_thread, mp); 1622*7c478bd9Sstevel@tonic-gate } 1623*7c478bd9Sstevel@tonic-gate f->f_stat.total++; 1624*7c478bd9Sstevel@tonic-gate } else { /* new message */ 1625*7c478bd9Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is new " 1626*7c478bd9Sstevel@tonic-gate "- %p\n", f->f_thread, mp); 1627*7c478bd9Sstevel@tonic-gate writemsg(CURRENT, f); 1628*7c478bd9Sstevel@tonic-gate if (!(mp->flags & NOCOPY)) 1629*7c478bd9Sstevel@tonic-gate copy_msg(f); 1630*7c478bd9Sstevel@tonic-gate f->f_stat.total++; 1631*7c478bd9Sstevel@tonic-gate } 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate /* 1634*7c478bd9Sstevel@tonic-gate * if message refcnt goes to zero after we decrement 1635*7c478bd9Sstevel@tonic-gate * it here, we are the last consumer of the message, 1636*7c478bd9Sstevel@tonic-gate * and we should free it. We need to hold the lock 1637*7c478bd9Sstevel@tonic-gate * between decrementing the count and checking for 1638*7c478bd9Sstevel@tonic-gate * zero so another thread doesn't beat us to it. 1639*7c478bd9Sstevel@tonic-gate */ 1640*7c478bd9Sstevel@tonic-gate out: 1641*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&mp->msg_mutex); 1642*7c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 1643*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1644*7c478bd9Sstevel@tonic-gate if (refcnt == 0) 1645*7c478bd9Sstevel@tonic-gate free_msg(mp); 1646*7c478bd9Sstevel@tonic-gate } 1647*7c478bd9Sstevel@tonic-gate /* register our exit */ 1648*7c478bd9Sstevel@tonic-gate 1649*7c478bd9Sstevel@tonic-gate /* 1650*7c478bd9Sstevel@tonic-gate * Pull out all pending messages, if they exist. 1651*7c478bd9Sstevel@tonic-gate */ 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&f->filed_mutex); 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate while (f->f_queue_count > 0) { 1656*7c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0); 1657*7c478bd9Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue " 1658*7c478bd9Sstevel@tonic-gate "%p\n", 1659*7c478bd9Sstevel@tonic-gate f->f_thread, mp, &f->f_queue); 1660*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&mp->msg_mutex); 1661*7c478bd9Sstevel@tonic-gate refcnt = --mp->refcnt; 1662*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&mp->msg_mutex); 1663*7c478bd9Sstevel@tonic-gate if (refcnt == 0) 1664*7c478bd9Sstevel@tonic-gate free_msg(mp); 1665*7c478bd9Sstevel@tonic-gate f->f_queue_count--; 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate 1668*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&f->filed_mutex); 1669*7c478bd9Sstevel@tonic-gate 1670*7c478bd9Sstevel@tonic-gate if (f->f_type != F_USERS && f->f_type != F_WALL && 1671*7c478bd9Sstevel@tonic-gate f->f_type != F_UNUSED) { 1672*7c478bd9Sstevel@tonic-gate if (f->f_type == F_FORW) 1673*7c478bd9Sstevel@tonic-gate (void) t_close(f->f_file); 1674*7c478bd9Sstevel@tonic-gate else 1675*7c478bd9Sstevel@tonic-gate (void) close(f->f_file); 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate /* 1679*7c478bd9Sstevel@tonic-gate * Since f_type may have been changed before this point, we need 1680*7c478bd9Sstevel@tonic-gate * to test orig_type. 1681*7c478bd9Sstevel@tonic-gate */ 1682*7c478bd9Sstevel@tonic-gate if (f->f_orig_type == F_FORW) { 1683*7c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 1687*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&cft); 1688*7c478bd9Sstevel@tonic-gate --conf_threads; 1689*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&cft); 1690*7c478bd9Sstevel@tonic-gate DPRINT1(5, "logit(%u): logging thread exited\n", f->f_thread); 1691*7c478bd9Sstevel@tonic-gate return (NULL); 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate /* 1695*7c478bd9Sstevel@tonic-gate * change the previous message to a flush message, stating how 1696*7c478bd9Sstevel@tonic-gate * many repeats occurred since the last flush 1697*7c478bd9Sstevel@tonic-gate */ 1698*7c478bd9Sstevel@tonic-gate static void 1699*7c478bd9Sstevel@tonic-gate set_flush_msg(struct filed *f) 1700*7c478bd9Sstevel@tonic-gate { 1701*7c478bd9Sstevel@tonic-gate char tbuf[10]; 1702*7c478bd9Sstevel@tonic-gate int prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16; 1703*7c478bd9Sstevel@tonic-gate 1704*7c478bd9Sstevel@tonic-gate if (f->f_prevcount == 1) 1705*7c478bd9Sstevel@tonic-gate (void) strncpy(tbuf, "time", sizeof (tbuf)); 1706*7c478bd9Sstevel@tonic-gate else 1707*7c478bd9Sstevel@tonic-gate (void) strncpy(tbuf, "times", sizeof (tbuf)); 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate (void) sprintf(f->f_prevmsg.msg+prevofst, 1710*7c478bd9Sstevel@tonic-gate "last message repeated %d %s", f->f_prevcount, tbuf); 1711*7c478bd9Sstevel@tonic-gate f->f_prevcount = 0; 1712*7c478bd9Sstevel@tonic-gate f->f_msgflag |= OLD_VALID; 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate /* 1717*7c478bd9Sstevel@tonic-gate * the actual writing of the message is broken into a separate function 1718*7c478bd9Sstevel@tonic-gate * because each file has a current and saved message associated with 1719*7c478bd9Sstevel@tonic-gate * it (for duplicate message detection). It is necessary to be able 1720*7c478bd9Sstevel@tonic-gate * to write either the saved message or the current message. 1721*7c478bd9Sstevel@tonic-gate */ 1722*7c478bd9Sstevel@tonic-gate static void 1723*7c478bd9Sstevel@tonic-gate writemsg(int selection, struct filed *f) 1724*7c478bd9Sstevel@tonic-gate { 1725*7c478bd9Sstevel@tonic-gate char *cp, *p; 1726*7c478bd9Sstevel@tonic-gate int pri; 1727*7c478bd9Sstevel@tonic-gate int flags; 1728*7c478bd9Sstevel@tonic-gate int l; 1729*7c478bd9Sstevel@tonic-gate time_t ts; 1730*7c478bd9Sstevel@tonic-gate struct t_unitdata ud; 1731*7c478bd9Sstevel@tonic-gate char *eomp, *eomp2, *from, *text, *msg; 1732*7c478bd9Sstevel@tonic-gate char line[MAXLINE*2]; 1733*7c478bd9Sstevel@tonic-gate char head[MAXLINE+1]; 1734*7c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE+1]; 1735*7c478bd9Sstevel@tonic-gate char cbuf[30]; 1736*7c478bd9Sstevel@tonic-gate char *filtered; 1737*7c478bd9Sstevel@tonic-gate char *msgid_start, *msgid_end; 1738*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1739*7c478bd9Sstevel@tonic-gate size_t hlen, filter_len; 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate if (Debug) { 1742*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1743*7c478bd9Sstevel@tonic-gate } 1744*7c478bd9Sstevel@tonic-gate 1745*7c478bd9Sstevel@tonic-gate switch (selection) { 1746*7c478bd9Sstevel@tonic-gate default: 1747*7c478bd9Sstevel@tonic-gate case CURRENT: /* print current message */ 1748*7c478bd9Sstevel@tonic-gate msg = f->f_current.msg; 1749*7c478bd9Sstevel@tonic-gate from = f->f_current.host; 1750*7c478bd9Sstevel@tonic-gate pri = f->f_current.pri; 1751*7c478bd9Sstevel@tonic-gate flags = f->f_current.flags; 1752*7c478bd9Sstevel@tonic-gate ts = f->f_current.time; 1753*7c478bd9Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID; 1754*7c478bd9Sstevel@tonic-gate break; 1755*7c478bd9Sstevel@tonic-gate case SAVED: /* print saved message */ 1756*7c478bd9Sstevel@tonic-gate msg = f->f_prevmsg.msg; 1757*7c478bd9Sstevel@tonic-gate from = f->f_prevmsg.host; 1758*7c478bd9Sstevel@tonic-gate pri = f->f_prevmsg.pri; 1759*7c478bd9Sstevel@tonic-gate flags = f->f_prevmsg.flags; 1760*7c478bd9Sstevel@tonic-gate ts = f->f_prevmsg.time; 1761*7c478bd9Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID; 1762*7c478bd9Sstevel@tonic-gate break; 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate if (msg[0] == '\0') 1766*7c478bd9Sstevel@tonic-gate return; 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate cp = line; 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate if (flags & ADDDATE) 1771*7c478bd9Sstevel@tonic-gate (void) strncpy(cp, ctime_r(&ts, cbuf) + 4, 15); 1772*7c478bd9Sstevel@tonic-gate else 1773*7c478bd9Sstevel@tonic-gate (void) strncpy(cp, msg, 15); 1774*7c478bd9Sstevel@tonic-gate 1775*7c478bd9Sstevel@tonic-gate line[15] = '\0'; 1776*7c478bd9Sstevel@tonic-gate (void) strcat(cp, " "); 1777*7c478bd9Sstevel@tonic-gate (void) strcat(cp, from); 1778*7c478bd9Sstevel@tonic-gate (void) strcat(cp, " "); 1779*7c478bd9Sstevel@tonic-gate text = cp + strlen(cp); 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate if (flags & ADDDATE) 1782*7c478bd9Sstevel@tonic-gate (void) strcat(cp, msg); 1783*7c478bd9Sstevel@tonic-gate else 1784*7c478bd9Sstevel@tonic-gate (void) strcat(cp, msg+16); 1785*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text); 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate errno = 0; 1788*7c478bd9Sstevel@tonic-gate t_errno = 0; 1789*7c478bd9Sstevel@tonic-gate switch (f->f_type) { 1790*7c478bd9Sstevel@tonic-gate case F_UNUSED: 1791*7c478bd9Sstevel@tonic-gate DPRINT1(1, "writemsg(%u): UNUSED\n", mythreadno); 1792*7c478bd9Sstevel@tonic-gate break; 1793*7c478bd9Sstevel@tonic-gate case F_FORW: 1794*7c478bd9Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n", 1795*7c478bd9Sstevel@tonic-gate mythreadno, msg, TypeNames[f->f_type], 1796*7c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_hname); 1797*7c478bd9Sstevel@tonic-gate 1798*7c478bd9Sstevel@tonic-gate hlen = snprintf(head, sizeof (head), 1799*7c478bd9Sstevel@tonic-gate "<%d>%.15s ", pri, cp); 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): head = \"%s\"\n", mythreadno, head); 1802*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): hlen = %d\n", mythreadno, hlen); 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate l = strlen(text); 1805*7c478bd9Sstevel@tonic-gate p = text; 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text); 1808*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(text) = %d\n", mythreadno, l); 1809*7c478bd9Sstevel@tonic-gate 1810*7c478bd9Sstevel@tonic-gate (void) strncpy(tmpbuf, head, hlen); 1811*7c478bd9Sstevel@tonic-gate 1812*7c478bd9Sstevel@tonic-gate while (l > 0) { 1813*7c478bd9Sstevel@tonic-gate size_t len; 1814*7c478bd9Sstevel@tonic-gate 1815*7c478bd9Sstevel@tonic-gate len = copy_frwd(tmpbuf + hlen, sizeof (tmpbuf) - hlen, 1816*7c478bd9Sstevel@tonic-gate p, l); 1817*7c478bd9Sstevel@tonic-gate 1818*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): tmpbuf = \"%s\"\n", 1819*7c478bd9Sstevel@tonic-gate mythreadno, tmpbuf); 1820*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): len = %d\n", mythreadno, 1821*7c478bd9Sstevel@tonic-gate len); 1822*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(tmpbuf) = %d\n", 1823*7c478bd9Sstevel@tonic-gate mythreadno, strlen(tmpbuf)); 1824*7c478bd9Sstevel@tonic-gate 1825*7c478bd9Sstevel@tonic-gate ud.opt.buf = NULL; 1826*7c478bd9Sstevel@tonic-gate ud.opt.len = 0; 1827*7c478bd9Sstevel@tonic-gate ud.udata.buf = tmpbuf; 1828*7c478bd9Sstevel@tonic-gate ud.udata.len = len + hlen; 1829*7c478bd9Sstevel@tonic-gate ud.addr.maxlen = f->f_un.f_forw.f_addr.maxlen; 1830*7c478bd9Sstevel@tonic-gate ud.addr.buf = f->f_un.f_forw.f_addr.buf; 1831*7c478bd9Sstevel@tonic-gate ud.addr.len = f->f_un.f_forw.f_addr.len; 1832*7c478bd9Sstevel@tonic-gate if (t_sndudata(f->f_file, &ud) < 0) { 1833*7c478bd9Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) && 1834*7c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) { 1835*7c478bd9Sstevel@tonic-gate break; 1836*7c478bd9Sstevel@tonic-gate } 1837*7c478bd9Sstevel@tonic-gate (void) t_close(f->f_file); 1838*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 1839*7c478bd9Sstevel@tonic-gate logerror("t_sndudata"); 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate /* 1842*7c478bd9Sstevel@tonic-gate * Since it has already failed, it's not worth 1843*7c478bd9Sstevel@tonic-gate * continuing output from the middle of 1844*7c478bd9Sstevel@tonic-gate * message string. 1845*7c478bd9Sstevel@tonic-gate */ 1846*7c478bd9Sstevel@tonic-gate break; 1847*7c478bd9Sstevel@tonic-gate } 1848*7c478bd9Sstevel@tonic-gate p += len; 1849*7c478bd9Sstevel@tonic-gate l -= len; 1850*7c478bd9Sstevel@tonic-gate } 1851*7c478bd9Sstevel@tonic-gate break; 1852*7c478bd9Sstevel@tonic-gate case F_CONSOLE: 1853*7c478bd9Sstevel@tonic-gate case F_TTY: 1854*7c478bd9Sstevel@tonic-gate case F_FILE: 1855*7c478bd9Sstevel@tonic-gate case F_USERS: 1856*7c478bd9Sstevel@tonic-gate case F_WALL: 1857*7c478bd9Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n", 1858*7c478bd9Sstevel@tonic-gate mythreadno, msg, TypeNames[f->f_type], 1859*7c478bd9Sstevel@tonic-gate ((f->f_type == F_USERS) || (f->f_type == F_WALL)) ? 1860*7c478bd9Sstevel@tonic-gate "" : f->f_un.f_fname); 1861*7c478bd9Sstevel@tonic-gate /* 1862*7c478bd9Sstevel@tonic-gate * filter the string in preparation for writing it 1863*7c478bd9Sstevel@tonic-gate * save the original for possible forwarding. 1864*7c478bd9Sstevel@tonic-gate * In case every byte in cp is a control character, 1865*7c478bd9Sstevel@tonic-gate * allocates large enough buffer for filtered. 1866*7c478bd9Sstevel@tonic-gate */ 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate filter_len = strlen(cp) * 4 + 1; 1869*7c478bd9Sstevel@tonic-gate filtered = (char *)malloc(filter_len); 1870*7c478bd9Sstevel@tonic-gate if (!filtered) { 1871*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 1872*7c478bd9Sstevel@tonic-gate /* seems we can just return */ 1873*7c478bd9Sstevel@tonic-gate return; 1874*7c478bd9Sstevel@tonic-gate } 1875*7c478bd9Sstevel@tonic-gate DPRINT3(5, "writemsg(%u): " 1876*7c478bd9Sstevel@tonic-gate "filtered allocated (%p: %d bytes)\n", 1877*7c478bd9Sstevel@tonic-gate mythreadno, filtered, filter_len); 1878*7c478bd9Sstevel@tonic-gate /* -3 : we may add "\r\n" to ecomp(filtered) later */ 1879*7c478bd9Sstevel@tonic-gate filter_string(cp, filtered, filter_len - 3); 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(filtered) = %d\n", 1882*7c478bd9Sstevel@tonic-gate mythreadno, strlen(filtered)); 1883*7c478bd9Sstevel@tonic-gate /* 1884*7c478bd9Sstevel@tonic-gate * If we're writing to the console, strip out the message ID 1885*7c478bd9Sstevel@tonic-gate * to reduce visual clutter. 1886*7c478bd9Sstevel@tonic-gate */ 1887*7c478bd9Sstevel@tonic-gate if ((msgid_start = strstr(filtered, "[ID ")) != NULL && 1888*7c478bd9Sstevel@tonic-gate (msgid_end = strstr(msgid_start, "] ")) != NULL && 1889*7c478bd9Sstevel@tonic-gate f->f_type == F_CONSOLE) 1890*7c478bd9Sstevel@tonic-gate (void) strcpy(msgid_start, msgid_end + 2); 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate eomp = filtered + strlen(filtered); 1893*7c478bd9Sstevel@tonic-gate 1894*7c478bd9Sstevel@tonic-gate if ((f->f_type == F_USERS) || (f->f_type == F_WALL)) { 1895*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 1896*7c478bd9Sstevel@tonic-gate (void) strcat(eomp, "\r\n"); /*lint !e669*/ 1897*7c478bd9Sstevel@tonic-gate /* 1898*7c478bd9Sstevel@tonic-gate * Since wallmsg messes with utmpx we need 1899*7c478bd9Sstevel@tonic-gate * to guarantee single threadedness... 1900*7c478bd9Sstevel@tonic-gate */ 1901*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&wmp); 1902*7c478bd9Sstevel@tonic-gate wallmsg(f, from, filtered); 1903*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&wmp); 1904*7c478bd9Sstevel@tonic-gate 1905*7c478bd9Sstevel@tonic-gate /* 1906*7c478bd9Sstevel@tonic-gate * The contents of filtered have been copied 1907*7c478bd9Sstevel@tonic-gate * out to the struct walldev. We should free it here. 1908*7c478bd9Sstevel@tonic-gate */ 1909*7c478bd9Sstevel@tonic-gate 1910*7c478bd9Sstevel@tonic-gate free(filtered); 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate /* exiting the switch */ 1913*7c478bd9Sstevel@tonic-gate break; 1914*7c478bd9Sstevel@tonic-gate } else if (f->f_type != F_FILE) { 1915*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 1916*7c478bd9Sstevel@tonic-gate (void) strncpy(eomp, "\r\n", 3); /*lint !e669*/ 1917*7c478bd9Sstevel@tonic-gate } else { 1918*7c478bd9Sstevel@tonic-gate if ((eomp2 = strchr(filtered, '\r')) != NULL) { 1919*7c478bd9Sstevel@tonic-gate (void) strncpy(eomp2, "\n", 2); 1920*7c478bd9Sstevel@tonic-gate } else { 1921*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 1922*7c478bd9Sstevel@tonic-gate (void) strncpy(eomp, "\n", 2); /*lint !e669*/ 1923*7c478bd9Sstevel@tonic-gate } 1924*7c478bd9Sstevel@tonic-gate } 1925*7c478bd9Sstevel@tonic-gate if (write(f->f_file, filtered, strlen(filtered)) < 0) { 1926*7c478bd9Sstevel@tonic-gate int e = errno; 1927*7c478bd9Sstevel@tonic-gate 1928*7c478bd9Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) && 1929*7c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) { 1930*7c478bd9Sstevel@tonic-gate free(filtered); 1931*7c478bd9Sstevel@tonic-gate break; 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate (void) close(f->f_file); 1934*7c478bd9Sstevel@tonic-gate /* 1935*7c478bd9Sstevel@tonic-gate * Check for EBADF on TTY's due 1936*7c478bd9Sstevel@tonic-gate * to vhangup() XXX 1937*7c478bd9Sstevel@tonic-gate */ 1938*7c478bd9Sstevel@tonic-gate if (e == EBADF && f->f_type != F_FILE) { 1939*7c478bd9Sstevel@tonic-gate f->f_file = open(f->f_un.f_fname, 1940*7c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY); 1941*7c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 1942*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 1943*7c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 1944*7c478bd9Sstevel@tonic-gate f->f_stat.errs++; 1945*7c478bd9Sstevel@tonic-gate } 1946*7c478bd9Sstevel@tonic-gate untty(); 1947*7c478bd9Sstevel@tonic-gate } else { 1948*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 1949*7c478bd9Sstevel@tonic-gate f->f_stat.errs++; 1950*7c478bd9Sstevel@tonic-gate errno = e; 1951*7c478bd9Sstevel@tonic-gate logerror(f->f_un.f_fname); 1952*7c478bd9Sstevel@tonic-gate } 1953*7c478bd9Sstevel@tonic-gate } else if (flags & SYNC_FILE) 1954*7c478bd9Sstevel@tonic-gate if (((pri & LOG_FACMASK) >> 3) == LOG_KERN) 1955*7c478bd9Sstevel@tonic-gate (void) fsync(f->f_file); 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): freeing filtered (%p)\n", 1958*7c478bd9Sstevel@tonic-gate mythreadno, filtered); 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate free(filtered); 1961*7c478bd9Sstevel@tonic-gate break; 1962*7c478bd9Sstevel@tonic-gate } 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate /* 1966*7c478bd9Sstevel@tonic-gate * WALLMSG -- Write a message to the world at large 1967*7c478bd9Sstevel@tonic-gate * 1968*7c478bd9Sstevel@tonic-gate * Write the specified message to either the entire 1969*7c478bd9Sstevel@tonic-gate * world, or a list of approved users. 1970*7c478bd9Sstevel@tonic-gate */ 1971*7c478bd9Sstevel@tonic-gate static void 1972*7c478bd9Sstevel@tonic-gate wallmsg(struct filed *f, char *from, char *msg) 1973*7c478bd9Sstevel@tonic-gate { 1974*7c478bd9Sstevel@tonic-gate int i; 1975*7c478bd9Sstevel@tonic-gate size_t len, clen; 1976*7c478bd9Sstevel@tonic-gate char *buf = NULL; 1977*7c478bd9Sstevel@tonic-gate struct utmpx *utxp; 1978*7c478bd9Sstevel@tonic-gate time_t now; 1979*7c478bd9Sstevel@tonic-gate char line[512], dev[100]; 1980*7c478bd9Sstevel@tonic-gate char cp[MAXLINE+1]; 1981*7c478bd9Sstevel@tonic-gate struct stat statbuf; 1982*7c478bd9Sstevel@tonic-gate walldev_t *w; 1983*7c478bd9Sstevel@tonic-gate char cbuf[30]; 1984*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 1985*7c478bd9Sstevel@tonic-gate 1986*7c478bd9Sstevel@tonic-gate if (Debug) { 1987*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate if (access(UTMPX_FILE, R_OK) != 0 || stat(UTMPX_FILE, &statbuf) != 0) { 1991*7c478bd9Sstevel@tonic-gate logerror(UTMPX_FILE); 1992*7c478bd9Sstevel@tonic-gate return; 1993*7c478bd9Sstevel@tonic-gate } else if (statbuf.st_uid != 0 || (statbuf.st_mode & 07777) != 0644) { 1994*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "%s %s", UTMPX_FILE, 1995*7c478bd9Sstevel@tonic-gate "not owned by root or not mode 644.\n" 1996*7c478bd9Sstevel@tonic-gate "This file must be owned by root " 1997*7c478bd9Sstevel@tonic-gate "and not writable by\n" 1998*7c478bd9Sstevel@tonic-gate "anyone other than root. This alert is being " 1999*7c478bd9Sstevel@tonic-gate "dropped because of\n" 2000*7c478bd9Sstevel@tonic-gate "this problem."); 2001*7c478bd9Sstevel@tonic-gate logerror(line); 2002*7c478bd9Sstevel@tonic-gate return; 2003*7c478bd9Sstevel@tonic-gate } 2004*7c478bd9Sstevel@tonic-gate 2005*7c478bd9Sstevel@tonic-gate if (f->f_type == F_WALL) { 2006*7c478bd9Sstevel@tonic-gate (void) time(&now); 2007*7c478bd9Sstevel@tonic-gate len = snprintf(line, sizeof (line), 2008*7c478bd9Sstevel@tonic-gate "\r\n\7Message from syslogd@%s " 2009*7c478bd9Sstevel@tonic-gate "at %.24s ...\r\n", from, ctime_r(&now, cbuf)); 2010*7c478bd9Sstevel@tonic-gate len += strlen(msg + 16); 2011*7c478bd9Sstevel@tonic-gate buf = (char *)malloc(len + 1); 2012*7c478bd9Sstevel@tonic-gate if (!buf) { 2013*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 2014*7c478bd9Sstevel@tonic-gate return; 2015*7c478bd9Sstevel@tonic-gate } 2016*7c478bd9Sstevel@tonic-gate DPRINT3(5, "wallmsg(%u): buf allocated (%p: %d bytes)\n", 2017*7c478bd9Sstevel@tonic-gate mythreadno, buf, len + 1); 2018*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, line); 2019*7c478bd9Sstevel@tonic-gate (void) strcat(buf, msg + 16); 2020*7c478bd9Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), buf, len); 2021*7c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n", 2022*7c478bd9Sstevel@tonic-gate mythreadno, clen); 2023*7c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): freeing buf (%p)\n", 2024*7c478bd9Sstevel@tonic-gate mythreadno, buf); 2025*7c478bd9Sstevel@tonic-gate free(buf); 2026*7c478bd9Sstevel@tonic-gate } else { 2027*7c478bd9Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), msg, strlen(msg)); 2028*7c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n", 2029*7c478bd9Sstevel@tonic-gate mythreadno, clen); 2030*7c478bd9Sstevel@tonic-gate } 2031*7c478bd9Sstevel@tonic-gate /* scan the user login file */ 2032*7c478bd9Sstevel@tonic-gate setutxent(); 2033*7c478bd9Sstevel@tonic-gate while ((utxp = getutxent()) != NULL) { 2034*7c478bd9Sstevel@tonic-gate /* is this slot used? */ 2035*7c478bd9Sstevel@tonic-gate if (utxp->ut_name[0] == '\0' || 2036*7c478bd9Sstevel@tonic-gate utxp->ut_line[0] == '\0' || 2037*7c478bd9Sstevel@tonic-gate utxp->ut_type != USER_PROCESS) 2038*7c478bd9Sstevel@tonic-gate continue; 2039*7c478bd9Sstevel@tonic-gate /* should we send the message to this user? */ 2040*7c478bd9Sstevel@tonic-gate if (f->f_type == F_USERS) { 2041*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES; i++) { 2042*7c478bd9Sstevel@tonic-gate if (!f->f_un.f_uname[i][0]) { 2043*7c478bd9Sstevel@tonic-gate i = MAXUNAMES; 2044*7c478bd9Sstevel@tonic-gate break; 2045*7c478bd9Sstevel@tonic-gate } 2046*7c478bd9Sstevel@tonic-gate if (strncmp(f->f_un.f_uname[i], 2047*7c478bd9Sstevel@tonic-gate utxp->ut_name, UNAMESZ) == 0) 2048*7c478bd9Sstevel@tonic-gate break; 2049*7c478bd9Sstevel@tonic-gate } 2050*7c478bd9Sstevel@tonic-gate if (i >= MAXUNAMES) 2051*7c478bd9Sstevel@tonic-gate continue; 2052*7c478bd9Sstevel@tonic-gate } 2053*7c478bd9Sstevel@tonic-gate 2054*7c478bd9Sstevel@tonic-gate /* compute the device name */ 2055*7c478bd9Sstevel@tonic-gate if (utxp->ut_line[0] == '/') { 2056*7c478bd9Sstevel@tonic-gate (void) strncpy(dev, utxp->ut_line, UDEVSZ); 2057*7c478bd9Sstevel@tonic-gate } else { 2058*7c478bd9Sstevel@tonic-gate (void) strcpy(dev, "/dev/"); 2059*7c478bd9Sstevel@tonic-gate (void) strncat(dev, utxp->ut_line, UDEVSZ); 2060*7c478bd9Sstevel@tonic-gate } 2061*7c478bd9Sstevel@tonic-gate DPRINT2(1, "wallmsg(%u): write to '%s'\n", mythreadno, 2062*7c478bd9Sstevel@tonic-gate dev); 2063*7c478bd9Sstevel@tonic-gate 2064*7c478bd9Sstevel@tonic-gate if ((w = malloc(sizeof (walldev_t))) != NULL) { 2065*7c478bd9Sstevel@tonic-gate int rc; 2066*7c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&w->thread_attr); 2067*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setdetachstate(&w->thread_attr, 2068*7c478bd9Sstevel@tonic-gate PTHREAD_CREATE_DETACHED); 2069*7c478bd9Sstevel@tonic-gate (void) strncpy(w->dev, dev, PATH_MAX); 2070*7c478bd9Sstevel@tonic-gate (void) strncpy(w->msg, cp, MAXLINE+1); 2071*7c478bd9Sstevel@tonic-gate (void) strncpy(w->ut_name, utxp->ut_name, 2072*7c478bd9Sstevel@tonic-gate sizeof (w->ut_name)); 2073*7c478bd9Sstevel@tonic-gate 2074*7c478bd9Sstevel@tonic-gate if ((rc = pthread_create(&w->thread, &w->thread_attr, 2075*7c478bd9Sstevel@tonic-gate writetodev, (void *) w)) != 0) { 2076*7c478bd9Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): wallmsg thread " 2077*7c478bd9Sstevel@tonic-gate "create failed rc = %d\n", 2078*7c478bd9Sstevel@tonic-gate mythreadno, rc); 2079*7c478bd9Sstevel@tonic-gate free(w); 2080*7c478bd9Sstevel@tonic-gate break; 2081*7c478bd9Sstevel@tonic-gate } 2082*7c478bd9Sstevel@tonic-gate } else { 2083*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message to user"); 2084*7c478bd9Sstevel@tonic-gate } 2085*7c478bd9Sstevel@tonic-gate } 2086*7c478bd9Sstevel@tonic-gate /* close the user login file */ 2087*7c478bd9Sstevel@tonic-gate endutxent(); 2088*7c478bd9Sstevel@tonic-gate } 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate /* 2091*7c478bd9Sstevel@tonic-gate * Each time we need to write to a tty device (a potentially expensive 2092*7c478bd9Sstevel@tonic-gate * or long-running operation) this routine gets called as a new 2093*7c478bd9Sstevel@tonic-gate * detached, unbound thread. This allows writes to many devices 2094*7c478bd9Sstevel@tonic-gate * to proceed nearly in parallel, without having to resort to 2095*7c478bd9Sstevel@tonic-gate * asynchronous I/O or forking. 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate static void * 2098*7c478bd9Sstevel@tonic-gate writetodev(void *ap) 2099*7c478bd9Sstevel@tonic-gate { 2100*7c478bd9Sstevel@tonic-gate walldev_t *w = ap; 2101*7c478bd9Sstevel@tonic-gate int ttyf; 2102*7c478bd9Sstevel@tonic-gate int len; 2103*7c478bd9Sstevel@tonic-gate struct stat statb; 2104*7c478bd9Sstevel@tonic-gate struct passwd pw, *pwp; 2105*7c478bd9Sstevel@tonic-gate char pwbuf[MAXLINE]; 2106*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2107*7c478bd9Sstevel@tonic-gate 2108*7c478bd9Sstevel@tonic-gate if (Debug) { 2109*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2110*7c478bd9Sstevel@tonic-gate } 2111*7c478bd9Sstevel@tonic-gate 2112*7c478bd9Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread started\n", 2113*7c478bd9Sstevel@tonic-gate mythreadno); 2114*7c478bd9Sstevel@tonic-gate 2115*7c478bd9Sstevel@tonic-gate len = strlen(w->msg); 2116*7c478bd9Sstevel@tonic-gate 2117*7c478bd9Sstevel@tonic-gate ttyf = open(w->dev, O_WRONLY|O_NOCTTY|O_NDELAY); 2118*7c478bd9Sstevel@tonic-gate if (ttyf >= 0) { 2119*7c478bd9Sstevel@tonic-gate if (fstat(ttyf, &statb) != 0) { 2120*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't stat '%s'\n", 2121*7c478bd9Sstevel@tonic-gate mythreadno, w->dev); 2122*7c478bd9Sstevel@tonic-gate errno = 0; 2123*7c478bd9Sstevel@tonic-gate logerror("Can't stat '%s'", w->dev); 2124*7c478bd9Sstevel@tonic-gate } else if (!(statb.st_mode & S_IWRITE)) { 2125*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't write to " 2126*7c478bd9Sstevel@tonic-gate "'%s'\n", mythreadno, w->dev); 2127*7c478bd9Sstevel@tonic-gate } else if (!isatty(ttyf)) { 2128*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): '%s' not a tty\n", 2129*7c478bd9Sstevel@tonic-gate mythreadno, w->dev); 2130*7c478bd9Sstevel@tonic-gate /* 2131*7c478bd9Sstevel@tonic-gate * We might hit dtremote here. Don't generate 2132*7c478bd9Sstevel@tonic-gate * error message. 2133*7c478bd9Sstevel@tonic-gate */ 2134*7c478bd9Sstevel@tonic-gate } else if (getpwuid_r(statb.st_uid, &pw, pwbuf, 2135*7c478bd9Sstevel@tonic-gate sizeof (pwbuf), &pwp) != 0) { 2136*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't determine owner " 2137*7c478bd9Sstevel@tonic-gate "of '%s'\n", mythreadno, w->dev); 2138*7c478bd9Sstevel@tonic-gate errno = 0; 2139*7c478bd9Sstevel@tonic-gate logerror("Can't determine owner of '%s'", w->dev); 2140*7c478bd9Sstevel@tonic-gate } else if (strncmp(pw.pw_name, w->ut_name, UNAMESZ) != 0) { 2141*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Bad terminal owner '%s'" 2142*7c478bd9Sstevel@tonic-gate "\n", mythreadno, w->dev); 2143*7c478bd9Sstevel@tonic-gate errno = 0; 2144*7c478bd9Sstevel@tonic-gate logerror("%s %s owns '%s' %s %.*s", 2145*7c478bd9Sstevel@tonic-gate "Bad terminal owner;", pw.pw_name, w->dev, 2146*7c478bd9Sstevel@tonic-gate "but utmpx says", UNAMESZ, w->ut_name); 2147*7c478bd9Sstevel@tonic-gate } else if (write(ttyf, w->msg, len) != len) { 2148*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Write failed to " 2149*7c478bd9Sstevel@tonic-gate "'%s'\n", mythreadno, w->dev); 2150*7c478bd9Sstevel@tonic-gate errno = 0; 2151*7c478bd9Sstevel@tonic-gate logerror("Write failed to '%s'", w->dev); 2152*7c478bd9Sstevel@tonic-gate } 2153*7c478bd9Sstevel@tonic-gate 2154*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): write to '%s' succeeded\n", 2155*7c478bd9Sstevel@tonic-gate mythreadno, w->dev); 2156*7c478bd9Sstevel@tonic-gate 2157*7c478bd9Sstevel@tonic-gate (void) close(ttyf); 2158*7c478bd9Sstevel@tonic-gate } else { 2159*7c478bd9Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't open '%s'\n", 2160*7c478bd9Sstevel@tonic-gate mythreadno, w->dev); 2161*7c478bd9Sstevel@tonic-gate } 2162*7c478bd9Sstevel@tonic-gate 2163*7c478bd9Sstevel@tonic-gate pthread_attr_destroy(&w->thread_attr); 2164*7c478bd9Sstevel@tonic-gate free(w); 2165*7c478bd9Sstevel@tonic-gate 2166*7c478bd9Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread exiting\n", 2167*7c478bd9Sstevel@tonic-gate mythreadno); 2168*7c478bd9Sstevel@tonic-gate 2169*7c478bd9Sstevel@tonic-gate pthread_exit(0); 2170*7c478bd9Sstevel@tonic-gate return (NULL); 2171*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2172*7c478bd9Sstevel@tonic-gate } 2173*7c478bd9Sstevel@tonic-gate 2174*7c478bd9Sstevel@tonic-gate /* 2175*7c478bd9Sstevel@tonic-gate * Return a printable representation of a host address. If unable to 2176*7c478bd9Sstevel@tonic-gate * look up hostname, format the numeric address for display instead. 2177*7c478bd9Sstevel@tonic-gate * 2178*7c478bd9Sstevel@tonic-gate * First calls hnc_lookup to see if there is valid cache entry for 2179*7c478bd9Sstevel@tonic-gate * given network address. If it failed, cvthname looks up hostname, 2180*7c478bd9Sstevel@tonic-gate * and push the results into the hostname cache. 2181*7c478bd9Sstevel@tonic-gate */ 2182*7c478bd9Sstevel@tonic-gate static host_list_t * 2183*7c478bd9Sstevel@tonic-gate cvthname(struct netbuf *nbp, struct netconfig *ncp, char *failsafe_addr) 2184*7c478bd9Sstevel@tonic-gate { 2185*7c478bd9Sstevel@tonic-gate int i; 2186*7c478bd9Sstevel@tonic-gate host_list_t *h; 2187*7c478bd9Sstevel@tonic-gate struct nd_hostservlist *hsp; 2188*7c478bd9Sstevel@tonic-gate struct nd_hostserv *hspp; 2189*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2190*7c478bd9Sstevel@tonic-gate char *uap; 2191*7c478bd9Sstevel@tonic-gate 2192*7c478bd9Sstevel@tonic-gate if (Debug) { 2193*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2194*7c478bd9Sstevel@tonic-gate } 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate if (Debug) 2197*7c478bd9Sstevel@tonic-gate uap = taddr2uaddr(ncp, nbp); 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): looking up hostname for %s\n", 2200*7c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate if ((h = hnc_lookup(nbp, ncp)) != NULL) { 2203*7c478bd9Sstevel@tonic-gate DPRINT4(2, "cvthname(%u): Cache found %p for %s (%s)\n", 2204*7c478bd9Sstevel@tonic-gate mythreadno, h, uap ? uap : "<unknown>", 2205*7c478bd9Sstevel@tonic-gate h->hl_hosts[0]); 2206*7c478bd9Sstevel@tonic-gate return (h); 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): No cache found for %s\n", 2209*7c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate if (Debug) 2212*7c478bd9Sstevel@tonic-gate free(uap); 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 2215*7c478bd9Sstevel@tonic-gate return (NULL); 2216*7c478bd9Sstevel@tonic-gate } 2217*7c478bd9Sstevel@tonic-gate 2218*7c478bd9Sstevel@tonic-gate /* memory allocation failure here is fatal */ 2219*7c478bd9Sstevel@tonic-gate if ((h = malloc(sizeof (host_list_t))) == NULL) { 2220*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 2221*7c478bd9Sstevel@tonic-gate return (NULL); 2222*7c478bd9Sstevel@tonic-gate } 2223*7c478bd9Sstevel@tonic-gate 2224*7c478bd9Sstevel@tonic-gate if (netdir_getbyaddr(ncp, &hsp, nbp) == 0) { 2225*7c478bd9Sstevel@tonic-gate if (hsp->h_cnt <= 0) { 2226*7c478bd9Sstevel@tonic-gate out: netdir_free((void *)hsp, ND_HOSTSERVLIST); 2227*7c478bd9Sstevel@tonic-gate free(h); 2228*7c478bd9Sstevel@tonic-gate return (NULL); 2229*7c478bd9Sstevel@tonic-gate } 2230*7c478bd9Sstevel@tonic-gate 2231*7c478bd9Sstevel@tonic-gate hspp = hsp->h_hostservs; 2232*7c478bd9Sstevel@tonic-gate h->hl_cnt = hsp->h_cnt; 2233*7c478bd9Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *) * (h->hl_cnt)); 2234*7c478bd9Sstevel@tonic-gate if (h->hl_hosts == NULL) { 2235*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 2236*7c478bd9Sstevel@tonic-gate goto out; 2237*7c478bd9Sstevel@tonic-gate } 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): Found %d hostnames\n", 2240*7c478bd9Sstevel@tonic-gate mythreadno, h->hl_cnt); 2241*7c478bd9Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) { 2242*7c478bd9Sstevel@tonic-gate h->hl_hosts[i] = (char *) 2243*7c478bd9Sstevel@tonic-gate malloc(sizeof (char) * (strlen(hspp->h_host) + 1)); 2244*7c478bd9Sstevel@tonic-gate if (h->hl_hosts[i] == NULL) { 2245*7c478bd9Sstevel@tonic-gate int j; 2246*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 2247*7c478bd9Sstevel@tonic-gate free(h->hl_hosts[j]); 2248*7c478bd9Sstevel@tonic-gate } 2249*7c478bd9Sstevel@tonic-gate free(h->hl_hosts); 2250*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 2251*7c478bd9Sstevel@tonic-gate goto out; 2252*7c478bd9Sstevel@tonic-gate } 2253*7c478bd9Sstevel@tonic-gate (void) strcpy(h->hl_hosts[i], hspp->h_host); 2254*7c478bd9Sstevel@tonic-gate hspp++; 2255*7c478bd9Sstevel@tonic-gate } 2256*7c478bd9Sstevel@tonic-gate netdir_free((void *)hsp, ND_HOSTSERVLIST); 2257*7c478bd9Sstevel@tonic-gate } else { /* unknown address */ 2258*7c478bd9Sstevel@tonic-gate h->hl_cnt = 1; 2259*7c478bd9Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *)); 2260*7c478bd9Sstevel@tonic-gate if (h->hl_hosts == NULL) { 2261*7c478bd9Sstevel@tonic-gate free(h); 2262*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 2263*7c478bd9Sstevel@tonic-gate return (NULL); 2264*7c478bd9Sstevel@tonic-gate } 2265*7c478bd9Sstevel@tonic-gate h->hl_hosts[0] = (char *)malloc(strlen(failsafe_addr) + 3); 2266*7c478bd9Sstevel@tonic-gate if (h->hl_hosts[0] == NULL) { 2267*7c478bd9Sstevel@tonic-gate free(h->hl_hosts); 2268*7c478bd9Sstevel@tonic-gate free(h); 2269*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("host name conversion"); 2270*7c478bd9Sstevel@tonic-gate return (NULL); 2271*7c478bd9Sstevel@tonic-gate } 2272*7c478bd9Sstevel@tonic-gate (void) sprintf(h->hl_hosts[0], "[%s]", failsafe_addr); 2273*7c478bd9Sstevel@tonic-gate DPRINT2(1, "cvthname(%u): Hostname lookup failed " 2274*7c478bd9Sstevel@tonic-gate "- using address %s instead\n", 2275*7c478bd9Sstevel@tonic-gate mythreadno, h->hl_hosts[0]); 2276*7c478bd9Sstevel@tonic-gate } 2277*7c478bd9Sstevel@tonic-gate 2278*7c478bd9Sstevel@tonic-gate h->hl_refcnt = 1; 2279*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&h->hl_mutex, NULL) != 0) { 2280*7c478bd9Sstevel@tonic-gate logerror("pthread_mutex_init failed"); 2281*7c478bd9Sstevel@tonic-gate /* This host_list won't be shared by the cache. */ 2282*7c478bd9Sstevel@tonic-gate return (h); 2283*7c478bd9Sstevel@tonic-gate } 2284*7c478bd9Sstevel@tonic-gate hnc_register(nbp, ncp, h); 2285*7c478bd9Sstevel@tonic-gate DPRINT3(2, "cvthname(%u): returning %p for %s\n", 2286*7c478bd9Sstevel@tonic-gate mythreadno, h, h->hl_hosts[0]); 2287*7c478bd9Sstevel@tonic-gate return (h); 2288*7c478bd9Sstevel@tonic-gate } 2289*7c478bd9Sstevel@tonic-gate 2290*7c478bd9Sstevel@tonic-gate /* 2291*7c478bd9Sstevel@tonic-gate * Print syslogd errors some place. Need to be careful here, because 2292*7c478bd9Sstevel@tonic-gate * this routine is called at times when we're not initialized and 2293*7c478bd9Sstevel@tonic-gate * ready to log messages...in this case, fall back to using the console. 2294*7c478bd9Sstevel@tonic-gate */ 2295*7c478bd9Sstevel@tonic-gate void 2296*7c478bd9Sstevel@tonic-gate logerror(const char *type, ...) 2297*7c478bd9Sstevel@tonic-gate { 2298*7c478bd9Sstevel@tonic-gate char buf[MAXLINE+1]; 2299*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2300*7c478bd9Sstevel@tonic-gate int flag; 2301*7c478bd9Sstevel@tonic-gate va_list ap; 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate if (Debug) { 2304*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2305*7c478bd9Sstevel@tonic-gate } 2306*7c478bd9Sstevel@tonic-gate 2307*7c478bd9Sstevel@tonic-gate va_start(ap, type); 2308*7c478bd9Sstevel@tonic-gate logerror_format(type, buf, ap); 2309*7c478bd9Sstevel@tonic-gate va_end(ap); 2310*7c478bd9Sstevel@tonic-gate DPRINT2(1, "logerror(%u): %s\n", mythreadno, buf); 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&logerror_lock); 2313*7c478bd9Sstevel@tonic-gate if (!interrorlog) { 2314*7c478bd9Sstevel@tonic-gate flag = 0; 2315*7c478bd9Sstevel@tonic-gate if (logerror_to_console(1, buf) == 0) { 2316*7c478bd9Sstevel@tonic-gate /* has written to the console */ 2317*7c478bd9Sstevel@tonic-gate flag = IGN_CONS; 2318*7c478bd9Sstevel@tonic-gate } 2319*7c478bd9Sstevel@tonic-gate (void) logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE|flag, 1); 2320*7c478bd9Sstevel@tonic-gate } else { 2321*7c478bd9Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE, 0) == -1) { 2322*7c478bd9Sstevel@tonic-gate (void) logerror_to_console(1, buf); 2323*7c478bd9Sstevel@tonic-gate } 2324*7c478bd9Sstevel@tonic-gate } 2325*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&logerror_lock); 2326*7c478bd9Sstevel@tonic-gate 2327*7c478bd9Sstevel@tonic-gate errno = 0; 2328*7c478bd9Sstevel@tonic-gate t_errno = 0; 2329*7c478bd9Sstevel@tonic-gate } 2330*7c478bd9Sstevel@tonic-gate 2331*7c478bd9Sstevel@tonic-gate static void 2332*7c478bd9Sstevel@tonic-gate logerror_format(const char *type, char *buf, va_list ap) 2333*7c478bd9Sstevel@tonic-gate { 2334*7c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE + 1]; 2335*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2336*7c478bd9Sstevel@tonic-gate 2337*7c478bd9Sstevel@tonic-gate if (Debug) { 2338*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2339*7c478bd9Sstevel@tonic-gate } 2340*7c478bd9Sstevel@tonic-gate 2341*7c478bd9Sstevel@tonic-gate (void) vsnprintf(tmpbuf, MAXLINE, type, ap); 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate if (t_errno == 0 || t_errno == TSYSERR) { 2344*7c478bd9Sstevel@tonic-gate char *errstr; 2345*7c478bd9Sstevel@tonic-gate 2346*7c478bd9Sstevel@tonic-gate if (errno == 0) { 2347*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %.*s", 2348*7c478bd9Sstevel@tonic-gate MAXLINE, tmpbuf); 2349*7c478bd9Sstevel@tonic-gate } else if ((errstr = strerror(errno)) == (char *)NULL) { 2350*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: error" 2351*7c478bd9Sstevel@tonic-gate " %d", tmpbuf, errno); 2352*7c478bd9Sstevel@tonic-gate } else { 2353*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s", 2354*7c478bd9Sstevel@tonic-gate tmpbuf, errstr); 2355*7c478bd9Sstevel@tonic-gate } 2356*7c478bd9Sstevel@tonic-gate } else { 2357*7c478bd9Sstevel@tonic-gate if (t_errno > t_nerr) { 2358*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s:" 2359*7c478bd9Sstevel@tonic-gate " t_error %d", tmpbuf, t_errno); 2360*7c478bd9Sstevel@tonic-gate } else { 2361*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s", 2362*7c478bd9Sstevel@tonic-gate tmpbuf, t_errlist[t_errno]); 2363*7c478bd9Sstevel@tonic-gate } 2364*7c478bd9Sstevel@tonic-gate } 2365*7c478bd9Sstevel@tonic-gate 2366*7c478bd9Sstevel@tonic-gate DPRINT2(5, "logerror_format(%u): out %s\n", mythreadno, buf); 2367*7c478bd9Sstevel@tonic-gate } 2368*7c478bd9Sstevel@tonic-gate 2369*7c478bd9Sstevel@tonic-gate static int 2370*7c478bd9Sstevel@tonic-gate logerror_to_console(int nonblock, const char *buf) 2371*7c478bd9Sstevel@tonic-gate { 2372*7c478bd9Sstevel@tonic-gate int cfd, modes; 2373*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2374*7c478bd9Sstevel@tonic-gate int ret = 0, len; 2375*7c478bd9Sstevel@tonic-gate char tmpbuf[MAXLINE + 1]; 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate if (Debug) { 2378*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2379*7c478bd9Sstevel@tonic-gate } 2380*7c478bd9Sstevel@tonic-gate 2381*7c478bd9Sstevel@tonic-gate DPRINT2(1, "logerror_to_console(%u): %s\n", mythreadno, buf); 2382*7c478bd9Sstevel@tonic-gate 2383*7c478bd9Sstevel@tonic-gate /* 2384*7c478bd9Sstevel@tonic-gate * must use open here instead of fopen, because 2385*7c478bd9Sstevel@tonic-gate * we need the O_NOCTTY behavior - otherwise we 2386*7c478bd9Sstevel@tonic-gate * could hang the console at boot time 2387*7c478bd9Sstevel@tonic-gate */ 2388*7c478bd9Sstevel@tonic-gate 2389*7c478bd9Sstevel@tonic-gate modes = (nonblock) ? 2390*7c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK : 2391*7c478bd9Sstevel@tonic-gate O_WRONLY|O_APPEND|O_NOCTTY; 2392*7c478bd9Sstevel@tonic-gate 2393*7c478bd9Sstevel@tonic-gate if (((cfd = open(sysmsg, modes)) >= 0) || 2394*7c478bd9Sstevel@tonic-gate ((cfd = open(ctty, modes)) >= 0)) { 2395*7c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, MAXLINE, "%s\n", buf); 2396*7c478bd9Sstevel@tonic-gate len = strlen(tmpbuf); 2397*7c478bd9Sstevel@tonic-gate if (write(cfd, tmpbuf, len) != len) { 2398*7c478bd9Sstevel@tonic-gate ret = 1; 2399*7c478bd9Sstevel@tonic-gate } 2400*7c478bd9Sstevel@tonic-gate (void) close(cfd); 2401*7c478bd9Sstevel@tonic-gate } else { 2402*7c478bd9Sstevel@tonic-gate ret = 1; 2403*7c478bd9Sstevel@tonic-gate 2404*7c478bd9Sstevel@tonic-gate /* punt */ 2405*7c478bd9Sstevel@tonic-gate DPRINT1(1, "logerror_console(%u): can't open console\n", 2406*7c478bd9Sstevel@tonic-gate mythreadno); 2407*7c478bd9Sstevel@tonic-gate } 2408*7c478bd9Sstevel@tonic-gate return (ret); 2409*7c478bd9Sstevel@tonic-gate } 2410*7c478bd9Sstevel@tonic-gate 2411*7c478bd9Sstevel@tonic-gate /* 2412*7c478bd9Sstevel@tonic-gate * copy current message to saved message in filed structure. 2413*7c478bd9Sstevel@tonic-gate */ 2414*7c478bd9Sstevel@tonic-gate static void 2415*7c478bd9Sstevel@tonic-gate copy_msg(struct filed *f) 2416*7c478bd9Sstevel@tonic-gate { 2417*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.msg, f->f_current.msg, MAXLINE+1); 2418*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.host, f->f_current.host, SYS_NMLN); 2419*7c478bd9Sstevel@tonic-gate f->f_prevmsg.pri = f->f_current.pri; 2420*7c478bd9Sstevel@tonic-gate f->f_prevmsg.flags = f->f_current.flags; 2421*7c478bd9Sstevel@tonic-gate f->f_prevmsg.time = f->f_current.time; 2422*7c478bd9Sstevel@tonic-gate f->f_msgflag |= OLD_VALID; 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate /* 2427*7c478bd9Sstevel@tonic-gate * function to free a host_list_t struct that was allocated 2428*7c478bd9Sstevel@tonic-gate * out of cvthname(). There is a special case where we don't 2429*7c478bd9Sstevel@tonic-gate * free the hostname list in LocalHostName, because that's 2430*7c478bd9Sstevel@tonic-gate * our own addresses, and we just want to have to look it 2431*7c478bd9Sstevel@tonic-gate * up once and save it. Also don't free it if it's 2432*7c478bd9Sstevel@tonic-gate * NullHostName, because that's a special one we use if 2433*7c478bd9Sstevel@tonic-gate * name service lookup fails. 2434*7c478bd9Sstevel@tonic-gate * 2435*7c478bd9Sstevel@tonic-gate * By having hostname cache, now host_list_t will be shared 2436*7c478bd9Sstevel@tonic-gate * by messages and hostname cache. hl_refcnt is used for 2437*7c478bd9Sstevel@tonic-gate * the purpose. 2438*7c478bd9Sstevel@tonic-gate */ 2439*7c478bd9Sstevel@tonic-gate static void 2440*7c478bd9Sstevel@tonic-gate freehl(host_list_t *h) 2441*7c478bd9Sstevel@tonic-gate { 2442*7c478bd9Sstevel@tonic-gate int i, refcnt; 2443*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2444*7c478bd9Sstevel@tonic-gate 2445*7c478bd9Sstevel@tonic-gate if (Debug) { 2446*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2447*7c478bd9Sstevel@tonic-gate } 2448*7c478bd9Sstevel@tonic-gate 2449*7c478bd9Sstevel@tonic-gate DPRINT2(2, "freehl(%u): releasing %p\n", mythreadno, h); 2450*7c478bd9Sstevel@tonic-gate 2451*7c478bd9Sstevel@tonic-gate if (h == NULL || h == &LocalHostName || h == &NullHostName) { 2452*7c478bd9Sstevel@tonic-gate return; 2453*7c478bd9Sstevel@tonic-gate } 2454*7c478bd9Sstevel@tonic-gate 2455*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&h->hl_mutex); 2456*7c478bd9Sstevel@tonic-gate refcnt = --h->hl_refcnt; 2457*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&h->hl_mutex); 2458*7c478bd9Sstevel@tonic-gate 2459*7c478bd9Sstevel@tonic-gate if (refcnt != 0) { 2460*7c478bd9Sstevel@tonic-gate DPRINT3(5, "freehl(%u): %p has reference %d\n", 2461*7c478bd9Sstevel@tonic-gate mythreadno, h, refcnt); 2462*7c478bd9Sstevel@tonic-gate return; 2463*7c478bd9Sstevel@tonic-gate } 2464*7c478bd9Sstevel@tonic-gate 2465*7c478bd9Sstevel@tonic-gate pthread_mutex_destroy(&h->hl_mutex); 2466*7c478bd9Sstevel@tonic-gate 2467*7c478bd9Sstevel@tonic-gate DPRINT2(5, "freehl(%u): freeing %p\n", mythreadno, h); 2468*7c478bd9Sstevel@tonic-gate 2469*7c478bd9Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) { 2470*7c478bd9Sstevel@tonic-gate free(h->hl_hosts[i]); 2471*7c478bd9Sstevel@tonic-gate } 2472*7c478bd9Sstevel@tonic-gate 2473*7c478bd9Sstevel@tonic-gate free(h->hl_hosts); 2474*7c478bd9Sstevel@tonic-gate free(h); 2475*7c478bd9Sstevel@tonic-gate } 2476*7c478bd9Sstevel@tonic-gate 2477*7c478bd9Sstevel@tonic-gate /* 2478*7c478bd9Sstevel@tonic-gate * Create the door file and the pid file in /var/run. If the filesystem 2479*7c478bd9Sstevel@tonic-gate * containing /etc is writable, create symlinks /etc/.syslog_door and 2480*7c478bd9Sstevel@tonic-gate * /etc/syslog.pid to them. On systems that do not support /var/run, create 2481*7c478bd9Sstevel@tonic-gate * /etc/.syslog_door and /etc/syslog.pid directly. 2482*7c478bd9Sstevel@tonic-gate * 2483*7c478bd9Sstevel@tonic-gate * Note: it is not considered fatal to fail to create the pid file or its 2484*7c478bd9Sstevel@tonic-gate * symlink. Attempts to use them in the usual way will fail, of course, but 2485*7c478bd9Sstevel@tonic-gate * syslogd will function nicely without it (not so for the door file). 2486*7c478bd9Sstevel@tonic-gate */ 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate static void 2489*7c478bd9Sstevel@tonic-gate open_door(void) 2490*7c478bd9Sstevel@tonic-gate { 2491*7c478bd9Sstevel@tonic-gate struct stat buf; 2492*7c478bd9Sstevel@tonic-gate door_info_t info; 2493*7c478bd9Sstevel@tonic-gate char line[MAXLINE+1]; 2494*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2495*7c478bd9Sstevel@tonic-gate int err; 2496*7c478bd9Sstevel@tonic-gate 2497*7c478bd9Sstevel@tonic-gate if (Debug) { 2498*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2499*7c478bd9Sstevel@tonic-gate } 2500*7c478bd9Sstevel@tonic-gate 2501*7c478bd9Sstevel@tonic-gate /* 2502*7c478bd9Sstevel@tonic-gate * first see if another syslogd is running by trying 2503*7c478bd9Sstevel@tonic-gate * a door call - if it succeeds, there is already 2504*7c478bd9Sstevel@tonic-gate * a syslogd process active 2505*7c478bd9Sstevel@tonic-gate */ 2506*7c478bd9Sstevel@tonic-gate 2507*7c478bd9Sstevel@tonic-gate if (!DoorCreated) { 2508*7c478bd9Sstevel@tonic-gate int door; 2509*7c478bd9Sstevel@tonic-gate 2510*7c478bd9Sstevel@tonic-gate if ((door = open(DoorFileName, O_RDONLY)) >= 0) { 2511*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s opened " 2512*7c478bd9Sstevel@tonic-gate "successfully\n", mythreadno, DoorFileName); 2513*7c478bd9Sstevel@tonic-gate 2514*7c478bd9Sstevel@tonic-gate if (door_info(door, &info) >= 0) { 2515*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): " 2516*7c478bd9Sstevel@tonic-gate "door_info:info.di_target = %ld\n", 2517*7c478bd9Sstevel@tonic-gate mythreadno, info.di_target); 2518*7c478bd9Sstevel@tonic-gate 2519*7c478bd9Sstevel@tonic-gate if (info.di_target > 0) { 2520*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "syslogd pid %ld" 2521*7c478bd9Sstevel@tonic-gate " already running. Cannot " 2522*7c478bd9Sstevel@tonic-gate "start another syslogd pid %ld", 2523*7c478bd9Sstevel@tonic-gate info.di_target, getpid()); 2524*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): error: " 2525*7c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 2526*7c478bd9Sstevel@tonic-gate errno = 0; 2527*7c478bd9Sstevel@tonic-gate logerror(line); 2528*7c478bd9Sstevel@tonic-gate exit(1); 2529*7c478bd9Sstevel@tonic-gate } 2530*7c478bd9Sstevel@tonic-gate } 2531*7c478bd9Sstevel@tonic-gate 2532*7c478bd9Sstevel@tonic-gate (void) close(door); 2533*7c478bd9Sstevel@tonic-gate } else { 2534*7c478bd9Sstevel@tonic-gate if (lstat(DoorFileName, &buf) < 0) { 2535*7c478bd9Sstevel@tonic-gate err = errno; 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): lstat() of %s " 2538*7c478bd9Sstevel@tonic-gate "failed, errno=%d\n", 2539*7c478bd9Sstevel@tonic-gate mythreadno, DoorFileName, err); 2540*7c478bd9Sstevel@tonic-gate 2541*7c478bd9Sstevel@tonic-gate if ((door = creat(DoorFileName, 0644)) < 0) { 2542*7c478bd9Sstevel@tonic-gate err = errno; 2543*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "creat() of %s " 2544*7c478bd9Sstevel@tonic-gate "failed - fatal", DoorFileName); 2545*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, " 2546*7c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, 2547*7c478bd9Sstevel@tonic-gate err); 2548*7c478bd9Sstevel@tonic-gate errno = err; 2549*7c478bd9Sstevel@tonic-gate logerror(line); 2550*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2551*7c478bd9Sstevel@tonic-gate exit(1); 2552*7c478bd9Sstevel@tonic-gate } 2553*7c478bd9Sstevel@tonic-gate 2554*7c478bd9Sstevel@tonic-gate (void) fchmod(door, 2555*7c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 2556*7c478bd9Sstevel@tonic-gate 2557*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): creat() of %s " 2558*7c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 2559*7c478bd9Sstevel@tonic-gate DoorFileName); 2560*7c478bd9Sstevel@tonic-gate 2561*7c478bd9Sstevel@tonic-gate (void) close(door); 2562*7c478bd9Sstevel@tonic-gate } 2563*7c478bd9Sstevel@tonic-gate } 2564*7c478bd9Sstevel@tonic-gate 2565*7c478bd9Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) { 2566*7c478bd9Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &buf) == 0) { 2567*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s " 2568*7c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 2569*7c478bd9Sstevel@tonic-gate OLD_DOORFILE); 2570*7c478bd9Sstevel@tonic-gate 2571*7c478bd9Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) { 2572*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "%s is a " 2573*7c478bd9Sstevel@tonic-gate "directory - fatal", 2574*7c478bd9Sstevel@tonic-gate OLD_DOORFILE); 2575*7c478bd9Sstevel@tonic-gate DPRINT2(1, "open_door(%u): error: " 2576*7c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 2577*7c478bd9Sstevel@tonic-gate errno = 0; 2578*7c478bd9Sstevel@tonic-gate logerror(line); 2579*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2580*7c478bd9Sstevel@tonic-gate exit(1); 2581*7c478bd9Sstevel@tonic-gate } 2582*7c478bd9Sstevel@tonic-gate 2583*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s is not a " 2584*7c478bd9Sstevel@tonic-gate "directory\n", 2585*7c478bd9Sstevel@tonic-gate mythreadno, OLD_DOORFILE); 2586*7c478bd9Sstevel@tonic-gate 2587*7c478bd9Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) { 2588*7c478bd9Sstevel@tonic-gate err = errno; 2589*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() of %s " 2590*7c478bd9Sstevel@tonic-gate "failed", OLD_DOORFILE); 2591*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", 2592*7c478bd9Sstevel@tonic-gate mythreadno, line); 2593*7c478bd9Sstevel@tonic-gate 2594*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 2595*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): " 2596*7c478bd9Sstevel@tonic-gate "error: %s, " 2597*7c478bd9Sstevel@tonic-gate "errno=%d\n", 2598*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 2599*7c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 2600*7c478bd9Sstevel@tonic-gate errno = err; 2601*7c478bd9Sstevel@tonic-gate logerror(line); 2602*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2603*7c478bd9Sstevel@tonic-gate exit(1); 2604*7c478bd9Sstevel@tonic-gate } 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink " 2607*7c478bd9Sstevel@tonic-gate "failure OK on RO file " 2608*7c478bd9Sstevel@tonic-gate "system\n", mythreadno); 2609*7c478bd9Sstevel@tonic-gate } 2610*7c478bd9Sstevel@tonic-gate } else { 2611*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't " 2612*7c478bd9Sstevel@tonic-gate "exist\n", mythreadno, OLD_DOORFILE); 2613*7c478bd9Sstevel@tonic-gate } 2614*7c478bd9Sstevel@tonic-gate 2615*7c478bd9Sstevel@tonic-gate if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) { 2616*7c478bd9Sstevel@tonic-gate err = errno; 2617*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "symlink %s -> %s " 2618*7c478bd9Sstevel@tonic-gate "failed", OLD_DOORFILE, 2619*7c478bd9Sstevel@tonic-gate RELATIVE_DOORFILE); 2620*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno, 2621*7c478bd9Sstevel@tonic-gate line); 2622*7c478bd9Sstevel@tonic-gate 2623*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 2624*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, " 2625*7c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, 2626*7c478bd9Sstevel@tonic-gate err); 2627*7c478bd9Sstevel@tonic-gate errno = err; 2628*7c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 2629*7c478bd9Sstevel@tonic-gate logerror(line); 2630*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2631*7c478bd9Sstevel@tonic-gate exit(1); 2632*7c478bd9Sstevel@tonic-gate } 2633*7c478bd9Sstevel@tonic-gate 2634*7c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK " 2635*7c478bd9Sstevel@tonic-gate "on RO file system\n", mythreadno); 2636*7c478bd9Sstevel@tonic-gate } else { 2637*7c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s " 2638*7c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, 2639*7c478bd9Sstevel@tonic-gate OLD_DOORFILE, RELATIVE_DOORFILE); 2640*7c478bd9Sstevel@tonic-gate } 2641*7c478bd9Sstevel@tonic-gate } 2642*7c478bd9Sstevel@tonic-gate 2643*7c478bd9Sstevel@tonic-gate if ((DoorFd = door_create(server, 0, 2644*7c478bd9Sstevel@tonic-gate DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { 2645*7c478bd9Sstevel@tonic-gate err = errno; 2646*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "door_create() failed - fatal"); 2647*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", 2648*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 2649*7c478bd9Sstevel@tonic-gate errno = err; 2650*7c478bd9Sstevel@tonic-gate logerror(line); 2651*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2652*7c478bd9Sstevel@tonic-gate exit(1); 2653*7c478bd9Sstevel@tonic-gate } 2654*7c478bd9Sstevel@tonic-gate (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0); 2655*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): door_create() succeeded, " 2656*7c478bd9Sstevel@tonic-gate "DoorFd=%d\n", mythreadno, DoorFd); 2657*7c478bd9Sstevel@tonic-gate 2658*7c478bd9Sstevel@tonic-gate DoorCreated = 1; 2659*7c478bd9Sstevel@tonic-gate } 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate (void) fdetach(DoorFileName); /* just in case... */ 2662*7c478bd9Sstevel@tonic-gate 2663*7c478bd9Sstevel@tonic-gate if (fattach(DoorFd, DoorFileName) < 0) { 2664*7c478bd9Sstevel@tonic-gate err = errno; 2665*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "fattach() of fd" 2666*7c478bd9Sstevel@tonic-gate " %d to %s failed - fatal", 2667*7c478bd9Sstevel@tonic-gate DoorFd, DoorFileName); 2668*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", mythreadno, 2669*7c478bd9Sstevel@tonic-gate line, err); 2670*7c478bd9Sstevel@tonic-gate errno = err; 2671*7c478bd9Sstevel@tonic-gate logerror(line); 2672*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 2673*7c478bd9Sstevel@tonic-gate exit(1); 2674*7c478bd9Sstevel@tonic-gate } 2675*7c478bd9Sstevel@tonic-gate 2676*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): attached server() to %s\n", mythreadno, 2677*7c478bd9Sstevel@tonic-gate DoorFileName); 2678*7c478bd9Sstevel@tonic-gate 2679*7c478bd9Sstevel@tonic-gate /* 2680*7c478bd9Sstevel@tonic-gate * create pidfile anyway, so those using it to control 2681*7c478bd9Sstevel@tonic-gate * syslogd (with kill `cat /etc/syslog.pid` perhaps) 2682*7c478bd9Sstevel@tonic-gate * don't get broken. 2683*7c478bd9Sstevel@tonic-gate */ 2684*7c478bd9Sstevel@tonic-gate 2685*7c478bd9Sstevel@tonic-gate if (!PidfileCreated) { 2686*7c478bd9Sstevel@tonic-gate int pidfd; 2687*7c478bd9Sstevel@tonic-gate 2688*7c478bd9Sstevel@tonic-gate PidfileCreated = 1; 2689*7c478bd9Sstevel@tonic-gate 2690*7c478bd9Sstevel@tonic-gate if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644)) 2691*7c478bd9Sstevel@tonic-gate < 0) { 2692*7c478bd9Sstevel@tonic-gate err = errno; 2693*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "open() of %s failed", 2694*7c478bd9Sstevel@tonic-gate PidFileName); 2695*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n", 2696*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 2697*7c478bd9Sstevel@tonic-gate errno = err; 2698*7c478bd9Sstevel@tonic-gate logerror(line); 2699*7c478bd9Sstevel@tonic-gate return; 2700*7c478bd9Sstevel@tonic-gate } 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate (void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 2703*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "%ld\n", getpid()); 2704*7c478bd9Sstevel@tonic-gate 2705*7c478bd9Sstevel@tonic-gate if (write(pidfd, line, strlen(line)) < 0) { 2706*7c478bd9Sstevel@tonic-gate err = errno; 2707*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "write to %s on fd %d failed", 2708*7c478bd9Sstevel@tonic-gate PidFileName, pidfd); 2709*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n", 2710*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 2711*7c478bd9Sstevel@tonic-gate errno = err; 2712*7c478bd9Sstevel@tonic-gate logerror(line); 2713*7c478bd9Sstevel@tonic-gate return; 2714*7c478bd9Sstevel@tonic-gate } 2715*7c478bd9Sstevel@tonic-gate 2716*7c478bd9Sstevel@tonic-gate (void) close(pidfd); 2717*7c478bd9Sstevel@tonic-gate 2718*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s created\n", 2719*7c478bd9Sstevel@tonic-gate mythreadno, PidFileName); 2720*7c478bd9Sstevel@tonic-gate 2721*7c478bd9Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) { 2722*7c478bd9Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &buf) == 0) { 2723*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s " 2724*7c478bd9Sstevel@tonic-gate "succeded\n", mythreadno, OLD_PIDFILE); 2725*7c478bd9Sstevel@tonic-gate 2726*7c478bd9Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) { 2727*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "file %s is a " 2728*7c478bd9Sstevel@tonic-gate "directory", 2729*7c478bd9Sstevel@tonic-gate OLD_PIDFILE); 2730*7c478bd9Sstevel@tonic-gate DPRINT2(1, "open_door(%u): warning: " 2731*7c478bd9Sstevel@tonic-gate "%s\n", mythreadno, line); 2732*7c478bd9Sstevel@tonic-gate errno = 0; 2733*7c478bd9Sstevel@tonic-gate logerror(line); 2734*7c478bd9Sstevel@tonic-gate return; 2735*7c478bd9Sstevel@tonic-gate } 2736*7c478bd9Sstevel@tonic-gate 2737*7c478bd9Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) { 2738*7c478bd9Sstevel@tonic-gate err = errno; 2739*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() " 2740*7c478bd9Sstevel@tonic-gate "of %s failed", OLD_PIDFILE); 2741*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", 2742*7c478bd9Sstevel@tonic-gate mythreadno, line); 2743*7c478bd9Sstevel@tonic-gate 2744*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 2745*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door (%u): " 2746*7c478bd9Sstevel@tonic-gate "warning: %s, " 2747*7c478bd9Sstevel@tonic-gate "errno=%d\n", 2748*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 2749*7c478bd9Sstevel@tonic-gate errno = err; 2750*7c478bd9Sstevel@tonic-gate logerror(line); 2751*7c478bd9Sstevel@tonic-gate return; 2752*7c478bd9Sstevel@tonic-gate } 2753*7c478bd9Sstevel@tonic-gate 2754*7c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink " 2755*7c478bd9Sstevel@tonic-gate "failure OK on RO file " 2756*7c478bd9Sstevel@tonic-gate "system\n", mythreadno); 2757*7c478bd9Sstevel@tonic-gate } 2758*7c478bd9Sstevel@tonic-gate } else { 2759*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't " 2760*7c478bd9Sstevel@tonic-gate "exist\n", mythreadno, OLD_PIDFILE); 2761*7c478bd9Sstevel@tonic-gate } 2762*7c478bd9Sstevel@tonic-gate 2763*7c478bd9Sstevel@tonic-gate if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) { 2764*7c478bd9Sstevel@tonic-gate err = errno; 2765*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "symlink %s -> %s " 2766*7c478bd9Sstevel@tonic-gate "failed", OLD_PIDFILE, 2767*7c478bd9Sstevel@tonic-gate RELATIVE_PIDFILE); 2768*7c478bd9Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno, 2769*7c478bd9Sstevel@tonic-gate line); 2770*7c478bd9Sstevel@tonic-gate 2771*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 2772*7c478bd9Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: " 2773*7c478bd9Sstevel@tonic-gate "%s, errno=%d\n", mythreadno, 2774*7c478bd9Sstevel@tonic-gate line, err); 2775*7c478bd9Sstevel@tonic-gate errno = err; 2776*7c478bd9Sstevel@tonic-gate logerror(line); 2777*7c478bd9Sstevel@tonic-gate return; 2778*7c478bd9Sstevel@tonic-gate } 2779*7c478bd9Sstevel@tonic-gate 2780*7c478bd9Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK " 2781*7c478bd9Sstevel@tonic-gate "on RO file system\n", mythreadno); 2782*7c478bd9Sstevel@tonic-gate return; 2783*7c478bd9Sstevel@tonic-gate } 2784*7c478bd9Sstevel@tonic-gate 2785*7c478bd9Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s " 2786*7c478bd9Sstevel@tonic-gate "succeeded\n", mythreadno, OLD_PIDFILE, 2787*7c478bd9Sstevel@tonic-gate RELATIVE_PIDFILE); 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate } 2790*7c478bd9Sstevel@tonic-gate } 2791*7c478bd9Sstevel@tonic-gate 2792*7c478bd9Sstevel@tonic-gate /* 2793*7c478bd9Sstevel@tonic-gate * the 'server' function that we export via the door. It does 2794*7c478bd9Sstevel@tonic-gate * nothing but return. 2795*7c478bd9Sstevel@tonic-gate */ 2796*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2797*7c478bd9Sstevel@tonic-gate static void 2798*7c478bd9Sstevel@tonic-gate server(void *cookie, char *argp, size_t arg_size, 2799*7c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t n) 2800*7c478bd9Sstevel@tonic-gate { 2801*7c478bd9Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 2802*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2803*7c478bd9Sstevel@tonic-gate } 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate /* 2806*7c478bd9Sstevel@tonic-gate * checkm4 - used to verify that the external utilities that 2807*7c478bd9Sstevel@tonic-gate * syslogd depends on are where we expect them to be. 2808*7c478bd9Sstevel@tonic-gate * Returns 0 if all utilities are found, > 0 if any are missing. 2809*7c478bd9Sstevel@tonic-gate * Also logs errors so user knows what's missing 2810*7c478bd9Sstevel@tonic-gate */ 2811*7c478bd9Sstevel@tonic-gate static int 2812*7c478bd9Sstevel@tonic-gate checkm4(void) 2813*7c478bd9Sstevel@tonic-gate { 2814*7c478bd9Sstevel@tonic-gate int notfound = 0; 2815*7c478bd9Sstevel@tonic-gate int saverrno; 2816*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2817*7c478bd9Sstevel@tonic-gate 2818*7c478bd9Sstevel@tonic-gate if (Debug) { 2819*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2820*7c478bd9Sstevel@tonic-gate } 2821*7c478bd9Sstevel@tonic-gate 2822*7c478bd9Sstevel@tonic-gate if (access("/usr/ccs/bin/m4", X_OK) < 0) { 2823*7c478bd9Sstevel@tonic-gate saverrno = errno; 2824*7c478bd9Sstevel@tonic-gate logerror("/usr/ccs/bin/m4"); 2825*7c478bd9Sstevel@tonic-gate DPRINT2(1, "checkm4(%u): /usr/ccs/bin/m4 - access " 2826*7c478bd9Sstevel@tonic-gate "returned %d\n", mythreadno, saverrno); 2827*7c478bd9Sstevel@tonic-gate notfound++; 2828*7c478bd9Sstevel@tonic-gate } 2829*7c478bd9Sstevel@tonic-gate 2830*7c478bd9Sstevel@tonic-gate return (notfound); 2831*7c478bd9Sstevel@tonic-gate } 2832*7c478bd9Sstevel@tonic-gate 2833*7c478bd9Sstevel@tonic-gate /* 2834*7c478bd9Sstevel@tonic-gate * INIT -- Initialize syslogd from configuration table, start up 2835*7c478bd9Sstevel@tonic-gate * input and logger threads. This routine is called only once. 2836*7c478bd9Sstevel@tonic-gate */ 2837*7c478bd9Sstevel@tonic-gate static void 2838*7c478bd9Sstevel@tonic-gate init(void) 2839*7c478bd9Sstevel@tonic-gate { 2840*7c478bd9Sstevel@tonic-gate struct utsname *up; 2841*7c478bd9Sstevel@tonic-gate pthread_attr_t sys_attr, net_attr, log_attr, hnl_attr; 2842*7c478bd9Sstevel@tonic-gate int nthread; 2843*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 2844*7c478bd9Sstevel@tonic-gate 2845*7c478bd9Sstevel@tonic-gate if (Debug) { 2846*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 2847*7c478bd9Sstevel@tonic-gate } 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate DPRINT1(2, "init(%u): initializing\n", mythreadno); 2850*7c478bd9Sstevel@tonic-gate 2851*7c478bd9Sstevel@tonic-gate /* hand-craft a host_list_t entry for our local host name */ 2852*7c478bd9Sstevel@tonic-gate if ((up = malloc(sizeof (struct utsname))) == NULL) { 2853*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 2854*7c478bd9Sstevel@tonic-gate } 2855*7c478bd9Sstevel@tonic-gate (void) uname(up); 2856*7c478bd9Sstevel@tonic-gate LocalHostName.hl_cnt = 1; 2857*7c478bd9Sstevel@tonic-gate if ((LocalHostName.hl_hosts = malloc(sizeof (char *))) == NULL) { 2858*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 2859*7c478bd9Sstevel@tonic-gate } 2860*7c478bd9Sstevel@tonic-gate if ((LocalHostName.hl_hosts[0] = strdup(up->nodename)) == NULL) { 2861*7c478bd9Sstevel@tonic-gate free(LocalHostName.hl_hosts); 2862*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 2863*7c478bd9Sstevel@tonic-gate } 2864*7c478bd9Sstevel@tonic-gate free(up); 2865*7c478bd9Sstevel@tonic-gate /* also hand craft one for use if name resolution fails */ 2866*7c478bd9Sstevel@tonic-gate NullHostName.hl_cnt = 1; 2867*7c478bd9Sstevel@tonic-gate if ((NullHostName.hl_hosts = malloc(sizeof (char *))) == NULL) { 2868*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 2869*7c478bd9Sstevel@tonic-gate } 2870*7c478bd9Sstevel@tonic-gate if ((NullHostName.hl_hosts[0] = strdup("name lookup failed")) == NULL) { 2871*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 2872*7c478bd9Sstevel@tonic-gate } 2873*7c478bd9Sstevel@tonic-gate 2874*7c478bd9Sstevel@tonic-gate hnc_init(0); 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate /* 2877*7c478bd9Sstevel@tonic-gate * Note that getnets will allocate network resources, but won't be 2878*7c478bd9Sstevel@tonic-gate * binding UDP port. This is because, there could be a race 2879*7c478bd9Sstevel@tonic-gate * condition between door. If we bind here, one syslogd could grab 2880*7c478bd9Sstevel@tonic-gate * UDP port first, but later another syslogd could take over without 2881*7c478bd9Sstevel@tonic-gate * getting UDP port but grab the door file. The 2nd syslogd could 2882*7c478bd9Sstevel@tonic-gate * continue to run without listening network. 2883*7c478bd9Sstevel@tonic-gate * bindnet() will be called after door was successfully opened. 2884*7c478bd9Sstevel@tonic-gate */ 2885*7c478bd9Sstevel@tonic-gate getnets(); 2886*7c478bd9Sstevel@tonic-gate 2887*7c478bd9Sstevel@tonic-gate /* 2888*7c478bd9Sstevel@tonic-gate * Start up configured theads 2889*7c478bd9Sstevel@tonic-gate */ 2890*7c478bd9Sstevel@tonic-gate conf_init(); 2891*7c478bd9Sstevel@tonic-gate 2892*7c478bd9Sstevel@tonic-gate /* 2893*7c478bd9Sstevel@tonic-gate * allocate thread stacks for the persistant threads 2894*7c478bd9Sstevel@tonic-gate */ 2895*7c478bd9Sstevel@tonic-gate nthread = (turnoff == 0) ? 4 : 2; 2896*7c478bd9Sstevel@tonic-gate 2897*7c478bd9Sstevel@tonic-gate if ((stack_ptr = alloc_stacks(nthread)) == NULL) { 2898*7c478bd9Sstevel@tonic-gate logerror("alloc_stacks failed - fatal"); 2899*7c478bd9Sstevel@tonic-gate exit(1); 2900*7c478bd9Sstevel@tonic-gate } 2901*7c478bd9Sstevel@tonic-gate 2902*7c478bd9Sstevel@tonic-gate if (Debug) { 2903*7c478bd9Sstevel@tonic-gate dumpstats(STDOUT_FILENO); 2904*7c478bd9Sstevel@tonic-gate } 2905*7c478bd9Sstevel@tonic-gate 2906*7c478bd9Sstevel@tonic-gate (void) dataq_init(&inputq); /* init the input queue */ 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate if (pthread_attr_init(&sys_attr) != 0 || 2909*7c478bd9Sstevel@tonic-gate pthread_attr_init(&log_attr) != 0 || 2910*7c478bd9Sstevel@tonic-gate pthread_attr_init(&net_attr) != 0 || 2911*7c478bd9Sstevel@tonic-gate pthread_attr_init(&hnl_attr) != 0) { 2912*7c478bd9Sstevel@tonic-gate logerror("pthread_attr_init failed - fatal"); 2913*7c478bd9Sstevel@tonic-gate exit(1); 2914*7c478bd9Sstevel@tonic-gate } 2915*7c478bd9Sstevel@tonic-gate 2916*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&sys_attr, PTHREAD_SCOPE_PROCESS); 2917*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&log_attr, PTHREAD_SCOPE_PROCESS); 2918*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&net_attr, PTHREAD_SCOPE_PROCESS); 2919*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&hnl_attr, PTHREAD_SCOPE_PROCESS); 2920*7c478bd9Sstevel@tonic-gate 2921*7c478bd9Sstevel@tonic-gate /* 1: logmsg thread */ 2922*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&log_attr, stacksize); 2923*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&log_attr, stack_ptr); 2924*7c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 2925*7c478bd9Sstevel@tonic-gate if (pthread_create(&log_thread, &log_attr, logmsg, NULL) != 0) { 2926*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 2927*7c478bd9Sstevel@tonic-gate exit(1); 2928*7c478bd9Sstevel@tonic-gate } 2929*7c478bd9Sstevel@tonic-gate 2930*7c478bd9Sstevel@tonic-gate /* 2931*7c478bd9Sstevel@tonic-gate * open the log device, and pull up all pending message 2932*7c478bd9Sstevel@tonic-gate * from the log driver. 2933*7c478bd9Sstevel@tonic-gate */ 2934*7c478bd9Sstevel@tonic-gate prepare_sys_poll(); 2935*7c478bd9Sstevel@tonic-gate 2936*7c478bd9Sstevel@tonic-gate /* 2937*7c478bd9Sstevel@tonic-gate * Now we can deliver the pending internal error messages. 2938*7c478bd9Sstevel@tonic-gate */ 2939*7c478bd9Sstevel@tonic-gate enable_errorlog(); 2940*7c478bd9Sstevel@tonic-gate 2941*7c478bd9Sstevel@tonic-gate /* 2: sys_poll thread */ 2942*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&sys_attr, stacksize); 2943*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&sys_attr, stack_ptr); 2944*7c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 2945*7c478bd9Sstevel@tonic-gate if (pthread_create(&sys_thread, &sys_attr, sys_poll, NULL) != 0) { 2946*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 2947*7c478bd9Sstevel@tonic-gate exit(1); 2948*7c478bd9Sstevel@tonic-gate } 2949*7c478bd9Sstevel@tonic-gate 2950*7c478bd9Sstevel@tonic-gate /* 2951*7c478bd9Sstevel@tonic-gate * We've started the sys_poll() and logmsg() threads. Now we are ready 2952*7c478bd9Sstevel@tonic-gate * to open the door. This cannot happen before spawning sys_poll(), 2953*7c478bd9Sstevel@tonic-gate * because after opening the door, syslog() will no longer take care of 2954*7c478bd9Sstevel@tonic-gate * LOG_CONS. Therefor, we should pull up all pending log messages and 2955*7c478bd9Sstevel@tonic-gate * activate sys_poll() before opening the door, so that log driver 2956*7c478bd9Sstevel@tonic-gate * won't drop messages. 2957*7c478bd9Sstevel@tonic-gate */ 2958*7c478bd9Sstevel@tonic-gate open_door(); 2959*7c478bd9Sstevel@tonic-gate 2960*7c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from local system\n", 2961*7c478bd9Sstevel@tonic-gate mythreadno); 2962*7c478bd9Sstevel@tonic-gate 2963*7c478bd9Sstevel@tonic-gate if (turnoff == 0) { 2964*7c478bd9Sstevel@tonic-gate /* init the hostname lookup queue */ 2965*7c478bd9Sstevel@tonic-gate (void) dataq_init(&hnlq); 2966*7c478bd9Sstevel@tonic-gate 2967*7c478bd9Sstevel@tonic-gate /* 3: hostname lookup thread */ 2968*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&hnl_attr, stacksize); 2969*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&hnl_attr, stack_ptr); 2970*7c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 2971*7c478bd9Sstevel@tonic-gate if (pthread_create(&hnl_thread, &hnl_attr, 2972*7c478bd9Sstevel@tonic-gate hostname_lookup, NULL) != 0) { 2973*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 2974*7c478bd9Sstevel@tonic-gate exit(1); 2975*7c478bd9Sstevel@tonic-gate } 2976*7c478bd9Sstevel@tonic-gate 2977*7c478bd9Sstevel@tonic-gate /* 4: net_poll thread */ 2978*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&net_attr, stacksize); 2979*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&net_attr, stack_ptr); 2980*7c478bd9Sstevel@tonic-gate stack_ptr += stacksize + redzonesize; 2981*7c478bd9Sstevel@tonic-gate 2982*7c478bd9Sstevel@tonic-gate /* grab UDP port */ 2983*7c478bd9Sstevel@tonic-gate bindnet(); 2984*7c478bd9Sstevel@tonic-gate 2985*7c478bd9Sstevel@tonic-gate if (pthread_create(&net_thread, &net_attr, net_poll, 2986*7c478bd9Sstevel@tonic-gate NULL) != 0) { 2987*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 2988*7c478bd9Sstevel@tonic-gate exit(1); 2989*7c478bd9Sstevel@tonic-gate } 2990*7c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from remote\n", 2991*7c478bd9Sstevel@tonic-gate mythreadno); 2992*7c478bd9Sstevel@tonic-gate } 2993*7c478bd9Sstevel@tonic-gate 2994*7c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&sys_attr); 2995*7c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&net_attr); 2996*7c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&log_attr); 2997*7c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&hnl_attr); 2998*7c478bd9Sstevel@tonic-gate 2999*7c478bd9Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT; 3000*7c478bd9Sstevel@tonic-gate (void) alarm((unsigned)curalarm); 3001*7c478bd9Sstevel@tonic-gate DPRINT2(2, "init(%u): Next alarm in %d seconds\n", 3002*7c478bd9Sstevel@tonic-gate mythreadno, curalarm); 3003*7c478bd9Sstevel@tonic-gate DPRINT1(1, "init(%u): syslogd: started\n", mythreadno); 3004*7c478bd9Sstevel@tonic-gate } 3005*7c478bd9Sstevel@tonic-gate 3006*7c478bd9Sstevel@tonic-gate /* 3007*7c478bd9Sstevel@tonic-gate * will print a bunch of debugging stats on 'fd' 3008*7c478bd9Sstevel@tonic-gate */ 3009*7c478bd9Sstevel@tonic-gate static void 3010*7c478bd9Sstevel@tonic-gate dumpstats(int fd) 3011*7c478bd9Sstevel@tonic-gate { 3012*7c478bd9Sstevel@tonic-gate FILE *out; 3013*7c478bd9Sstevel@tonic-gate struct filed *f; 3014*7c478bd9Sstevel@tonic-gate int i; 3015*7c478bd9Sstevel@tonic-gate char users[1024]; 3016*7c478bd9Sstevel@tonic-gate char cbuf[30]; 3017*7c478bd9Sstevel@tonic-gate char *dashes = "------------------------"; 3018*7c478bd9Sstevel@tonic-gate static int conversion_printed; 3019*7c478bd9Sstevel@tonic-gate 3020*7c478bd9Sstevel@tonic-gate if ((out = fdopen(fd, "w+")) == NULL) 3021*7c478bd9Sstevel@tonic-gate return; 3022*7c478bd9Sstevel@tonic-gate 3023*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n syslogd: version %s\n", Version); 3024*7c478bd9Sstevel@tonic-gate (void) fprintf(out, " Started: %s", ctime_r(&start_time, cbuf)); 3025*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "Input message count: system %d, network %d\n", 3026*7c478bd9Sstevel@tonic-gate sys_msg_count, net_msg_count); 3027*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "# Outputs: %d\n\n", nlogs); 3028*7c478bd9Sstevel@tonic-gate 3029*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s priority = [file, facility] %s\n\n", 3030*7c478bd9Sstevel@tonic-gate dashes, dashes); 3031*7c478bd9Sstevel@tonic-gate 3032*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 3033*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", i / 10); 3034*7c478bd9Sstevel@tonic-gate } 3035*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 3036*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 3037*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", i % 10); 3038*7c478bd9Sstevel@tonic-gate } 3039*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 3040*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 3041*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "--"); 3042*7c478bd9Sstevel@tonic-gate } 3043*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 3044*7c478bd9Sstevel@tonic-gate 3045*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 3046*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) { 3047*7c478bd9Sstevel@tonic-gate if (f->f_pmask[i] == NOPRI) 3048*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "X "); 3049*7c478bd9Sstevel@tonic-gate else 3050*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%d ", 3051*7c478bd9Sstevel@tonic-gate f->f_pmask[i]); 3052*7c478bd9Sstevel@tonic-gate } 3053*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s: ", TypeNames[f->f_type]); 3054*7c478bd9Sstevel@tonic-gate switch (f->f_type) { 3055*7c478bd9Sstevel@tonic-gate case F_FILE: 3056*7c478bd9Sstevel@tonic-gate case F_TTY: 3057*7c478bd9Sstevel@tonic-gate case F_CONSOLE: 3058*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_fname); 3059*7c478bd9Sstevel@tonic-gate break; 3060*7c478bd9Sstevel@tonic-gate case F_FORW: 3061*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_forw.f_hname); 3062*7c478bd9Sstevel@tonic-gate break; 3063*7c478bd9Sstevel@tonic-gate case F_USERS: 3064*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && 3065*7c478bd9Sstevel@tonic-gate *f->f_un.f_uname[i]; i++) { 3066*7c478bd9Sstevel@tonic-gate if (!i) 3067*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%s", 3068*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 3069*7c478bd9Sstevel@tonic-gate else 3070*7c478bd9Sstevel@tonic-gate (void) fprintf(out, ", %s", 3071*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 3072*7c478bd9Sstevel@tonic-gate } 3073*7c478bd9Sstevel@tonic-gate break; 3074*7c478bd9Sstevel@tonic-gate } 3075*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n"); 3076*7c478bd9Sstevel@tonic-gate } 3077*7c478bd9Sstevel@tonic-gate 3078*7c478bd9Sstevel@tonic-gate if (!conversion_printed) { 3079*7c478bd9Sstevel@tonic-gate fprintf(out, "\nFacilities:\n"); 3080*7c478bd9Sstevel@tonic-gate 3081*7c478bd9Sstevel@tonic-gate for (i = 0; FacNames[i].c_val != -1; i++) { 3082*7c478bd9Sstevel@tonic-gate fprintf(out, " [%02d] %s: %3d\n", i, 3083*7c478bd9Sstevel@tonic-gate FacNames[i].c_name, FacNames[i].c_val); 3084*7c478bd9Sstevel@tonic-gate } 3085*7c478bd9Sstevel@tonic-gate 3086*7c478bd9Sstevel@tonic-gate fprintf(out, "\nPriorities:\n"); 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate for (i = 0; PriNames[i].c_val != -1; i++) { 3089*7c478bd9Sstevel@tonic-gate fprintf(out, " [%02d] %s: %3d\n", i, 3090*7c478bd9Sstevel@tonic-gate PriNames[i].c_name, PriNames[i].c_val); 3091*7c478bd9Sstevel@tonic-gate } 3092*7c478bd9Sstevel@tonic-gate 3093*7c478bd9Sstevel@tonic-gate conversion_printed = 1; 3094*7c478bd9Sstevel@tonic-gate } 3095*7c478bd9Sstevel@tonic-gate 3096*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n\n\n\t\tPer File Statistics\n"); 3097*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s\tTot\tDups\tNofwd\tErrs\n", "File"); 3098*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s\t---\t----\t-----\t----\n", "----"); 3099*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 3100*7c478bd9Sstevel@tonic-gate switch (f->f_type) { 3101*7c478bd9Sstevel@tonic-gate case F_FILE: 3102*7c478bd9Sstevel@tonic-gate case F_TTY: 3103*7c478bd9Sstevel@tonic-gate case F_CONSOLE: 3104*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_fname); 3105*7c478bd9Sstevel@tonic-gate break; 3106*7c478bd9Sstevel@tonic-gate case F_WALL: 3107*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", TypeNames[f->f_type]); 3108*7c478bd9Sstevel@tonic-gate break; 3109*7c478bd9Sstevel@tonic-gate case F_FORW: 3110*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_forw.f_hname); 3111*7c478bd9Sstevel@tonic-gate break; 3112*7c478bd9Sstevel@tonic-gate case F_USERS: 3113*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && 3114*7c478bd9Sstevel@tonic-gate *f->f_un.f_uname[i]; i++) { 3115*7c478bd9Sstevel@tonic-gate if (!i) 3116*7c478bd9Sstevel@tonic-gate (void) strcpy(users, 3117*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 3118*7c478bd9Sstevel@tonic-gate else { 3119*7c478bd9Sstevel@tonic-gate (void) strcat(users, ","); 3120*7c478bd9Sstevel@tonic-gate (void) strcat(users, 3121*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i]); 3122*7c478bd9Sstevel@tonic-gate } 3123*7c478bd9Sstevel@tonic-gate } 3124*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "%-24s", users); 3125*7c478bd9Sstevel@tonic-gate break; 3126*7c478bd9Sstevel@tonic-gate } 3127*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\t%d\t%d\t%d\t%d\n", 3128*7c478bd9Sstevel@tonic-gate f->f_stat.total, f->f_stat.dups, 3129*7c478bd9Sstevel@tonic-gate f->f_stat.cantfwd, f->f_stat.errs); 3130*7c478bd9Sstevel@tonic-gate } 3131*7c478bd9Sstevel@tonic-gate (void) fprintf(out, "\n\n"); 3132*7c478bd9Sstevel@tonic-gate if (Debug && fd == 1) 3133*7c478bd9Sstevel@tonic-gate return; 3134*7c478bd9Sstevel@tonic-gate (void) fclose(out); 3135*7c478bd9Sstevel@tonic-gate } 3136*7c478bd9Sstevel@tonic-gate 3137*7c478bd9Sstevel@tonic-gate /* 3138*7c478bd9Sstevel@tonic-gate * conf_init - This routine is code seperated from the 3139*7c478bd9Sstevel@tonic-gate * init routine in order to be re-callable when we get 3140*7c478bd9Sstevel@tonic-gate * a SIGHUP signal. 3141*7c478bd9Sstevel@tonic-gate */ 3142*7c478bd9Sstevel@tonic-gate static void 3143*7c478bd9Sstevel@tonic-gate conf_init(void) 3144*7c478bd9Sstevel@tonic-gate { 3145*7c478bd9Sstevel@tonic-gate char *p; 3146*7c478bd9Sstevel@tonic-gate int i; 3147*7c478bd9Sstevel@tonic-gate struct filed *f; 3148*7c478bd9Sstevel@tonic-gate char *m4argv[4]; 3149*7c478bd9Sstevel@tonic-gate int m4argc = 0; 3150*7c478bd9Sstevel@tonic-gate conf_t cf; 3151*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3152*7c478bd9Sstevel@tonic-gate 3153*7c478bd9Sstevel@tonic-gate if (Debug) { 3154*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3155*7c478bd9Sstevel@tonic-gate } 3156*7c478bd9Sstevel@tonic-gate 3157*7c478bd9Sstevel@tonic-gate DPRINT1(2, "conf_init(%u): starting logger threads\n", 3158*7c478bd9Sstevel@tonic-gate mythreadno); 3159*7c478bd9Sstevel@tonic-gate 3160*7c478bd9Sstevel@tonic-gate m4argv[m4argc++] = "m4"; 3161*7c478bd9Sstevel@tonic-gate 3162*7c478bd9Sstevel@tonic-gate if (amiloghost() == 1) { 3163*7c478bd9Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): I am loghost\n", mythreadno); 3164*7c478bd9Sstevel@tonic-gate m4argv[m4argc++] = "-DLOGHOST=1"; 3165*7c478bd9Sstevel@tonic-gate } 3166*7c478bd9Sstevel@tonic-gate 3167*7c478bd9Sstevel@tonic-gate m4argv[m4argc++] = ConfFile; 3168*7c478bd9Sstevel@tonic-gate m4argv[m4argc] = NULL; 3169*7c478bd9Sstevel@tonic-gate 3170*7c478bd9Sstevel@tonic-gate /* 3171*7c478bd9Sstevel@tonic-gate * Make sure the configuration file and m4 exist, and then parse 3172*7c478bd9Sstevel@tonic-gate * the configuration file with m4. If any of these fail, resort 3173*7c478bd9Sstevel@tonic-gate * to our hardcoded fallback configuration. 3174*7c478bd9Sstevel@tonic-gate */ 3175*7c478bd9Sstevel@tonic-gate 3176*7c478bd9Sstevel@tonic-gate if (access(ConfFile, R_OK) == -1) { 3177*7c478bd9Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): %s does not exist\n", mythreadno, 3178*7c478bd9Sstevel@tonic-gate ConfFile); 3179*7c478bd9Sstevel@tonic-gate logerror("can't open configuration file"); 3180*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 3181*7c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 3182*7c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 3183*7c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 3184*7c478bd9Sstevel@tonic-gate nlogs = 2; 3185*7c478bd9Sstevel@tonic-gate goto nofile; 3186*7c478bd9Sstevel@tonic-gate } 3187*7c478bd9Sstevel@tonic-gate 3188*7c478bd9Sstevel@tonic-gate if (checkm4() != 0 || conf_open(&cf, "/usr/ccs/bin/m4", m4argv) == -1) { 3189*7c478bd9Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): cannot open %s\n", mythreadno, 3190*7c478bd9Sstevel@tonic-gate ConfFile); 3191*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 3192*7c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 3193*7c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 3194*7c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 3195*7c478bd9Sstevel@tonic-gate nlogs = 2; 3196*7c478bd9Sstevel@tonic-gate goto nofile; 3197*7c478bd9Sstevel@tonic-gate } 3198*7c478bd9Sstevel@tonic-gate 3199*7c478bd9Sstevel@tonic-gate /* Count the number of lines which are not blanks or comments */ 3200*7c478bd9Sstevel@tonic-gate nlogs = 0; 3201*7c478bd9Sstevel@tonic-gate while ((p = conf_read(&cf)) != NULL) { 3202*7c478bd9Sstevel@tonic-gate if (p[0] != '\0' && p[0] != '#') 3203*7c478bd9Sstevel@tonic-gate nlogs++; 3204*7c478bd9Sstevel@tonic-gate } 3205*7c478bd9Sstevel@tonic-gate 3206*7c478bd9Sstevel@tonic-gate Files = (struct filed *)malloc(sizeof (struct filed) * nlogs); 3207*7c478bd9Sstevel@tonic-gate 3208*7c478bd9Sstevel@tonic-gate if (!Files) { 3209*7c478bd9Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): malloc failed - can't " 3210*7c478bd9Sstevel@tonic-gate "allocate 'Files' array\n", mythreadno); 3211*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("loading minimum configuration"); 3212*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 3213*7c478bd9Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */ 3214*7c478bd9Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]); 3215*7c478bd9Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]); 3216*7c478bd9Sstevel@tonic-gate nlogs = 2; 3217*7c478bd9Sstevel@tonic-gate conf_close(&cf); 3218*7c478bd9Sstevel@tonic-gate goto nofile; 3219*7c478bd9Sstevel@tonic-gate } 3220*7c478bd9Sstevel@tonic-gate 3221*7c478bd9Sstevel@tonic-gate /* 3222*7c478bd9Sstevel@tonic-gate * Foreach line in the conf table, open that file. 3223*7c478bd9Sstevel@tonic-gate */ 3224*7c478bd9Sstevel@tonic-gate conf_rewind(&cf); 3225*7c478bd9Sstevel@tonic-gate f = Files; 3226*7c478bd9Sstevel@tonic-gate i = 0; 3227*7c478bd9Sstevel@tonic-gate while (((p = conf_read(&cf)) != NULL) && (f < &Files[nlogs])) { 3228*7c478bd9Sstevel@tonic-gate i++; 3229*7c478bd9Sstevel@tonic-gate /* check for end-of-section */ 3230*7c478bd9Sstevel@tonic-gate if (p[0] == '\0' || p[0] == '#') 3231*7c478bd9Sstevel@tonic-gate continue; 3232*7c478bd9Sstevel@tonic-gate 3233*7c478bd9Sstevel@tonic-gate cfline(p, i, f); 3234*7c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) 3235*7c478bd9Sstevel@tonic-gate nlogs--; 3236*7c478bd9Sstevel@tonic-gate else 3237*7c478bd9Sstevel@tonic-gate f++; 3238*7c478bd9Sstevel@tonic-gate } 3239*7c478bd9Sstevel@tonic-gate 3240*7c478bd9Sstevel@tonic-gate conf_close(&cf); 3241*7c478bd9Sstevel@tonic-gate 3242*7c478bd9Sstevel@tonic-gate /* 3243*7c478bd9Sstevel@tonic-gate * See if marks are to be written to any files. If so, set up a 3244*7c478bd9Sstevel@tonic-gate * timeout for marks. 3245*7c478bd9Sstevel@tonic-gate */ 3246*7c478bd9Sstevel@tonic-gate nofile: 3247*7c478bd9Sstevel@tonic-gate Marking = 0; 3248*7c478bd9Sstevel@tonic-gate 3249*7c478bd9Sstevel@tonic-gate /* 3250*7c478bd9Sstevel@tonic-gate * allocate thread stacks - one for each logger thread. 3251*7c478bd9Sstevel@tonic-gate */ 3252*7c478bd9Sstevel@tonic-gate if ((cstack_ptr = alloc_stacks(nlogs)) == NULL) { 3253*7c478bd9Sstevel@tonic-gate logerror("alloc_stacks failed - fatal"); 3254*7c478bd9Sstevel@tonic-gate exit(1); 3255*7c478bd9Sstevel@tonic-gate } 3256*7c478bd9Sstevel@tonic-gate 3257*7c478bd9Sstevel@tonic-gate /* And now one thread for each configured file */ 3258*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 3259*7c478bd9Sstevel@tonic-gate if (filed_init(f) != 0) { 3260*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed - fatal"); 3261*7c478bd9Sstevel@tonic-gate exit(1); 3262*7c478bd9Sstevel@tonic-gate } 3263*7c478bd9Sstevel@tonic-gate 3264*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&cft); 3265*7c478bd9Sstevel@tonic-gate ++conf_threads; 3266*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&cft); 3267*7c478bd9Sstevel@tonic-gate 3268*7c478bd9Sstevel@tonic-gate if (f->f_type != F_UNUSED && 3269*7c478bd9Sstevel@tonic-gate f->f_pmask[LOG_NFACILITIES] != NOPRI) 3270*7c478bd9Sstevel@tonic-gate Marking = 1; 3271*7c478bd9Sstevel@tonic-gate } 3272*7c478bd9Sstevel@tonic-gate } 3273*7c478bd9Sstevel@tonic-gate 3274*7c478bd9Sstevel@tonic-gate /* 3275*7c478bd9Sstevel@tonic-gate * filed init - initialize fields in a file descriptor struct 3276*7c478bd9Sstevel@tonic-gate * this is called before multiple threads are running, so no mutex 3277*7c478bd9Sstevel@tonic-gate * needs to be held at this time. 3278*7c478bd9Sstevel@tonic-gate */ 3279*7c478bd9Sstevel@tonic-gate static 3280*7c478bd9Sstevel@tonic-gate filed_init(struct filed *f) 3281*7c478bd9Sstevel@tonic-gate { 3282*7c478bd9Sstevel@tonic-gate pthread_attr_t stack_attr; 3283*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3284*7c478bd9Sstevel@tonic-gate 3285*7c478bd9Sstevel@tonic-gate if (Debug) { 3286*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3287*7c478bd9Sstevel@tonic-gate } 3288*7c478bd9Sstevel@tonic-gate 3289*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&f->filed_mutex, NULL) != 0) { 3290*7c478bd9Sstevel@tonic-gate logerror("pthread_mutex_init failed"); 3291*7c478bd9Sstevel@tonic-gate return (-1); 3292*7c478bd9Sstevel@tonic-gate } 3293*7c478bd9Sstevel@tonic-gate 3294*7c478bd9Sstevel@tonic-gate DPRINT2(5, "filed_init(%u): dataq_init for queue %p\n", 3295*7c478bd9Sstevel@tonic-gate mythreadno, &f->f_queue); 3296*7c478bd9Sstevel@tonic-gate (void) dataq_init(&f->f_queue); 3297*7c478bd9Sstevel@tonic-gate 3298*7c478bd9Sstevel@tonic-gate if (pthread_attr_init(&stack_attr) != 0) { 3299*7c478bd9Sstevel@tonic-gate logerror("pthread_attr_init failed"); 3300*7c478bd9Sstevel@tonic-gate return (-1); 3301*7c478bd9Sstevel@tonic-gate } 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstacksize(&stack_attr, stacksize); 3304*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&stack_attr, cstack_ptr); 3305*7c478bd9Sstevel@tonic-gate cstack_ptr += stacksize + redzonesize; 3306*7c478bd9Sstevel@tonic-gate 3307*7c478bd9Sstevel@tonic-gate f->f_msgflag = 0; 3308*7c478bd9Sstevel@tonic-gate f->f_prevmsg.msg[0] = '\0'; 3309*7c478bd9Sstevel@tonic-gate f->f_prevmsg.flags = 0; 3310*7c478bd9Sstevel@tonic-gate f->f_prevmsg.pri = 0; 3311*7c478bd9Sstevel@tonic-gate f->f_prevmsg.host[0] = '\0'; 3312*7c478bd9Sstevel@tonic-gate 3313*7c478bd9Sstevel@tonic-gate f->f_current.msg[0] = '\0'; 3314*7c478bd9Sstevel@tonic-gate f->f_current.flags = 0; 3315*7c478bd9Sstevel@tonic-gate f->f_current.pri = 0; 3316*7c478bd9Sstevel@tonic-gate f->f_current.host[0] = '\0'; 3317*7c478bd9Sstevel@tonic-gate 3318*7c478bd9Sstevel@tonic-gate f->f_prevcount = 0; 3319*7c478bd9Sstevel@tonic-gate 3320*7c478bd9Sstevel@tonic-gate f->f_stat.flag = 0; 3321*7c478bd9Sstevel@tonic-gate f->f_stat.total = 0; 3322*7c478bd9Sstevel@tonic-gate f->f_stat.dups = 0; 3323*7c478bd9Sstevel@tonic-gate f->f_stat.cantfwd = 0; 3324*7c478bd9Sstevel@tonic-gate f->f_stat.errs = 0; 3325*7c478bd9Sstevel@tonic-gate 3326*7c478bd9Sstevel@tonic-gate if (pthread_create(&f->f_thread, NULL, logit, (void *)f) != 0) { 3327*7c478bd9Sstevel@tonic-gate logerror("pthread_create failed"); 3328*7c478bd9Sstevel@tonic-gate pthread_attr_destroy(&stack_attr); 3329*7c478bd9Sstevel@tonic-gate return (-1); 3330*7c478bd9Sstevel@tonic-gate } 3331*7c478bd9Sstevel@tonic-gate 3332*7c478bd9Sstevel@tonic-gate pthread_attr_destroy(&stack_attr); 3333*7c478bd9Sstevel@tonic-gate return (0); 3334*7c478bd9Sstevel@tonic-gate } 3335*7c478bd9Sstevel@tonic-gate 3336*7c478bd9Sstevel@tonic-gate 3337*7c478bd9Sstevel@tonic-gate /* 3338*7c478bd9Sstevel@tonic-gate * Crack a configuration file line 3339*7c478bd9Sstevel@tonic-gate */ 3340*7c478bd9Sstevel@tonic-gate static void 3341*7c478bd9Sstevel@tonic-gate cfline(char *line, int lineno, struct filed *f) 3342*7c478bd9Sstevel@tonic-gate { 3343*7c478bd9Sstevel@tonic-gate char *p; 3344*7c478bd9Sstevel@tonic-gate char *q; 3345*7c478bd9Sstevel@tonic-gate int i; 3346*7c478bd9Sstevel@tonic-gate char *bp; 3347*7c478bd9Sstevel@tonic-gate int pri; 3348*7c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 3349*7c478bd9Sstevel@tonic-gate char ebuf[SYS_NMLN+1+40]; 3350*7c478bd9Sstevel@tonic-gate mode_t fmode, omode = O_WRONLY|O_APPEND|O_NOCTTY; 3351*7c478bd9Sstevel@tonic-gate struct stat64 sbuf; 3352*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3353*7c478bd9Sstevel@tonic-gate 3354*7c478bd9Sstevel@tonic-gate if (Debug) { 3355*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3356*7c478bd9Sstevel@tonic-gate } 3357*7c478bd9Sstevel@tonic-gate 3358*7c478bd9Sstevel@tonic-gate DPRINT2(1, "cfline(%u): (%s)\n", mythreadno, line); 3359*7c478bd9Sstevel@tonic-gate 3360*7c478bd9Sstevel@tonic-gate errno = 0; /* keep sys_errlist stuff out of logerror messages */ 3361*7c478bd9Sstevel@tonic-gate 3362*7c478bd9Sstevel@tonic-gate /* clear out file entry */ 3363*7c478bd9Sstevel@tonic-gate bzero((char *)f, sizeof (*f)); 3364*7c478bd9Sstevel@tonic-gate for (i = 0; i <= LOG_NFACILITIES; i++) 3365*7c478bd9Sstevel@tonic-gate f->f_pmask[i] = NOPRI; 3366*7c478bd9Sstevel@tonic-gate 3367*7c478bd9Sstevel@tonic-gate /* scan through the list of selectors */ 3368*7c478bd9Sstevel@tonic-gate for (p = line; *p && *p != '\t'; ) { 3369*7c478bd9Sstevel@tonic-gate 3370*7c478bd9Sstevel@tonic-gate /* find the end of this facility name list */ 3371*7c478bd9Sstevel@tonic-gate for (q = p; *q && *q != '\t' && *q++ != '.'; ) 3372*7c478bd9Sstevel@tonic-gate continue; 3373*7c478bd9Sstevel@tonic-gate 3374*7c478bd9Sstevel@tonic-gate /* collect priority name */ 3375*7c478bd9Sstevel@tonic-gate for (bp = buf; *q && !strchr("\t,;", *q); ) 3376*7c478bd9Sstevel@tonic-gate *bp++ = *q++; 3377*7c478bd9Sstevel@tonic-gate *bp = '\0'; 3378*7c478bd9Sstevel@tonic-gate 3379*7c478bd9Sstevel@tonic-gate /* skip cruft */ 3380*7c478bd9Sstevel@tonic-gate while (strchr(", ;", *q)) 3381*7c478bd9Sstevel@tonic-gate q++; 3382*7c478bd9Sstevel@tonic-gate 3383*7c478bd9Sstevel@tonic-gate /* decode priority name */ 3384*7c478bd9Sstevel@tonic-gate pri = decode(buf, PriNames); 3385*7c478bd9Sstevel@tonic-gate if (pri < 0) { 3386*7c478bd9Sstevel@tonic-gate logerror("line %d: unknown priority name \"%s\"", 3387*7c478bd9Sstevel@tonic-gate lineno, buf); 3388*7c478bd9Sstevel@tonic-gate return; 3389*7c478bd9Sstevel@tonic-gate } 3390*7c478bd9Sstevel@tonic-gate 3391*7c478bd9Sstevel@tonic-gate /* scan facilities */ 3392*7c478bd9Sstevel@tonic-gate while (*p && !strchr("\t.;", *p)) { 3393*7c478bd9Sstevel@tonic-gate for (bp = buf; *p && !strchr("\t,;.", *p); ) 3394*7c478bd9Sstevel@tonic-gate *bp++ = *p++; 3395*7c478bd9Sstevel@tonic-gate *bp = '\0'; 3396*7c478bd9Sstevel@tonic-gate if (*buf == '*') 3397*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES; i++) 3398*7c478bd9Sstevel@tonic-gate f->f_pmask[i] = (uchar_t)pri; 3399*7c478bd9Sstevel@tonic-gate else { 3400*7c478bd9Sstevel@tonic-gate i = decode(buf, FacNames); 3401*7c478bd9Sstevel@tonic-gate if (i < 0) { 3402*7c478bd9Sstevel@tonic-gate logerror("line %d: unknown facility" 3403*7c478bd9Sstevel@tonic-gate " name \"%s\"", lineno, buf); 3404*7c478bd9Sstevel@tonic-gate return; 3405*7c478bd9Sstevel@tonic-gate } 3406*7c478bd9Sstevel@tonic-gate f->f_pmask[i >> 3] = (uchar_t)pri; 3407*7c478bd9Sstevel@tonic-gate } 3408*7c478bd9Sstevel@tonic-gate while (*p == ',' || *p == ' ') 3409*7c478bd9Sstevel@tonic-gate p++; 3410*7c478bd9Sstevel@tonic-gate } 3411*7c478bd9Sstevel@tonic-gate 3412*7c478bd9Sstevel@tonic-gate p = q; 3413*7c478bd9Sstevel@tonic-gate } 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate /* skip to action part */ 3416*7c478bd9Sstevel@tonic-gate while (*p == '\t' || *p == ' ') 3417*7c478bd9Sstevel@tonic-gate p++; 3418*7c478bd9Sstevel@tonic-gate 3419*7c478bd9Sstevel@tonic-gate switch (*p) { 3420*7c478bd9Sstevel@tonic-gate case '\0': 3421*7c478bd9Sstevel@tonic-gate errno = 0; 3422*7c478bd9Sstevel@tonic-gate logerror("line %d: no action part", lineno); 3423*7c478bd9Sstevel@tonic-gate break; 3424*7c478bd9Sstevel@tonic-gate 3425*7c478bd9Sstevel@tonic-gate case '@': 3426*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_forw.f_hname, ++p, SYS_NMLN); 3427*7c478bd9Sstevel@tonic-gate if (logforward(f, ebuf) != 0) { 3428*7c478bd9Sstevel@tonic-gate logerror("line %d: %s", lineno, ebuf); 3429*7c478bd9Sstevel@tonic-gate break; 3430*7c478bd9Sstevel@tonic-gate } 3431*7c478bd9Sstevel@tonic-gate f->f_type = F_FORW; 3432*7c478bd9Sstevel@tonic-gate break; 3433*7c478bd9Sstevel@tonic-gate 3434*7c478bd9Sstevel@tonic-gate case '/': 3435*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_fname, p, MAXPATHLEN); 3436*7c478bd9Sstevel@tonic-gate if (stat64(p, &sbuf) < 0) { 3437*7c478bd9Sstevel@tonic-gate logerror(p); 3438*7c478bd9Sstevel@tonic-gate break; 3439*7c478bd9Sstevel@tonic-gate } 3440*7c478bd9Sstevel@tonic-gate /* 3441*7c478bd9Sstevel@tonic-gate * don't block trying to open a pipe 3442*7c478bd9Sstevel@tonic-gate * with no reader on the other end 3443*7c478bd9Sstevel@tonic-gate */ 3444*7c478bd9Sstevel@tonic-gate fmode = 0; /* reset each pass */ 3445*7c478bd9Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode)) 3446*7c478bd9Sstevel@tonic-gate fmode = O_NONBLOCK; 3447*7c478bd9Sstevel@tonic-gate 3448*7c478bd9Sstevel@tonic-gate f->f_file = open64(p, omode|fmode); 3449*7c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 3450*7c478bd9Sstevel@tonic-gate if (fmode && errno == ENXIO) { 3451*7c478bd9Sstevel@tonic-gate errno = 0; 3452*7c478bd9Sstevel@tonic-gate logerror("%s - no reader", p); 3453*7c478bd9Sstevel@tonic-gate } else 3454*7c478bd9Sstevel@tonic-gate logerror(p); 3455*7c478bd9Sstevel@tonic-gate break; 3456*7c478bd9Sstevel@tonic-gate } 3457*7c478bd9Sstevel@tonic-gate 3458*7c478bd9Sstevel@tonic-gate /* 3459*7c478bd9Sstevel@tonic-gate * Fifos are initially opened NONBLOCK 3460*7c478bd9Sstevel@tonic-gate * to insure we don't hang, but once 3461*7c478bd9Sstevel@tonic-gate * we are open, we need to change the 3462*7c478bd9Sstevel@tonic-gate * behavior back to blocking, otherwise 3463*7c478bd9Sstevel@tonic-gate * we may get write errors, and the log 3464*7c478bd9Sstevel@tonic-gate * will get closed down the line. 3465*7c478bd9Sstevel@tonic-gate */ 3466*7c478bd9Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode)) 3467*7c478bd9Sstevel@tonic-gate (void) fcntl(f->f_file, F_SETFL, omode); 3468*7c478bd9Sstevel@tonic-gate 3469*7c478bd9Sstevel@tonic-gate if (isatty(f->f_file)) { 3470*7c478bd9Sstevel@tonic-gate f->f_type = F_TTY; 3471*7c478bd9Sstevel@tonic-gate untty(); 3472*7c478bd9Sstevel@tonic-gate } else 3473*7c478bd9Sstevel@tonic-gate f->f_type = F_FILE; 3474*7c478bd9Sstevel@tonic-gate 3475*7c478bd9Sstevel@tonic-gate if ((strcmp(p, ctty) == 0) || (strcmp(p, sysmsg) == 0)) 3476*7c478bd9Sstevel@tonic-gate f->f_type = F_CONSOLE; 3477*7c478bd9Sstevel@tonic-gate break; 3478*7c478bd9Sstevel@tonic-gate 3479*7c478bd9Sstevel@tonic-gate case '*': 3480*7c478bd9Sstevel@tonic-gate f->f_type = F_WALL; 3481*7c478bd9Sstevel@tonic-gate break; 3482*7c478bd9Sstevel@tonic-gate 3483*7c478bd9Sstevel@tonic-gate default: 3484*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && *p; i++) { 3485*7c478bd9Sstevel@tonic-gate for (q = p; *q && *q != ','; ) 3486*7c478bd9Sstevel@tonic-gate q++; 3487*7c478bd9Sstevel@tonic-gate (void) strlcpy(f->f_un.f_uname[i], p, UNAMESZ); 3488*7c478bd9Sstevel@tonic-gate if ((q - p) > UNAMESZ) 3489*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i][UNAMESZ] = '\0'; 3490*7c478bd9Sstevel@tonic-gate else 3491*7c478bd9Sstevel@tonic-gate f->f_un.f_uname[i][q - p] = '\0'; 3492*7c478bd9Sstevel@tonic-gate while (*q == ',' || *q == ' ') 3493*7c478bd9Sstevel@tonic-gate q++; 3494*7c478bd9Sstevel@tonic-gate p = q; 3495*7c478bd9Sstevel@tonic-gate } 3496*7c478bd9Sstevel@tonic-gate f->f_type = F_USERS; 3497*7c478bd9Sstevel@tonic-gate break; 3498*7c478bd9Sstevel@tonic-gate } 3499*7c478bd9Sstevel@tonic-gate f->f_orig_type = f->f_type; 3500*7c478bd9Sstevel@tonic-gate } 3501*7c478bd9Sstevel@tonic-gate 3502*7c478bd9Sstevel@tonic-gate 3503*7c478bd9Sstevel@tonic-gate /* 3504*7c478bd9Sstevel@tonic-gate * Decode a symbolic name to a numeric value 3505*7c478bd9Sstevel@tonic-gate */ 3506*7c478bd9Sstevel@tonic-gate static int 3507*7c478bd9Sstevel@tonic-gate decode(char *name, struct code *codetab) 3508*7c478bd9Sstevel@tonic-gate { 3509*7c478bd9Sstevel@tonic-gate struct code *c; 3510*7c478bd9Sstevel@tonic-gate char *p; 3511*7c478bd9Sstevel@tonic-gate char buf[40]; 3512*7c478bd9Sstevel@tonic-gate 3513*7c478bd9Sstevel@tonic-gate if (isdigit(*name)) 3514*7c478bd9Sstevel@tonic-gate return (atoi(name)); 3515*7c478bd9Sstevel@tonic-gate 3516*7c478bd9Sstevel@tonic-gate (void) strncpy(buf, name, sizeof (buf) - 1); 3517*7c478bd9Sstevel@tonic-gate for (p = buf; *p; p++) 3518*7c478bd9Sstevel@tonic-gate if (isupper(*p)) 3519*7c478bd9Sstevel@tonic-gate *p = tolower(*p); 3520*7c478bd9Sstevel@tonic-gate for (c = codetab; c->c_name; c++) 3521*7c478bd9Sstevel@tonic-gate if (!(strcmp(buf, c->c_name))) 3522*7c478bd9Sstevel@tonic-gate return (c->c_val); 3523*7c478bd9Sstevel@tonic-gate 3524*7c478bd9Sstevel@tonic-gate return (-1); 3525*7c478bd9Sstevel@tonic-gate } 3526*7c478bd9Sstevel@tonic-gate 3527*7c478bd9Sstevel@tonic-gate static int 3528*7c478bd9Sstevel@tonic-gate ismyaddr(struct netbuf *nbp) 3529*7c478bd9Sstevel@tonic-gate { 3530*7c478bd9Sstevel@tonic-gate int i; 3531*7c478bd9Sstevel@tonic-gate 3532*7c478bd9Sstevel@tonic-gate if (nbp == NULL) 3533*7c478bd9Sstevel@tonic-gate return (0); 3534*7c478bd9Sstevel@tonic-gate 3535*7c478bd9Sstevel@tonic-gate for (i = 1; i < Ninputs; i++) { 3536*7c478bd9Sstevel@tonic-gate if (same_addr(nbp, Myaddrs[i])) 3537*7c478bd9Sstevel@tonic-gate return (1); 3538*7c478bd9Sstevel@tonic-gate } 3539*7c478bd9Sstevel@tonic-gate return (0); 3540*7c478bd9Sstevel@tonic-gate } 3541*7c478bd9Sstevel@tonic-gate 3542*7c478bd9Sstevel@tonic-gate static void 3543*7c478bd9Sstevel@tonic-gate getnets(void) 3544*7c478bd9Sstevel@tonic-gate { 3545*7c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 3546*7c478bd9Sstevel@tonic-gate struct netconfig *ncp; 3547*7c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 3548*7c478bd9Sstevel@tonic-gate struct netbuf *nbp; 3549*7c478bd9Sstevel@tonic-gate int i, inputs; 3550*7c478bd9Sstevel@tonic-gate void *handle; 3551*7c478bd9Sstevel@tonic-gate char *uap; 3552*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3553*7c478bd9Sstevel@tonic-gate 3554*7c478bd9Sstevel@tonic-gate if (Debug) { 3555*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3556*7c478bd9Sstevel@tonic-gate } 3557*7c478bd9Sstevel@tonic-gate 3558*7c478bd9Sstevel@tonic-gate if (turnoff) { 3559*7c478bd9Sstevel@tonic-gate DPRINT1(1, "getnets(%u): network is being turned off\n", 3560*7c478bd9Sstevel@tonic-gate mythreadno); 3561*7c478bd9Sstevel@tonic-gate return; 3562*7c478bd9Sstevel@tonic-gate } 3563*7c478bd9Sstevel@tonic-gate 3564*7c478bd9Sstevel@tonic-gate hs.h_host = HOST_SELF; 3565*7c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 3566*7c478bd9Sstevel@tonic-gate 3567*7c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 3568*7c478bd9Sstevel@tonic-gate return; 3569*7c478bd9Sstevel@tonic-gate } 3570*7c478bd9Sstevel@tonic-gate 3571*7c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 3572*7c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 3573*7c478bd9Sstevel@tonic-gate continue; 3574*7c478bd9Sstevel@tonic-gate } 3575*7c478bd9Sstevel@tonic-gate 3576*7c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) { 3577*7c478bd9Sstevel@tonic-gate continue; 3578*7c478bd9Sstevel@tonic-gate } 3579*7c478bd9Sstevel@tonic-gate 3580*7c478bd9Sstevel@tonic-gate if (nap == NULL || nap->n_cnt <= 0) { 3581*7c478bd9Sstevel@tonic-gate DPRINT1(1, "getnets(%u): found no address\n", 3582*7c478bd9Sstevel@tonic-gate mythreadno); 3583*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3584*7c478bd9Sstevel@tonic-gate continue; 3585*7c478bd9Sstevel@tonic-gate } 3586*7c478bd9Sstevel@tonic-gate 3587*7c478bd9Sstevel@tonic-gate if (Debug) { 3588*7c478bd9Sstevel@tonic-gate DPRINT2(1, "getnets(%u): found %d addresses", 3589*7c478bd9Sstevel@tonic-gate mythreadno, nap->n_cnt); 3590*7c478bd9Sstevel@tonic-gate DPRINT0(1, ", they are: "); 3591*7c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 3592*7c478bd9Sstevel@tonic-gate 3593*7c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) { 3594*7c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) { 3595*7c478bd9Sstevel@tonic-gate DPRINT1(1, "%s ", uap); 3596*7c478bd9Sstevel@tonic-gate free(uap); 3597*7c478bd9Sstevel@tonic-gate } 3598*7c478bd9Sstevel@tonic-gate nbp++; 3599*7c478bd9Sstevel@tonic-gate } 3600*7c478bd9Sstevel@tonic-gate 3601*7c478bd9Sstevel@tonic-gate DPRINT0(1, "\n"); 3602*7c478bd9Sstevel@tonic-gate } 3603*7c478bd9Sstevel@tonic-gate 3604*7c478bd9Sstevel@tonic-gate inputs = Ninputs + nap->n_cnt; 3605*7c478bd9Sstevel@tonic-gate 3606*7c478bd9Sstevel@tonic-gate Nfd = realloc(Nfd, inputs * sizeof (struct pollfd)); 3607*7c478bd9Sstevel@tonic-gate Ncf = realloc(Ncf, inputs * sizeof (struct netconfig)); 3608*7c478bd9Sstevel@tonic-gate Myaddrs = realloc(Myaddrs, inputs * sizeof (struct netbuf *)); 3609*7c478bd9Sstevel@tonic-gate Udp = realloc(Udp, inputs * sizeof (struct t_unitdata *)); 3610*7c478bd9Sstevel@tonic-gate Errp = realloc(Errp, inputs * sizeof (struct t_uderr *)); 3611*7c478bd9Sstevel@tonic-gate 3612*7c478bd9Sstevel@tonic-gate /* 3613*7c478bd9Sstevel@tonic-gate * all malloc failures here are fatal 3614*7c478bd9Sstevel@tonic-gate */ 3615*7c478bd9Sstevel@tonic-gate if (Nfd == NULL || Ncf == NULL || Myaddrs == NULL || 3616*7c478bd9Sstevel@tonic-gate Udp == NULL || Errp == NULL) { 3617*7c478bd9Sstevel@tonic-gate MALLOC_FAIL_EXIT; 3618*7c478bd9Sstevel@tonic-gate } 3619*7c478bd9Sstevel@tonic-gate 3620*7c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 3621*7c478bd9Sstevel@tonic-gate 3622*7c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++, nbp++) { 3623*7c478bd9Sstevel@tonic-gate char ebuf[128]; 3624*7c478bd9Sstevel@tonic-gate 3625*7c478bd9Sstevel@tonic-gate if (addnet(ncp, nbp) == 0) { 3626*7c478bd9Sstevel@tonic-gate /* no error */ 3627*7c478bd9Sstevel@tonic-gate continue; 3628*7c478bd9Sstevel@tonic-gate } 3629*7c478bd9Sstevel@tonic-gate 3630*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to configure syslog port"); 3631*7c478bd9Sstevel@tonic-gate 3632*7c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) { 3633*7c478bd9Sstevel@tonic-gate size_t l = strlen(ebuf); 3634*7c478bd9Sstevel@tonic-gate (void) snprintf(ebuf + l, sizeof (ebuf) - l, 3635*7c478bd9Sstevel@tonic-gate " for %s", uap); 3636*7c478bd9Sstevel@tonic-gate } 3637*7c478bd9Sstevel@tonic-gate 3638*7c478bd9Sstevel@tonic-gate DPRINT2(1, "getnets(%u): %s", 3639*7c478bd9Sstevel@tonic-gate mythreadno, ebuf); 3640*7c478bd9Sstevel@tonic-gate 3641*7c478bd9Sstevel@tonic-gate if (uap) { 3642*7c478bd9Sstevel@tonic-gate free(uap); 3643*7c478bd9Sstevel@tonic-gate } 3644*7c478bd9Sstevel@tonic-gate 3645*7c478bd9Sstevel@tonic-gate logerror(ebuf); 3646*7c478bd9Sstevel@tonic-gate /* 3647*7c478bd9Sstevel@tonic-gate * Here maybe syslogd can quit. However, syslogd 3648*7c478bd9Sstevel@tonic-gate * has been ignoring this error and keep running. 3649*7c478bd9Sstevel@tonic-gate * So we won't break it. 3650*7c478bd9Sstevel@tonic-gate */ 3651*7c478bd9Sstevel@tonic-gate } 3652*7c478bd9Sstevel@tonic-gate 3653*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3654*7c478bd9Sstevel@tonic-gate } 3655*7c478bd9Sstevel@tonic-gate 3656*7c478bd9Sstevel@tonic-gate (void) endnetconfig(handle); 3657*7c478bd9Sstevel@tonic-gate } 3658*7c478bd9Sstevel@tonic-gate 3659*7c478bd9Sstevel@tonic-gate /* 3660*7c478bd9Sstevel@tonic-gate * Open the network device, and allocate necessary resources. 3661*7c478bd9Sstevel@tonic-gate * Myaddrs will also be filled, so that we can call ismyaddr() before 3662*7c478bd9Sstevel@tonic-gate * being bound to the network. 3663*7c478bd9Sstevel@tonic-gate */ 3664*7c478bd9Sstevel@tonic-gate static int 3665*7c478bd9Sstevel@tonic-gate addnet(struct netconfig *ncp, struct netbuf *nbp) 3666*7c478bd9Sstevel@tonic-gate { 3667*7c478bd9Sstevel@tonic-gate int fd; 3668*7c478bd9Sstevel@tonic-gate struct netbuf *bp; 3669*7c478bd9Sstevel@tonic-gate 3670*7c478bd9Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL); 3671*7c478bd9Sstevel@tonic-gate 3672*7c478bd9Sstevel@tonic-gate if (fd < 0) { 3673*7c478bd9Sstevel@tonic-gate return (1); 3674*7c478bd9Sstevel@tonic-gate } 3675*7c478bd9Sstevel@tonic-gate 3676*7c478bd9Sstevel@tonic-gate (void) memcpy(&Ncf[Ninputs], ncp, sizeof (struct netconfig)); 3677*7c478bd9Sstevel@tonic-gate 3678*7c478bd9Sstevel@tonic-gate /*LINTED*/ 3679*7c478bd9Sstevel@tonic-gate Udp[Ninputs] = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR); 3680*7c478bd9Sstevel@tonic-gate 3681*7c478bd9Sstevel@tonic-gate if (Udp[Ninputs] == NULL) { 3682*7c478bd9Sstevel@tonic-gate t_close(fd); 3683*7c478bd9Sstevel@tonic-gate return (1); 3684*7c478bd9Sstevel@tonic-gate } 3685*7c478bd9Sstevel@tonic-gate 3686*7c478bd9Sstevel@tonic-gate /*LINTED*/ 3687*7c478bd9Sstevel@tonic-gate Errp[Ninputs] = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ADDR); 3688*7c478bd9Sstevel@tonic-gate 3689*7c478bd9Sstevel@tonic-gate if (Errp[Ninputs] == NULL) { 3690*7c478bd9Sstevel@tonic-gate t_close(fd); 3691*7c478bd9Sstevel@tonic-gate t_free((char *)Udp[Ninputs], T_UNITDATA); 3692*7c478bd9Sstevel@tonic-gate return (1); 3693*7c478bd9Sstevel@tonic-gate } 3694*7c478bd9Sstevel@tonic-gate 3695*7c478bd9Sstevel@tonic-gate if ((bp = malloc(sizeof (struct netbuf))) == NULL || 3696*7c478bd9Sstevel@tonic-gate (bp->buf = malloc(nbp->len)) == NULL) { 3697*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("allocating address buffer"); 3698*7c478bd9Sstevel@tonic-gate t_close(fd); 3699*7c478bd9Sstevel@tonic-gate t_free((char *)Udp[Ninputs], T_UNITDATA); 3700*7c478bd9Sstevel@tonic-gate t_free((char *)Errp[Ninputs], T_UDERROR); 3701*7c478bd9Sstevel@tonic-gate 3702*7c478bd9Sstevel@tonic-gate if (bp) { 3703*7c478bd9Sstevel@tonic-gate free(bp); 3704*7c478bd9Sstevel@tonic-gate } 3705*7c478bd9Sstevel@tonic-gate 3706*7c478bd9Sstevel@tonic-gate return (1); 3707*7c478bd9Sstevel@tonic-gate } 3708*7c478bd9Sstevel@tonic-gate 3709*7c478bd9Sstevel@tonic-gate bp->len = nbp->len; 3710*7c478bd9Sstevel@tonic-gate (void) memcpy(bp->buf, nbp->buf, nbp->len); 3711*7c478bd9Sstevel@tonic-gate Myaddrs[Ninputs] = bp; 3712*7c478bd9Sstevel@tonic-gate 3713*7c478bd9Sstevel@tonic-gate Nfd[Ninputs].fd = fd; 3714*7c478bd9Sstevel@tonic-gate Nfd[Ninputs].events = POLLIN; 3715*7c478bd9Sstevel@tonic-gate Ninputs++; 3716*7c478bd9Sstevel@tonic-gate return (0); 3717*7c478bd9Sstevel@tonic-gate } 3718*7c478bd9Sstevel@tonic-gate 3719*7c478bd9Sstevel@tonic-gate /* 3720*7c478bd9Sstevel@tonic-gate * Allocate UDP buffer to minimize packet loss. 3721*7c478bd9Sstevel@tonic-gate */ 3722*7c478bd9Sstevel@tonic-gate static void 3723*7c478bd9Sstevel@tonic-gate set_udp_buffer(int fd) 3724*7c478bd9Sstevel@tonic-gate { 3725*7c478bd9Sstevel@tonic-gate struct t_optmgmt req, resp; 3726*7c478bd9Sstevel@tonic-gate struct opthdr *opt; 3727*7c478bd9Sstevel@tonic-gate size_t optsize, bsize = 256 * 1024; 3728*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3729*7c478bd9Sstevel@tonic-gate 3730*7c478bd9Sstevel@tonic-gate if (Debug) { 3731*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3732*7c478bd9Sstevel@tonic-gate } 3733*7c478bd9Sstevel@tonic-gate 3734*7c478bd9Sstevel@tonic-gate optsize = sizeof (struct opthdr) + sizeof (int); 3735*7c478bd9Sstevel@tonic-gate if ((opt = malloc(optsize)) == NULL) { 3736*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("will have no udp buffer"); 3737*7c478bd9Sstevel@tonic-gate return; 3738*7c478bd9Sstevel@tonic-gate } 3739*7c478bd9Sstevel@tonic-gate opt->level = SOL_SOCKET; 3740*7c478bd9Sstevel@tonic-gate opt->name = SO_RCVBUF; 3741*7c478bd9Sstevel@tonic-gate opt->len = sizeof (int); 3742*7c478bd9Sstevel@tonic-gate *(int *)(opt + 1) = bsize; 3743*7c478bd9Sstevel@tonic-gate 3744*7c478bd9Sstevel@tonic-gate req.flags = T_NEGOTIATE; 3745*7c478bd9Sstevel@tonic-gate req.opt.len = optsize; 3746*7c478bd9Sstevel@tonic-gate req.opt.buf = (char *)opt; 3747*7c478bd9Sstevel@tonic-gate 3748*7c478bd9Sstevel@tonic-gate resp.flags = 0; 3749*7c478bd9Sstevel@tonic-gate resp.opt.maxlen = optsize; 3750*7c478bd9Sstevel@tonic-gate resp.opt.buf = (char *)opt; 3751*7c478bd9Sstevel@tonic-gate 3752*7c478bd9Sstevel@tonic-gate while (t_optmgmt(fd, &req, &resp) == -1 || resp.flags != T_SUCCESS) { 3753*7c478bd9Sstevel@tonic-gate if (t_errno != TSYSERR || errno != ENOBUFS) { 3754*7c478bd9Sstevel@tonic-gate bsize = 0; 3755*7c478bd9Sstevel@tonic-gate break; 3756*7c478bd9Sstevel@tonic-gate } 3757*7c478bd9Sstevel@tonic-gate bsize >>= 1; 3758*7c478bd9Sstevel@tonic-gate if (bsize < 8192) { 3759*7c478bd9Sstevel@tonic-gate break; 3760*7c478bd9Sstevel@tonic-gate } 3761*7c478bd9Sstevel@tonic-gate *(int *)(opt + 1) = bsize; 3762*7c478bd9Sstevel@tonic-gate } 3763*7c478bd9Sstevel@tonic-gate if (bsize == 0) { 3764*7c478bd9Sstevel@tonic-gate logerror("failed to allocate UDP buffer"); 3765*7c478bd9Sstevel@tonic-gate } 3766*7c478bd9Sstevel@tonic-gate DPRINT3(1, "set_udp_buffer(%u): allocate %d for fd %d\n", 3767*7c478bd9Sstevel@tonic-gate mythreadno, bsize, fd); 3768*7c478bd9Sstevel@tonic-gate free(opt); 3769*7c478bd9Sstevel@tonic-gate } 3770*7c478bd9Sstevel@tonic-gate 3771*7c478bd9Sstevel@tonic-gate /* 3772*7c478bd9Sstevel@tonic-gate * Attach the network, and allocate UDP buffer for the interface. 3773*7c478bd9Sstevel@tonic-gate */ 3774*7c478bd9Sstevel@tonic-gate static void 3775*7c478bd9Sstevel@tonic-gate bindnet(void) 3776*7c478bd9Sstevel@tonic-gate { 3777*7c478bd9Sstevel@tonic-gate struct t_bind bind, *bound; 3778*7c478bd9Sstevel@tonic-gate int cnt, i; 3779*7c478bd9Sstevel@tonic-gate char *uap; 3780*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3781*7c478bd9Sstevel@tonic-gate 3782*7c478bd9Sstevel@tonic-gate if (Debug) { 3783*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3784*7c478bd9Sstevel@tonic-gate } 3785*7c478bd9Sstevel@tonic-gate 3786*7c478bd9Sstevel@tonic-gate cnt = 0; 3787*7c478bd9Sstevel@tonic-gate 3788*7c478bd9Sstevel@tonic-gate while (cnt < Ninputs) { 3789*7c478bd9Sstevel@tonic-gate char ebuf[128]; 3790*7c478bd9Sstevel@tonic-gate 3791*7c478bd9Sstevel@tonic-gate /*LINTED*/ 3792*7c478bd9Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(Nfd[cnt].fd, T_BIND, T_ADDR); 3793*7c478bd9Sstevel@tonic-gate bind.addr = *Myaddrs[cnt]; 3794*7c478bd9Sstevel@tonic-gate bind.qlen = 0; 3795*7c478bd9Sstevel@tonic-gate 3796*7c478bd9Sstevel@tonic-gate if (t_bind(Nfd[cnt].fd, &bind, bound) == 0) { 3797*7c478bd9Sstevel@tonic-gate if (same_addr(&bind.addr, &bound->addr)) { 3798*7c478bd9Sstevel@tonic-gate t_free((char *)bound, T_BIND); 3799*7c478bd9Sstevel@tonic-gate set_udp_buffer(Nfd[cnt].fd); 3800*7c478bd9Sstevel@tonic-gate cnt++; 3801*7c478bd9Sstevel@tonic-gate continue; 3802*7c478bd9Sstevel@tonic-gate } 3803*7c478bd9Sstevel@tonic-gate } 3804*7c478bd9Sstevel@tonic-gate 3805*7c478bd9Sstevel@tonic-gate /* failed to bind port */ 3806*7c478bd9Sstevel@tonic-gate t_free((char *)bound, T_BIND); 3807*7c478bd9Sstevel@tonic-gate 3808*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to bind syslog port"); 3809*7c478bd9Sstevel@tonic-gate 3810*7c478bd9Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[cnt], Myaddrs[cnt]); 3811*7c478bd9Sstevel@tonic-gate if (uap) { 3812*7c478bd9Sstevel@tonic-gate i = strlen(ebuf); 3813*7c478bd9Sstevel@tonic-gate (void) snprintf(ebuf + i, sizeof (ebuf) - i, 3814*7c478bd9Sstevel@tonic-gate " for %s", uap); 3815*7c478bd9Sstevel@tonic-gate } 3816*7c478bd9Sstevel@tonic-gate 3817*7c478bd9Sstevel@tonic-gate DPRINT2(1, "bindnet(%u): failed to bind port (%s)\n", 3818*7c478bd9Sstevel@tonic-gate mythreadno, uap ? uap : "<unknown>"); 3819*7c478bd9Sstevel@tonic-gate 3820*7c478bd9Sstevel@tonic-gate if (uap) { 3821*7c478bd9Sstevel@tonic-gate free(uap); 3822*7c478bd9Sstevel@tonic-gate } 3823*7c478bd9Sstevel@tonic-gate 3824*7c478bd9Sstevel@tonic-gate errno = 0; 3825*7c478bd9Sstevel@tonic-gate logerror(ebuf); 3826*7c478bd9Sstevel@tonic-gate 3827*7c478bd9Sstevel@tonic-gate t_close(Nfd[cnt].fd); 3828*7c478bd9Sstevel@tonic-gate free(Myaddrs[cnt]->buf); 3829*7c478bd9Sstevel@tonic-gate free(Myaddrs[cnt]); 3830*7c478bd9Sstevel@tonic-gate t_free((char *)Udp[cnt], T_UNITDATA); 3831*7c478bd9Sstevel@tonic-gate t_free((char *)Errp[cnt], T_UDERROR); 3832*7c478bd9Sstevel@tonic-gate 3833*7c478bd9Sstevel@tonic-gate for (i = cnt; i < (Ninputs-1); i++) { 3834*7c478bd9Sstevel@tonic-gate Nfd[i] = Nfd[i + 1]; 3835*7c478bd9Sstevel@tonic-gate Ncf[i] = Ncf[i + 1]; 3836*7c478bd9Sstevel@tonic-gate Myaddrs[i] = Myaddrs[i + 1]; 3837*7c478bd9Sstevel@tonic-gate Udp[i] = Udp[i + 1]; 3838*7c478bd9Sstevel@tonic-gate Errp[i] = Errp[i + 1]; 3839*7c478bd9Sstevel@tonic-gate } 3840*7c478bd9Sstevel@tonic-gate 3841*7c478bd9Sstevel@tonic-gate Ninputs--; 3842*7c478bd9Sstevel@tonic-gate } 3843*7c478bd9Sstevel@tonic-gate } 3844*7c478bd9Sstevel@tonic-gate 3845*7c478bd9Sstevel@tonic-gate static int 3846*7c478bd9Sstevel@tonic-gate logforward(struct filed *f, char *ebuf) 3847*7c478bd9Sstevel@tonic-gate { 3848*7c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 3849*7c478bd9Sstevel@tonic-gate struct netbuf *nbp; 3850*7c478bd9Sstevel@tonic-gate struct netconfig *ncp; 3851*7c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 3852*7c478bd9Sstevel@tonic-gate void *handle; 3853*7c478bd9Sstevel@tonic-gate char *hp; 3854*7c478bd9Sstevel@tonic-gate 3855*7c478bd9Sstevel@tonic-gate hp = f->f_un.f_forw.f_hname; 3856*7c478bd9Sstevel@tonic-gate hs.h_host = hp; 3857*7c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 3858*7c478bd9Sstevel@tonic-gate 3859*7c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 3860*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, 3861*7c478bd9Sstevel@tonic-gate "unable to rewind the netconfig database"); 3862*7c478bd9Sstevel@tonic-gate errno = 0; 3863*7c478bd9Sstevel@tonic-gate return (-1); 3864*7c478bd9Sstevel@tonic-gate } 3865*7c478bd9Sstevel@tonic-gate nap = (struct nd_addrlist *)NULL; 3866*7c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 3867*7c478bd9Sstevel@tonic-gate if (ncp->nc_semantics == NC_TPI_CLTS) { 3868*7c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) == 0) { 3869*7c478bd9Sstevel@tonic-gate if (!nap) 3870*7c478bd9Sstevel@tonic-gate continue; 3871*7c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 3872*7c478bd9Sstevel@tonic-gate break; 3873*7c478bd9Sstevel@tonic-gate } 3874*7c478bd9Sstevel@tonic-gate } 3875*7c478bd9Sstevel@tonic-gate } 3876*7c478bd9Sstevel@tonic-gate if (ncp == NULL) { 3877*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3878*7c478bd9Sstevel@tonic-gate (void) sprintf(ebuf, "WARNING: %s could not be resolved", hp); 3879*7c478bd9Sstevel@tonic-gate errno = 0; 3880*7c478bd9Sstevel@tonic-gate return (-1); 3881*7c478bd9Sstevel@tonic-gate } 3882*7c478bd9Sstevel@tonic-gate if (nap == (struct nd_addrlist *)NULL) { 3883*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3884*7c478bd9Sstevel@tonic-gate (void) sprintf(ebuf, "unknown host %s", hp); 3885*7c478bd9Sstevel@tonic-gate errno = 0; 3886*7c478bd9Sstevel@tonic-gate return (-1); 3887*7c478bd9Sstevel@tonic-gate } 3888*7c478bd9Sstevel@tonic-gate /* CSTYLED */ 3889*7c478bd9Sstevel@tonic-gate if (ismyaddr(nbp)) { /*lint !e644 */ 3890*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3891*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3892*7c478bd9Sstevel@tonic-gate (void) sprintf(ebuf, "host %s is this host - logging loop", 3893*7c478bd9Sstevel@tonic-gate hp); 3894*7c478bd9Sstevel@tonic-gate errno = 0; 3895*7c478bd9Sstevel@tonic-gate return (-1); 3896*7c478bd9Sstevel@tonic-gate } 3897*7c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_addr.buf = malloc(nbp->len); 3898*7c478bd9Sstevel@tonic-gate if (f->f_un.f_forw.f_addr.buf == NULL) { 3899*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3900*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3901*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "malloc failed"); 3902*7c478bd9Sstevel@tonic-gate return (-1); 3903*7c478bd9Sstevel@tonic-gate } 3904*7c478bd9Sstevel@tonic-gate bcopy(nbp->buf, f->f_un.f_forw.f_addr.buf, nbp->len); 3905*7c478bd9Sstevel@tonic-gate f->f_un.f_forw.f_addr.len = nbp->len; 3906*7c478bd9Sstevel@tonic-gate f->f_file = t_open(ncp->nc_device, O_RDWR, NULL); 3907*7c478bd9Sstevel@tonic-gate if (f->f_file < 0) { 3908*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3909*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3910*7c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 3911*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "t_open"); 3912*7c478bd9Sstevel@tonic-gate return (-1); 3913*7c478bd9Sstevel@tonic-gate } 3914*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3915*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3916*7c478bd9Sstevel@tonic-gate if (t_bind(f->f_file, NULL, NULL) < 0) { 3917*7c478bd9Sstevel@tonic-gate (void) strcpy(ebuf, "t_bind"); 3918*7c478bd9Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf); 3919*7c478bd9Sstevel@tonic-gate t_close(f->f_file); 3920*7c478bd9Sstevel@tonic-gate return (-1); 3921*7c478bd9Sstevel@tonic-gate } 3922*7c478bd9Sstevel@tonic-gate return (0); 3923*7c478bd9Sstevel@tonic-gate } 3924*7c478bd9Sstevel@tonic-gate 3925*7c478bd9Sstevel@tonic-gate static int 3926*7c478bd9Sstevel@tonic-gate amiloghost(void) 3927*7c478bd9Sstevel@tonic-gate { 3928*7c478bd9Sstevel@tonic-gate struct nd_hostserv hs; 3929*7c478bd9Sstevel@tonic-gate struct netconfig *ncp; 3930*7c478bd9Sstevel@tonic-gate struct nd_addrlist *nap; 3931*7c478bd9Sstevel@tonic-gate struct netbuf *nbp; 3932*7c478bd9Sstevel@tonic-gate int i, fd; 3933*7c478bd9Sstevel@tonic-gate void *handle; 3934*7c478bd9Sstevel@tonic-gate char *uap; 3935*7c478bd9Sstevel@tonic-gate struct t_bind bind, *bound; 3936*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 3937*7c478bd9Sstevel@tonic-gate 3938*7c478bd9Sstevel@tonic-gate if (Debug) { 3939*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 3940*7c478bd9Sstevel@tonic-gate } 3941*7c478bd9Sstevel@tonic-gate 3942*7c478bd9Sstevel@tonic-gate /* 3943*7c478bd9Sstevel@tonic-gate * we need to know if we are running on the loghost. This is 3944*7c478bd9Sstevel@tonic-gate * checked by binding to the address associated with "loghost" 3945*7c478bd9Sstevel@tonic-gate * and "syslogd" service over the connectionless transport 3946*7c478bd9Sstevel@tonic-gate */ 3947*7c478bd9Sstevel@tonic-gate hs.h_host = "loghost"; 3948*7c478bd9Sstevel@tonic-gate hs.h_serv = "syslog"; 3949*7c478bd9Sstevel@tonic-gate 3950*7c478bd9Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) { 3951*7c478bd9Sstevel@tonic-gate return (0); 3952*7c478bd9Sstevel@tonic-gate } 3953*7c478bd9Sstevel@tonic-gate 3954*7c478bd9Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) { 3955*7c478bd9Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) { 3956*7c478bd9Sstevel@tonic-gate continue; 3957*7c478bd9Sstevel@tonic-gate } 3958*7c478bd9Sstevel@tonic-gate 3959*7c478bd9Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) { 3960*7c478bd9Sstevel@tonic-gate continue; 3961*7c478bd9Sstevel@tonic-gate } 3962*7c478bd9Sstevel@tonic-gate 3963*7c478bd9Sstevel@tonic-gate if (nap == NULL) { 3964*7c478bd9Sstevel@tonic-gate continue; 3965*7c478bd9Sstevel@tonic-gate } 3966*7c478bd9Sstevel@tonic-gate 3967*7c478bd9Sstevel@tonic-gate nbp = nap->n_addrs; 3968*7c478bd9Sstevel@tonic-gate 3969*7c478bd9Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) { 3970*7c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != (char *)NULL) { 3971*7c478bd9Sstevel@tonic-gate DPRINT2(1, "amiloghost(%u): testing %s\n", 3972*7c478bd9Sstevel@tonic-gate mythreadno, uap); 3973*7c478bd9Sstevel@tonic-gate } 3974*7c478bd9Sstevel@tonic-gate 3975*7c478bd9Sstevel@tonic-gate free(uap); 3976*7c478bd9Sstevel@tonic-gate 3977*7c478bd9Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL); 3978*7c478bd9Sstevel@tonic-gate 3979*7c478bd9Sstevel@tonic-gate if (fd < 0) { 3980*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3981*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3982*7c478bd9Sstevel@tonic-gate return (0); 3983*7c478bd9Sstevel@tonic-gate } 3984*7c478bd9Sstevel@tonic-gate 3985*7c478bd9Sstevel@tonic-gate /*LINTED*/ 3986*7c478bd9Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 3987*7c478bd9Sstevel@tonic-gate bind.addr = *nbp; 3988*7c478bd9Sstevel@tonic-gate bind.qlen = 0; 3989*7c478bd9Sstevel@tonic-gate 3990*7c478bd9Sstevel@tonic-gate if (t_bind(fd, &bind, bound) == 0) { 3991*7c478bd9Sstevel@tonic-gate t_close(fd); 3992*7c478bd9Sstevel@tonic-gate t_free((char *)bound, T_BIND); 3993*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 3994*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 3995*7c478bd9Sstevel@tonic-gate return (1); 3996*7c478bd9Sstevel@tonic-gate } else { 3997*7c478bd9Sstevel@tonic-gate t_close(fd); 3998*7c478bd9Sstevel@tonic-gate t_free((char *)bound, T_BIND); 3999*7c478bd9Sstevel@tonic-gate } 4000*7c478bd9Sstevel@tonic-gate 4001*7c478bd9Sstevel@tonic-gate nbp++; 4002*7c478bd9Sstevel@tonic-gate } 4003*7c478bd9Sstevel@tonic-gate 4004*7c478bd9Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST); 4005*7c478bd9Sstevel@tonic-gate } 4006*7c478bd9Sstevel@tonic-gate 4007*7c478bd9Sstevel@tonic-gate endnetconfig(handle); 4008*7c478bd9Sstevel@tonic-gate return (0); 4009*7c478bd9Sstevel@tonic-gate } 4010*7c478bd9Sstevel@tonic-gate 4011*7c478bd9Sstevel@tonic-gate int 4012*7c478bd9Sstevel@tonic-gate same_addr(struct netbuf *na, struct netbuf *nb) 4013*7c478bd9Sstevel@tonic-gate { 4014*7c478bd9Sstevel@tonic-gate char *a, *b; 4015*7c478bd9Sstevel@tonic-gate size_t n; 4016*7c478bd9Sstevel@tonic-gate 4017*7c478bd9Sstevel@tonic-gate assert(a != NULL && b != NULL); 4018*7c478bd9Sstevel@tonic-gate 4019*7c478bd9Sstevel@tonic-gate if (na->len != nb->len) { 4020*7c478bd9Sstevel@tonic-gate return (0); 4021*7c478bd9Sstevel@tonic-gate } 4022*7c478bd9Sstevel@tonic-gate 4023*7c478bd9Sstevel@tonic-gate a = na->buf; 4024*7c478bd9Sstevel@tonic-gate b = nb->buf; 4025*7c478bd9Sstevel@tonic-gate n = nb->len; 4026*7c478bd9Sstevel@tonic-gate 4027*7c478bd9Sstevel@tonic-gate while (n-- > 0) { 4028*7c478bd9Sstevel@tonic-gate if (*a++ != *b++) { 4029*7c478bd9Sstevel@tonic-gate return (0); 4030*7c478bd9Sstevel@tonic-gate } 4031*7c478bd9Sstevel@tonic-gate } 4032*7c478bd9Sstevel@tonic-gate 4033*7c478bd9Sstevel@tonic-gate return (1); 4034*7c478bd9Sstevel@tonic-gate } 4035*7c478bd9Sstevel@tonic-gate 4036*7c478bd9Sstevel@tonic-gate /* 4037*7c478bd9Sstevel@tonic-gate * allocates a new message structure, initializes it 4038*7c478bd9Sstevel@tonic-gate * and returns a pointer to it 4039*7c478bd9Sstevel@tonic-gate */ 4040*7c478bd9Sstevel@tonic-gate static log_message_t * 4041*7c478bd9Sstevel@tonic-gate new_msg(void) 4042*7c478bd9Sstevel@tonic-gate { 4043*7c478bd9Sstevel@tonic-gate log_message_t *lm; 4044*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4045*7c478bd9Sstevel@tonic-gate 4046*7c478bd9Sstevel@tonic-gate if (Debug) { 4047*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4048*7c478bd9Sstevel@tonic-gate } 4049*7c478bd9Sstevel@tonic-gate 4050*7c478bd9Sstevel@tonic-gate if ((lm = malloc(sizeof (log_message_t))) == NULL) 4051*7c478bd9Sstevel@tonic-gate return ((log_message_t *)NULL); 4052*7c478bd9Sstevel@tonic-gate 4053*7c478bd9Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lm)) 4054*7c478bd9Sstevel@tonic-gate 4055*7c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&lm->msg_mutex, NULL) != 0) 4056*7c478bd9Sstevel@tonic-gate return ((log_message_t *)NULL); 4057*7c478bd9Sstevel@tonic-gate lm->refcnt = 0; 4058*7c478bd9Sstevel@tonic-gate lm->pri = 0; 4059*7c478bd9Sstevel@tonic-gate lm->flags = 0; 4060*7c478bd9Sstevel@tonic-gate lm->hlp = NULL; 4061*7c478bd9Sstevel@tonic-gate lm->msg[0] = '\0'; 4062*7c478bd9Sstevel@tonic-gate lm->ptr = NULL; 4063*7c478bd9Sstevel@tonic-gate 4064*7c478bd9Sstevel@tonic-gate DPRINT2(3, "new_msg(%u): creating msg %p\n", mythreadno, lm); 4065*7c478bd9Sstevel@tonic-gate return (lm); 4066*7c478bd9Sstevel@tonic-gate } 4067*7c478bd9Sstevel@tonic-gate 4068*7c478bd9Sstevel@tonic-gate /* 4069*7c478bd9Sstevel@tonic-gate * frees a message structure - should only be called if 4070*7c478bd9Sstevel@tonic-gate * the refcount is 0 4071*7c478bd9Sstevel@tonic-gate */ 4072*7c478bd9Sstevel@tonic-gate static void 4073*7c478bd9Sstevel@tonic-gate free_msg(log_message_t *lm) 4074*7c478bd9Sstevel@tonic-gate { 4075*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4076*7c478bd9Sstevel@tonic-gate 4077*7c478bd9Sstevel@tonic-gate if (Debug) { 4078*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4079*7c478bd9Sstevel@tonic-gate } 4080*7c478bd9Sstevel@tonic-gate 4081*7c478bd9Sstevel@tonic-gate assert(lm != NULL && lm->refcnt == 0); 4082*7c478bd9Sstevel@tonic-gate if (lm->hlp != NULL) 4083*7c478bd9Sstevel@tonic-gate freehl(lm->hlp); 4084*7c478bd9Sstevel@tonic-gate DPRINT2(3, "free_msg(%u): freeing msg %p\n", mythreadno, lm); 4085*7c478bd9Sstevel@tonic-gate free(lm); 4086*7c478bd9Sstevel@tonic-gate } 4087*7c478bd9Sstevel@tonic-gate 4088*7c478bd9Sstevel@tonic-gate /* 4089*7c478bd9Sstevel@tonic-gate * Make sure that the message makes sense in the current locale, and 4090*7c478bd9Sstevel@tonic-gate * does not contain stray control characters. 4091*7c478bd9Sstevel@tonic-gate */ 4092*7c478bd9Sstevel@tonic-gate static void 4093*7c478bd9Sstevel@tonic-gate filter_string(char *mbstr, char *filtered, size_t max) 4094*7c478bd9Sstevel@tonic-gate { 4095*7c478bd9Sstevel@tonic-gate size_t cs = 0; 4096*7c478bd9Sstevel@tonic-gate size_t mb_cur_max; 4097*7c478bd9Sstevel@tonic-gate unsigned char *p = (unsigned char *)mbstr; 4098*7c478bd9Sstevel@tonic-gate pthread_t mythreadno = 0; 4099*7c478bd9Sstevel@tonic-gate 4100*7c478bd9Sstevel@tonic-gate if (Debug) { 4101*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4102*7c478bd9Sstevel@tonic-gate } 4103*7c478bd9Sstevel@tonic-gate 4104*7c478bd9Sstevel@tonic-gate assert(mbstr != NULL && filtered != NULL); 4105*7c478bd9Sstevel@tonic-gate 4106*7c478bd9Sstevel@tonic-gate /* 4107*7c478bd9Sstevel@tonic-gate * Since the access to MB_CUR_MAX is expensive (because 4108*7c478bd9Sstevel@tonic-gate * MB_CUR_MAX lives in a global area), it should be 4109*7c478bd9Sstevel@tonic-gate * restrained for the better performance. 4110*7c478bd9Sstevel@tonic-gate */ 4111*7c478bd9Sstevel@tonic-gate mb_cur_max = (size_t)MB_CUR_MAX; 4112*7c478bd9Sstevel@tonic-gate if (mb_cur_max > 1) { 4113*7c478bd9Sstevel@tonic-gate /* multibyte locale */ 4114*7c478bd9Sstevel@tonic-gate int mlen; 4115*7c478bd9Sstevel@tonic-gate wchar_t wc; 4116*7c478bd9Sstevel@tonic-gate 4117*7c478bd9Sstevel@tonic-gate while (*p != '\0') { 4118*7c478bd9Sstevel@tonic-gate if ((mlen = mbtowc(&wc, (char *)p, 4119*7c478bd9Sstevel@tonic-gate mb_cur_max)) == -1) { 4120*7c478bd9Sstevel@tonic-gate /* 4121*7c478bd9Sstevel@tonic-gate * Invalid byte sequence found. 4122*7c478bd9Sstevel@tonic-gate * 4123*7c478bd9Sstevel@tonic-gate * try to print one byte 4124*7c478bd9Sstevel@tonic-gate * in ASCII format. 4125*7c478bd9Sstevel@tonic-gate */ 4126*7c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): Invalid " 4127*7c478bd9Sstevel@tonic-gate "MB sequence: %d\n", mythreadno, 4128*7c478bd9Sstevel@tonic-gate wc); 4129*7c478bd9Sstevel@tonic-gate 4130*7c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 4131*7c478bd9Sstevel@tonic-gate /* not enough buffer */ 4132*7c478bd9Sstevel@tonic-gate goto end; 4133*7c478bd9Sstevel@tonic-gate } else { 4134*7c478bd9Sstevel@tonic-gate continue; 4135*7c478bd9Sstevel@tonic-gate } 4136*7c478bd9Sstevel@tonic-gate } else { 4137*7c478bd9Sstevel@tonic-gate /* 4138*7c478bd9Sstevel@tonic-gate * Since *p is not a null byte here, 4139*7c478bd9Sstevel@tonic-gate * mbtowc should have never returned 0. 4140*7c478bd9Sstevel@tonic-gate * 4141*7c478bd9Sstevel@tonic-gate * A valid wide character found. 4142*7c478bd9Sstevel@tonic-gate */ 4143*7c478bd9Sstevel@tonic-gate 4144*7c478bd9Sstevel@tonic-gate if (wc != L'\t' && iswcntrl(wc)) { 4145*7c478bd9Sstevel@tonic-gate /* 4146*7c478bd9Sstevel@tonic-gate * non-tab, non-newline, and 4147*7c478bd9Sstevel@tonic-gate * control character found. 4148*7c478bd9Sstevel@tonic-gate * 4149*7c478bd9Sstevel@tonic-gate * try to print this wide character 4150*7c478bd9Sstevel@tonic-gate * in ASCII-format. 4151*7c478bd9Sstevel@tonic-gate */ 4152*7c478bd9Sstevel@tonic-gate char *q = filtered; 4153*7c478bd9Sstevel@tonic-gate 4154*7c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): MB" 4155*7c478bd9Sstevel@tonic-gate " control character: %d\n", 4156*7c478bd9Sstevel@tonic-gate mythreadno, wc); 4157*7c478bd9Sstevel@tonic-gate 4158*7c478bd9Sstevel@tonic-gate while (mlen--) { 4159*7c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, 4160*7c478bd9Sstevel@tonic-gate &cs, max)) { 4161*7c478bd9Sstevel@tonic-gate /* 4162*7c478bd9Sstevel@tonic-gate * not enough buffer in 4163*7c478bd9Sstevel@tonic-gate * filtered 4164*7c478bd9Sstevel@tonic-gate * 4165*7c478bd9Sstevel@tonic-gate * cancel already 4166*7c478bd9Sstevel@tonic-gate * stored bytes in 4167*7c478bd9Sstevel@tonic-gate * filtered for this 4168*7c478bd9Sstevel@tonic-gate * wide character. 4169*7c478bd9Sstevel@tonic-gate */ 4170*7c478bd9Sstevel@tonic-gate filtered = q; 4171*7c478bd9Sstevel@tonic-gate goto end; 4172*7c478bd9Sstevel@tonic-gate } 4173*7c478bd9Sstevel@tonic-gate } 4174*7c478bd9Sstevel@tonic-gate continue; 4175*7c478bd9Sstevel@tonic-gate } else { 4176*7c478bd9Sstevel@tonic-gate /* 4177*7c478bd9Sstevel@tonic-gate * tab, newline, or non-control 4178*7c478bd9Sstevel@tonic-gate * character found. 4179*7c478bd9Sstevel@tonic-gate */ 4180*7c478bd9Sstevel@tonic-gate if (cs + mlen < max) { 4181*7c478bd9Sstevel@tonic-gate /* enough buffer */ 4182*7c478bd9Sstevel@tonic-gate cs += mlen; 4183*7c478bd9Sstevel@tonic-gate while (mlen--) { 4184*7c478bd9Sstevel@tonic-gate *filtered++ = *p++; 4185*7c478bd9Sstevel@tonic-gate } 4186*7c478bd9Sstevel@tonic-gate continue; 4187*7c478bd9Sstevel@tonic-gate } else { 4188*7c478bd9Sstevel@tonic-gate /* not enough buffer */ 4189*7c478bd9Sstevel@tonic-gate goto end; 4190*7c478bd9Sstevel@tonic-gate } 4191*7c478bd9Sstevel@tonic-gate } 4192*7c478bd9Sstevel@tonic-gate } 4193*7c478bd9Sstevel@tonic-gate } 4194*7c478bd9Sstevel@tonic-gate } else { 4195*7c478bd9Sstevel@tonic-gate /* singlebyte locale */ 4196*7c478bd9Sstevel@tonic-gate 4197*7c478bd9Sstevel@tonic-gate while (*p != '\0') { 4198*7c478bd9Sstevel@tonic-gate if (*p != '\t' && iscntrl(*p)) { 4199*7c478bd9Sstevel@tonic-gate /* 4200*7c478bd9Sstevel@tonic-gate * non-tab, non-newline, 4201*7c478bd9Sstevel@tonic-gate * and control character found. 4202*7c478bd9Sstevel@tonic-gate * 4203*7c478bd9Sstevel@tonic-gate * try to print this singlebyte character 4204*7c478bd9Sstevel@tonic-gate * in ASCII format. 4205*7c478bd9Sstevel@tonic-gate */ 4206*7c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): control " 4207*7c478bd9Sstevel@tonic-gate "character: %d\n", mythreadno, *p); 4208*7c478bd9Sstevel@tonic-gate 4209*7c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 4210*7c478bd9Sstevel@tonic-gate /* not enough buffer */ 4211*7c478bd9Sstevel@tonic-gate goto end; 4212*7c478bd9Sstevel@tonic-gate } else { 4213*7c478bd9Sstevel@tonic-gate continue; 4214*7c478bd9Sstevel@tonic-gate } 4215*7c478bd9Sstevel@tonic-gate } else if (*p != '\t' && !isprint(*p)) { 4216*7c478bd9Sstevel@tonic-gate /* 4217*7c478bd9Sstevel@tonic-gate * non-tab and non printable character found 4218*7c478bd9Sstevel@tonic-gate * this check is required for the C locale 4219*7c478bd9Sstevel@tonic-gate */ 4220*7c478bd9Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): non-printable " 4221*7c478bd9Sstevel@tonic-gate "character: %d\n", mythreadno, *p); 4222*7c478bd9Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) { 4223*7c478bd9Sstevel@tonic-gate /* not enough buffer */ 4224*7c478bd9Sstevel@tonic-gate goto end; 4225*7c478bd9Sstevel@tonic-gate } else { 4226*7c478bd9Sstevel@tonic-gate continue; 4227*7c478bd9Sstevel@tonic-gate } 4228*7c478bd9Sstevel@tonic-gate } else { 4229*7c478bd9Sstevel@tonic-gate /* 4230*7c478bd9Sstevel@tonic-gate * tab, newline, non-control character, or 4231*7c478bd9Sstevel@tonic-gate * printable found. 4232*7c478bd9Sstevel@tonic-gate */ 4233*7c478bd9Sstevel@tonic-gate if (cs + 1 < max) { 4234*7c478bd9Sstevel@tonic-gate *filtered++ = *p++; 4235*7c478bd9Sstevel@tonic-gate cs++; 4236*7c478bd9Sstevel@tonic-gate continue; 4237*7c478bd9Sstevel@tonic-gate } else { 4238*7c478bd9Sstevel@tonic-gate /* not enough buffer */ 4239*7c478bd9Sstevel@tonic-gate goto end; 4240*7c478bd9Sstevel@tonic-gate } 4241*7c478bd9Sstevel@tonic-gate } 4242*7c478bd9Sstevel@tonic-gate } 4243*7c478bd9Sstevel@tonic-gate } 4244*7c478bd9Sstevel@tonic-gate 4245*7c478bd9Sstevel@tonic-gate end: 4246*7c478bd9Sstevel@tonic-gate *filtered = '\0'; 4247*7c478bd9Sstevel@tonic-gate 4248*7c478bd9Sstevel@tonic-gate if (cs >= 2 && 4249*7c478bd9Sstevel@tonic-gate filtered[-2] == '\\' && filtered[-1] == 'n') { 4250*7c478bd9Sstevel@tonic-gate filtered[-2] = '\0'; 4251*7c478bd9Sstevel@tonic-gate } 4252*7c478bd9Sstevel@tonic-gate } 4253*7c478bd9Sstevel@tonic-gate 4254*7c478bd9Sstevel@tonic-gate static char * 4255*7c478bd9Sstevel@tonic-gate alloc_stacks(int numstacks) 4256*7c478bd9Sstevel@tonic-gate { 4257*7c478bd9Sstevel@tonic-gate size_t pagesize, mapsize; 4258*7c478bd9Sstevel@tonic-gate char *stack_top; 4259*7c478bd9Sstevel@tonic-gate char *addr; 4260*7c478bd9Sstevel@tonic-gate int i; 4261*7c478bd9Sstevel@tonic-gate 4262*7c478bd9Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE); 4263*7c478bd9Sstevel@tonic-gate /* 4264*7c478bd9Sstevel@tonic-gate * stacksize and redzonesize are global so threads 4265*7c478bd9Sstevel@tonic-gate * can be created elsewhere and refer to the sizes 4266*7c478bd9Sstevel@tonic-gate */ 4267*7c478bd9Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) + 4268*7c478bd9Sstevel@tonic-gate DEFAULT_STACKSIZE, pagesize); 4269*7c478bd9Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize); 4270*7c478bd9Sstevel@tonic-gate 4271*7c478bd9Sstevel@tonic-gate /* 4272*7c478bd9Sstevel@tonic-gate * allocate an additional "redzonesize" chunk in addition 4273*7c478bd9Sstevel@tonic-gate * to what we require, so we can create a redzone at the 4274*7c478bd9Sstevel@tonic-gate * bottom of the last stack as well. 4275*7c478bd9Sstevel@tonic-gate */ 4276*7c478bd9Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize); 4277*7c478bd9Sstevel@tonic-gate stack_top = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, 4278*7c478bd9Sstevel@tonic-gate MAP_PRIVATE|MAP_ANON, -1, 0); 4279*7c478bd9Sstevel@tonic-gate if (stack_top == MAP_FAILED) 4280*7c478bd9Sstevel@tonic-gate return (NULL); 4281*7c478bd9Sstevel@tonic-gate 4282*7c478bd9Sstevel@tonic-gate addr = stack_top; 4283*7c478bd9Sstevel@tonic-gate /* 4284*7c478bd9Sstevel@tonic-gate * this loop is intentionally <= instead of <, so we can 4285*7c478bd9Sstevel@tonic-gate * protect the redzone at the bottom of the last stack 4286*7c478bd9Sstevel@tonic-gate */ 4287*7c478bd9Sstevel@tonic-gate for (i = 0; i <= numstacks; i++) { 4288*7c478bd9Sstevel@tonic-gate (void) mprotect(addr, redzonesize, PROT_NONE); 4289*7c478bd9Sstevel@tonic-gate addr += stacksize + redzonesize; 4290*7c478bd9Sstevel@tonic-gate } 4291*7c478bd9Sstevel@tonic-gate return ((char *)(stack_top + redzonesize)); 4292*7c478bd9Sstevel@tonic-gate } 4293*7c478bd9Sstevel@tonic-gate 4294*7c478bd9Sstevel@tonic-gate static void 4295*7c478bd9Sstevel@tonic-gate dealloc_stacks(int numstacks) 4296*7c478bd9Sstevel@tonic-gate { 4297*7c478bd9Sstevel@tonic-gate size_t pagesize, mapsize; 4298*7c478bd9Sstevel@tonic-gate 4299*7c478bd9Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE); 4300*7c478bd9Sstevel@tonic-gate 4301*7c478bd9Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) + 4302*7c478bd9Sstevel@tonic-gate DEFAULT_STACKSIZE, pagesize); 4303*7c478bd9Sstevel@tonic-gate 4304*7c478bd9Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize); 4305*7c478bd9Sstevel@tonic-gate 4306*7c478bd9Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize); 4307*7c478bd9Sstevel@tonic-gate (void) munmap(cstack_ptr - mapsize, mapsize); 4308*7c478bd9Sstevel@tonic-gate } 4309*7c478bd9Sstevel@tonic-gate 4310*7c478bd9Sstevel@tonic-gate static void 4311*7c478bd9Sstevel@tonic-gate filed_destroy(struct filed *f) 4312*7c478bd9Sstevel@tonic-gate { 4313*7c478bd9Sstevel@tonic-gate (void) dataq_destroy(&f->f_queue); 4314*7c478bd9Sstevel@tonic-gate pthread_mutex_destroy(&f->filed_mutex); 4315*7c478bd9Sstevel@tonic-gate } 4316*7c478bd9Sstevel@tonic-gate 4317*7c478bd9Sstevel@tonic-gate static void 4318*7c478bd9Sstevel@tonic-gate close_door(void) 4319*7c478bd9Sstevel@tonic-gate { 4320*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4321*7c478bd9Sstevel@tonic-gate 4322*7c478bd9Sstevel@tonic-gate if (Debug) { 4323*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4324*7c478bd9Sstevel@tonic-gate } 4325*7c478bd9Sstevel@tonic-gate 4326*7c478bd9Sstevel@tonic-gate (void) fdetach(DoorFileName); 4327*7c478bd9Sstevel@tonic-gate 4328*7c478bd9Sstevel@tonic-gate DPRINT2(5, "close_door(%u): detached server() from %s\n", 4329*7c478bd9Sstevel@tonic-gate mythreadno, DoorFileName); 4330*7c478bd9Sstevel@tonic-gate } 4331*7c478bd9Sstevel@tonic-gate 4332*7c478bd9Sstevel@tonic-gate static void 4333*7c478bd9Sstevel@tonic-gate delete_doorfiles(void) 4334*7c478bd9Sstevel@tonic-gate { 4335*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4336*7c478bd9Sstevel@tonic-gate struct stat sb; 4337*7c478bd9Sstevel@tonic-gate int err; 4338*7c478bd9Sstevel@tonic-gate char line[MAXLINE+1]; 4339*7c478bd9Sstevel@tonic-gate 4340*7c478bd9Sstevel@tonic-gate if (Debug) { 4341*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4342*7c478bd9Sstevel@tonic-gate } 4343*7c478bd9Sstevel@tonic-gate 4344*7c478bd9Sstevel@tonic-gate 4345*7c478bd9Sstevel@tonic-gate if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 4346*7c478bd9Sstevel@tonic-gate if (unlink(DoorFileName) < 0) { 4347*7c478bd9Sstevel@tonic-gate err = errno; 4348*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() of %s failed - fatal", 4349*7c478bd9Sstevel@tonic-gate DoorFileName); 4350*7c478bd9Sstevel@tonic-gate errno = err; 4351*7c478bd9Sstevel@tonic-gate logerror(line); 4352*7c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, " 4353*7c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, err); 4354*7c478bd9Sstevel@tonic-gate exit(1); 4355*7c478bd9Sstevel@tonic-gate } 4356*7c478bd9Sstevel@tonic-gate 4357*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 4358*7c478bd9Sstevel@tonic-gate mythreadno, DoorFileName); 4359*7c478bd9Sstevel@tonic-gate } 4360*7c478bd9Sstevel@tonic-gate 4361*7c478bd9Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) { 4362*7c478bd9Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 4363*7c478bd9Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) { 4364*7c478bd9Sstevel@tonic-gate err = errno; 4365*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() of %s " 4366*7c478bd9Sstevel@tonic-gate "failed", OLD_DOORFILE); 4367*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s\n", 4368*7c478bd9Sstevel@tonic-gate mythreadno, line); 4369*7c478bd9Sstevel@tonic-gate 4370*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 4371*7c478bd9Sstevel@tonic-gate errno = err; 4372*7c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 4373*7c478bd9Sstevel@tonic-gate logerror(line); 4374*7c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): " 4375*7c478bd9Sstevel@tonic-gate "error: %s, errno=%d\n", 4376*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 4377*7c478bd9Sstevel@tonic-gate exit(1); 4378*7c478bd9Sstevel@tonic-gate } 4379*7c478bd9Sstevel@tonic-gate 4380*7c478bd9Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink() " 4381*7c478bd9Sstevel@tonic-gate "failure OK on RO file system\n", 4382*7c478bd9Sstevel@tonic-gate mythreadno); 4383*7c478bd9Sstevel@tonic-gate } 4384*7c478bd9Sstevel@tonic-gate 4385*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 4386*7c478bd9Sstevel@tonic-gate mythreadno, OLD_DOORFILE); 4387*7c478bd9Sstevel@tonic-gate } 4388*7c478bd9Sstevel@tonic-gate } 4389*7c478bd9Sstevel@tonic-gate 4390*7c478bd9Sstevel@tonic-gate if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 4391*7c478bd9Sstevel@tonic-gate if (unlink(PidFileName) < 0) { 4392*7c478bd9Sstevel@tonic-gate err = errno; 4393*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() of %s failed" 4394*7c478bd9Sstevel@tonic-gate " - fatal", PidFileName); 4395*7c478bd9Sstevel@tonic-gate errno = err; 4396*7c478bd9Sstevel@tonic-gate logerror(line); 4397*7c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, " 4398*7c478bd9Sstevel@tonic-gate "errno=%d\n", mythreadno, line, err); 4399*7c478bd9Sstevel@tonic-gate exit(1); 4400*7c478bd9Sstevel@tonic-gate } 4401*7c478bd9Sstevel@tonic-gate 4402*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", mythreadno, 4403*7c478bd9Sstevel@tonic-gate PidFileName); 4404*7c478bd9Sstevel@tonic-gate } 4405*7c478bd9Sstevel@tonic-gate 4406*7c478bd9Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) { 4407*7c478bd9Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { 4408*7c478bd9Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) { 4409*7c478bd9Sstevel@tonic-gate err = errno; 4410*7c478bd9Sstevel@tonic-gate (void) sprintf(line, "unlink() of %s failed", 4411*7c478bd9Sstevel@tonic-gate OLD_PIDFILE); 4412*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s, \n", 4413*7c478bd9Sstevel@tonic-gate mythreadno, line); 4414*7c478bd9Sstevel@tonic-gate 4415*7c478bd9Sstevel@tonic-gate if (err != EROFS) { 4416*7c478bd9Sstevel@tonic-gate errno = err; 4417*7c478bd9Sstevel@tonic-gate (void) strcat(line, " - fatal"); 4418*7c478bd9Sstevel@tonic-gate logerror(line); 4419*7c478bd9Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): " 4420*7c478bd9Sstevel@tonic-gate "error: %s, errno=%d\n", 4421*7c478bd9Sstevel@tonic-gate mythreadno, line, err); 4422*7c478bd9Sstevel@tonic-gate exit(1); 4423*7c478bd9Sstevel@tonic-gate } 4424*7c478bd9Sstevel@tonic-gate 4425*7c478bd9Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink " 4426*7c478bd9Sstevel@tonic-gate "failure OK on RO file system\n", 4427*7c478bd9Sstevel@tonic-gate mythreadno); 4428*7c478bd9Sstevel@tonic-gate } 4429*7c478bd9Sstevel@tonic-gate 4430*7c478bd9Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", 4431*7c478bd9Sstevel@tonic-gate mythreadno, OLD_PIDFILE); 4432*7c478bd9Sstevel@tonic-gate } 4433*7c478bd9Sstevel@tonic-gate } 4434*7c478bd9Sstevel@tonic-gate 4435*7c478bd9Sstevel@tonic-gate if (DoorFd != -1) { 4436*7c478bd9Sstevel@tonic-gate (void) door_revoke(DoorFd); 4437*7c478bd9Sstevel@tonic-gate } 4438*7c478bd9Sstevel@tonic-gate 4439*7c478bd9Sstevel@tonic-gate DPRINT2(1, "delete_doorfiles(%u): revoked door: DoorFd=%d\n", 4440*7c478bd9Sstevel@tonic-gate mythreadno, DoorFd); 4441*7c478bd9Sstevel@tonic-gate } 4442*7c478bd9Sstevel@tonic-gate 4443*7c478bd9Sstevel@tonic-gate 4444*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4445*7c478bd9Sstevel@tonic-gate static void 4446*7c478bd9Sstevel@tonic-gate signull(int sig, siginfo_t *sip, void *utp) 4447*7c478bd9Sstevel@tonic-gate { 4448*7c478bd9Sstevel@tonic-gate DPRINT1(1, "signull(%u): THIS CALL SHOULD NEVER HAPPEN\n", 4449*7c478bd9Sstevel@tonic-gate pthread_self()); 4450*7c478bd9Sstevel@tonic-gate /* 4451*7c478bd9Sstevel@tonic-gate * Do nothing, as this is a place-holder used in conjunction with 4452*7c478bd9Sstevel@tonic-gate * sigaction()/sigwait() to ensure that the proper disposition is 4453*7c478bd9Sstevel@tonic-gate * given to the signals we handle in main(). 4454*7c478bd9Sstevel@tonic-gate */ 4455*7c478bd9Sstevel@tonic-gate } 4456*7c478bd9Sstevel@tonic-gate 4457*7c478bd9Sstevel@tonic-gate /* 4458*7c478bd9Sstevel@tonic-gate * putctrlc returns zero, if failed due to not enough buffer. 4459*7c478bd9Sstevel@tonic-gate * Otherwise, putctrlc returns non-zero. 4460*7c478bd9Sstevel@tonic-gate * 4461*7c478bd9Sstevel@tonic-gate * c: a byte to print in ASCII format 4462*7c478bd9Sstevel@tonic-gate * **buf: a pointer to the pointer to the output buffer. 4463*7c478bd9Sstevel@tonic-gate * *cl: current length of characters in the output buffer 4464*7c478bd9Sstevel@tonic-gate * max: maximum length of the buffer 4465*7c478bd9Sstevel@tonic-gate */ 4466*7c478bd9Sstevel@tonic-gate 4467*7c478bd9Sstevel@tonic-gate static int 4468*7c478bd9Sstevel@tonic-gate putctrlc(int c, char **buf, size_t *cl, size_t max) 4469*7c478bd9Sstevel@tonic-gate { 4470*7c478bd9Sstevel@tonic-gate char *p = *buf; 4471*7c478bd9Sstevel@tonic-gate 4472*7c478bd9Sstevel@tonic-gate if (c == '\n') { 4473*7c478bd9Sstevel@tonic-gate if (*cl + 2 < max) { 4474*7c478bd9Sstevel@tonic-gate *p++ = '\\'; 4475*7c478bd9Sstevel@tonic-gate *p++ = 'n'; 4476*7c478bd9Sstevel@tonic-gate *cl += 2; 4477*7c478bd9Sstevel@tonic-gate *buf = p; 4478*7c478bd9Sstevel@tonic-gate return (2); 4479*7c478bd9Sstevel@tonic-gate } else { 4480*7c478bd9Sstevel@tonic-gate return (0); 4481*7c478bd9Sstevel@tonic-gate } 4482*7c478bd9Sstevel@tonic-gate } else if (c < 0200) { 4483*7c478bd9Sstevel@tonic-gate /* ascii control character */ 4484*7c478bd9Sstevel@tonic-gate if (*cl + 2 < max) { 4485*7c478bd9Sstevel@tonic-gate *p++ = '^'; 4486*7c478bd9Sstevel@tonic-gate *p++ = c ^ 0100; 4487*7c478bd9Sstevel@tonic-gate *cl += 2; 4488*7c478bd9Sstevel@tonic-gate *buf = p; 4489*7c478bd9Sstevel@tonic-gate return (2); 4490*7c478bd9Sstevel@tonic-gate } else { 4491*7c478bd9Sstevel@tonic-gate return (0); 4492*7c478bd9Sstevel@tonic-gate } 4493*7c478bd9Sstevel@tonic-gate } else { 4494*7c478bd9Sstevel@tonic-gate if (*cl + 4 < max) { 4495*7c478bd9Sstevel@tonic-gate *p++ = '\\'; 4496*7c478bd9Sstevel@tonic-gate *p++ = ((c >> 6) & 07) + '0'; 4497*7c478bd9Sstevel@tonic-gate *p++ = ((c >> 3) & 07) + '0'; 4498*7c478bd9Sstevel@tonic-gate *p++ = (c & 07) + '0'; 4499*7c478bd9Sstevel@tonic-gate *cl += 4; 4500*7c478bd9Sstevel@tonic-gate *buf = p; 4501*7c478bd9Sstevel@tonic-gate return (4); 4502*7c478bd9Sstevel@tonic-gate } else { 4503*7c478bd9Sstevel@tonic-gate return (0); 4504*7c478bd9Sstevel@tonic-gate } 4505*7c478bd9Sstevel@tonic-gate } 4506*7c478bd9Sstevel@tonic-gate } 4507*7c478bd9Sstevel@tonic-gate 4508*7c478bd9Sstevel@tonic-gate /* 4509*7c478bd9Sstevel@tonic-gate * findnl_bkwd: 4510*7c478bd9Sstevel@tonic-gate * Scans each character in buf until it finds the last newline in buf, 4511*7c478bd9Sstevel@tonic-gate * or the scanned character becomes the last COMPLETE character in buf. 4512*7c478bd9Sstevel@tonic-gate * Returns the number of scanned bytes. 4513*7c478bd9Sstevel@tonic-gate * 4514*7c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 4515*7c478bd9Sstevel@tonic-gate * len - the length of the buffer 4516*7c478bd9Sstevel@tonic-gate */ 4517*7c478bd9Sstevel@tonic-gate size_t 4518*7c478bd9Sstevel@tonic-gate findnl_bkwd(const char *buf, const size_t len) 4519*7c478bd9Sstevel@tonic-gate { 4520*7c478bd9Sstevel@tonic-gate const char *p; 4521*7c478bd9Sstevel@tonic-gate size_t mb_cur_max; 4522*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4523*7c478bd9Sstevel@tonic-gate 4524*7c478bd9Sstevel@tonic-gate if (Debug) { 4525*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4526*7c478bd9Sstevel@tonic-gate } 4527*7c478bd9Sstevel@tonic-gate 4528*7c478bd9Sstevel@tonic-gate if (len == 0) { 4529*7c478bd9Sstevel@tonic-gate return (0); 4530*7c478bd9Sstevel@tonic-gate } 4531*7c478bd9Sstevel@tonic-gate 4532*7c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 4533*7c478bd9Sstevel@tonic-gate 4534*7c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 4535*7c478bd9Sstevel@tonic-gate /* single-byte locale */ 4536*7c478bd9Sstevel@tonic-gate for (p = buf + len - 1; p != buf; p--) { 4537*7c478bd9Sstevel@tonic-gate if (*p == '\n') { 4538*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4539*7c478bd9Sstevel@tonic-gate } 4540*7c478bd9Sstevel@tonic-gate } 4541*7c478bd9Sstevel@tonic-gate return ((size_t)len); 4542*7c478bd9Sstevel@tonic-gate } else { 4543*7c478bd9Sstevel@tonic-gate /* multi-byte locale */ 4544*7c478bd9Sstevel@tonic-gate int mlen; 4545*7c478bd9Sstevel@tonic-gate const char *nl; 4546*7c478bd9Sstevel@tonic-gate size_t rem; 4547*7c478bd9Sstevel@tonic-gate 4548*7c478bd9Sstevel@tonic-gate p = buf; 4549*7c478bd9Sstevel@tonic-gate nl = NULL; 4550*7c478bd9Sstevel@tonic-gate for (rem = len; rem >= mb_cur_max; ) { 4551*7c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 4552*7c478bd9Sstevel@tonic-gate if (mlen == -1) { 4553*7c478bd9Sstevel@tonic-gate /* 4554*7c478bd9Sstevel@tonic-gate * Invalid character found. 4555*7c478bd9Sstevel@tonic-gate */ 4556*7c478bd9Sstevel@tonic-gate DPRINT1(9, "findnl_bkwd(%u): Invalid MB " 4557*7c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 4558*7c478bd9Sstevel@tonic-gate /* 4559*7c478bd9Sstevel@tonic-gate * handle as a single byte character. 4560*7c478bd9Sstevel@tonic-gate */ 4561*7c478bd9Sstevel@tonic-gate p++; 4562*7c478bd9Sstevel@tonic-gate rem--; 4563*7c478bd9Sstevel@tonic-gate } else { 4564*7c478bd9Sstevel@tonic-gate /* 4565*7c478bd9Sstevel@tonic-gate * It's guaranteed that *p points to 4566*7c478bd9Sstevel@tonic-gate * the 1st byte of a multibyte character. 4567*7c478bd9Sstevel@tonic-gate */ 4568*7c478bd9Sstevel@tonic-gate if (*p == '\n') { 4569*7c478bd9Sstevel@tonic-gate nl = p; 4570*7c478bd9Sstevel@tonic-gate } 4571*7c478bd9Sstevel@tonic-gate p += mlen; 4572*7c478bd9Sstevel@tonic-gate rem -= mlen; 4573*7c478bd9Sstevel@tonic-gate } 4574*7c478bd9Sstevel@tonic-gate } 4575*7c478bd9Sstevel@tonic-gate if (nl) { 4576*7c478bd9Sstevel@tonic-gate return ((size_t)(nl - buf)); 4577*7c478bd9Sstevel@tonic-gate } 4578*7c478bd9Sstevel@tonic-gate /* 4579*7c478bd9Sstevel@tonic-gate * no newline nor null byte found. 4580*7c478bd9Sstevel@tonic-gate * Also it's guaranteed that *p points to 4581*7c478bd9Sstevel@tonic-gate * the 1st byte of a (multibyte) character 4582*7c478bd9Sstevel@tonic-gate * at this point. 4583*7c478bd9Sstevel@tonic-gate */ 4584*7c478bd9Sstevel@tonic-gate return (len - rem); 4585*7c478bd9Sstevel@tonic-gate } 4586*7c478bd9Sstevel@tonic-gate } 4587*7c478bd9Sstevel@tonic-gate 4588*7c478bd9Sstevel@tonic-gate /* 4589*7c478bd9Sstevel@tonic-gate * copynl_frwd: 4590*7c478bd9Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf 4591*7c478bd9Sstevel@tonic-gate * until it finds a null byte or a newline, or 4592*7c478bd9Sstevel@tonic-gate * the number of the remaining bytes in obuf gets to exceed obuflen 4593*7c478bd9Sstevel@tonic-gate * if copying the scanned character to obuf. 4594*7c478bd9Sstevel@tonic-gate * Returns the number of scanned bytes. 4595*7c478bd9Sstevel@tonic-gate * 4596*7c478bd9Sstevel@tonic-gate * obuf - buffer to be copied the scanned character 4597*7c478bd9Sstevel@tonic-gate * obuflen - the size of obuf 4598*7c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 4599*7c478bd9Sstevel@tonic-gate * len - the length of the buffer 4600*7c478bd9Sstevel@tonic-gate */ 4601*7c478bd9Sstevel@tonic-gate size_t 4602*7c478bd9Sstevel@tonic-gate copynl_frwd(char *obuf, const size_t obuflen, 4603*7c478bd9Sstevel@tonic-gate const char *buf, const size_t len) 4604*7c478bd9Sstevel@tonic-gate { 4605*7c478bd9Sstevel@tonic-gate const char *p; 4606*7c478bd9Sstevel@tonic-gate char *q = obuf; 4607*7c478bd9Sstevel@tonic-gate size_t olen = 0; 4608*7c478bd9Sstevel@tonic-gate size_t mb_cur_max; 4609*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4610*7c478bd9Sstevel@tonic-gate 4611*7c478bd9Sstevel@tonic-gate if (Debug) { 4612*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4613*7c478bd9Sstevel@tonic-gate } 4614*7c478bd9Sstevel@tonic-gate 4615*7c478bd9Sstevel@tonic-gate if (len == 0) { 4616*7c478bd9Sstevel@tonic-gate return (0); 4617*7c478bd9Sstevel@tonic-gate } 4618*7c478bd9Sstevel@tonic-gate 4619*7c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 4620*7c478bd9Sstevel@tonic-gate 4621*7c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 4622*7c478bd9Sstevel@tonic-gate /* single-byte locale */ 4623*7c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 4624*7c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 4625*7c478bd9Sstevel@tonic-gate if (*p != '\n') { 4626*7c478bd9Sstevel@tonic-gate *q++ = *p++; 4627*7c478bd9Sstevel@tonic-gate olen++; 4628*7c478bd9Sstevel@tonic-gate } else { 4629*7c478bd9Sstevel@tonic-gate *q = '\0'; 4630*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4631*7c478bd9Sstevel@tonic-gate } 4632*7c478bd9Sstevel@tonic-gate } else { 4633*7c478bd9Sstevel@tonic-gate *q = '\0'; 4634*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4635*7c478bd9Sstevel@tonic-gate } 4636*7c478bd9Sstevel@tonic-gate } 4637*7c478bd9Sstevel@tonic-gate *q = '\0'; 4638*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4639*7c478bd9Sstevel@tonic-gate } else { 4640*7c478bd9Sstevel@tonic-gate /* multi-byte locale */ 4641*7c478bd9Sstevel@tonic-gate int mlen; 4642*7c478bd9Sstevel@tonic-gate 4643*7c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 4644*7c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 4645*7c478bd9Sstevel@tonic-gate if (mlen == -1) { 4646*7c478bd9Sstevel@tonic-gate /* 4647*7c478bd9Sstevel@tonic-gate * Invalid character found. 4648*7c478bd9Sstevel@tonic-gate */ 4649*7c478bd9Sstevel@tonic-gate DPRINT1(9, "copynl_frwd(%u): Invalid MB " 4650*7c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 4651*7c478bd9Sstevel@tonic-gate /* 4652*7c478bd9Sstevel@tonic-gate * handle as a single byte character. 4653*7c478bd9Sstevel@tonic-gate */ 4654*7c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 4655*7c478bd9Sstevel@tonic-gate *q++ = *p++; 4656*7c478bd9Sstevel@tonic-gate olen++; 4657*7c478bd9Sstevel@tonic-gate } else { 4658*7c478bd9Sstevel@tonic-gate *q = '\0'; 4659*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4660*7c478bd9Sstevel@tonic-gate } 4661*7c478bd9Sstevel@tonic-gate } else { 4662*7c478bd9Sstevel@tonic-gate /* 4663*7c478bd9Sstevel@tonic-gate * It's guaranteed that *p points to 4664*7c478bd9Sstevel@tonic-gate * the 1st byte of a multibyte character. 4665*7c478bd9Sstevel@tonic-gate */ 4666*7c478bd9Sstevel@tonic-gate if (*p == '\n') { 4667*7c478bd9Sstevel@tonic-gate *q = '\0'; 4668*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4669*7c478bd9Sstevel@tonic-gate } 4670*7c478bd9Sstevel@tonic-gate if (obuflen > olen + mlen) { 4671*7c478bd9Sstevel@tonic-gate int n; 4672*7c478bd9Sstevel@tonic-gate for (n = 0; n < mlen; n++) { 4673*7c478bd9Sstevel@tonic-gate *q++ = *p++; 4674*7c478bd9Sstevel@tonic-gate } 4675*7c478bd9Sstevel@tonic-gate olen += mlen; 4676*7c478bd9Sstevel@tonic-gate } else { 4677*7c478bd9Sstevel@tonic-gate *q = '\0'; 4678*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4679*7c478bd9Sstevel@tonic-gate } 4680*7c478bd9Sstevel@tonic-gate } 4681*7c478bd9Sstevel@tonic-gate } 4682*7c478bd9Sstevel@tonic-gate /* 4683*7c478bd9Sstevel@tonic-gate * no newline nor null byte found. 4684*7c478bd9Sstevel@tonic-gate * Also it's guaranteed that *p points to 4685*7c478bd9Sstevel@tonic-gate * the 1st byte of a (multibyte) character 4686*7c478bd9Sstevel@tonic-gate * at this point. 4687*7c478bd9Sstevel@tonic-gate */ 4688*7c478bd9Sstevel@tonic-gate *q = '\0'; 4689*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4690*7c478bd9Sstevel@tonic-gate } 4691*7c478bd9Sstevel@tonic-gate } 4692*7c478bd9Sstevel@tonic-gate 4693*7c478bd9Sstevel@tonic-gate /* 4694*7c478bd9Sstevel@tonic-gate * copy_frwd: 4695*7c478bd9Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf 4696*7c478bd9Sstevel@tonic-gate * until the number of the remaining bytes in obuf gets to exceed obuflen 4697*7c478bd9Sstevel@tonic-gate * if copying the scanned character to obuf. 4698*7c478bd9Sstevel@tonic-gate * Returns the number of scanned (copied) bytes. 4699*7c478bd9Sstevel@tonic-gate * 4700*7c478bd9Sstevel@tonic-gate * obuf - buffer to be copied the scanned character 4701*7c478bd9Sstevel@tonic-gate * obuflen - the size of obuf 4702*7c478bd9Sstevel@tonic-gate * buf - pointer to a buffer containing the message string 4703*7c478bd9Sstevel@tonic-gate * len - the length of the buffer 4704*7c478bd9Sstevel@tonic-gate */ 4705*7c478bd9Sstevel@tonic-gate size_t 4706*7c478bd9Sstevel@tonic-gate copy_frwd(char *obuf, const size_t obuflen, 4707*7c478bd9Sstevel@tonic-gate const char *buf, const size_t len) 4708*7c478bd9Sstevel@tonic-gate { 4709*7c478bd9Sstevel@tonic-gate const char *p; 4710*7c478bd9Sstevel@tonic-gate char *q = obuf; 4711*7c478bd9Sstevel@tonic-gate size_t olen = 0; 4712*7c478bd9Sstevel@tonic-gate size_t mb_cur_max; 4713*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4714*7c478bd9Sstevel@tonic-gate 4715*7c478bd9Sstevel@tonic-gate if (Debug) { 4716*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4717*7c478bd9Sstevel@tonic-gate } 4718*7c478bd9Sstevel@tonic-gate 4719*7c478bd9Sstevel@tonic-gate if (len == 0) { 4720*7c478bd9Sstevel@tonic-gate return (0); 4721*7c478bd9Sstevel@tonic-gate } 4722*7c478bd9Sstevel@tonic-gate 4723*7c478bd9Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX; 4724*7c478bd9Sstevel@tonic-gate 4725*7c478bd9Sstevel@tonic-gate if (mb_cur_max == 1) { 4726*7c478bd9Sstevel@tonic-gate /* single-byte locale */ 4727*7c478bd9Sstevel@tonic-gate if (obuflen > len) { 4728*7c478bd9Sstevel@tonic-gate (void) memcpy(obuf, buf, len); 4729*7c478bd9Sstevel@tonic-gate obuf[len] = '\0'; 4730*7c478bd9Sstevel@tonic-gate return ((size_t)len); 4731*7c478bd9Sstevel@tonic-gate } else { 4732*7c478bd9Sstevel@tonic-gate (void) memcpy(obuf, buf, obuflen - 1); 4733*7c478bd9Sstevel@tonic-gate obuf[obuflen - 1] = '\0'; 4734*7c478bd9Sstevel@tonic-gate return (obuflen - 1); 4735*7c478bd9Sstevel@tonic-gate } 4736*7c478bd9Sstevel@tonic-gate } else { 4737*7c478bd9Sstevel@tonic-gate /* multi-byte locale */ 4738*7c478bd9Sstevel@tonic-gate int mlen; 4739*7c478bd9Sstevel@tonic-gate 4740*7c478bd9Sstevel@tonic-gate for (p = buf; *p; ) { 4741*7c478bd9Sstevel@tonic-gate mlen = mblen(p, mb_cur_max); 4742*7c478bd9Sstevel@tonic-gate if (mlen == -1) { 4743*7c478bd9Sstevel@tonic-gate /* 4744*7c478bd9Sstevel@tonic-gate * Invalid character found. 4745*7c478bd9Sstevel@tonic-gate */ 4746*7c478bd9Sstevel@tonic-gate DPRINT1(9, "copy_frwd(%u): Invalid MB " 4747*7c478bd9Sstevel@tonic-gate "sequence\n", mythreadno); 4748*7c478bd9Sstevel@tonic-gate /* 4749*7c478bd9Sstevel@tonic-gate * handle as a single byte character. 4750*7c478bd9Sstevel@tonic-gate */ 4751*7c478bd9Sstevel@tonic-gate if (obuflen > olen + 1) { 4752*7c478bd9Sstevel@tonic-gate *q++ = *p++; 4753*7c478bd9Sstevel@tonic-gate olen++; 4754*7c478bd9Sstevel@tonic-gate } else { 4755*7c478bd9Sstevel@tonic-gate *q = '\0'; 4756*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4757*7c478bd9Sstevel@tonic-gate } 4758*7c478bd9Sstevel@tonic-gate } else { 4759*7c478bd9Sstevel@tonic-gate if (obuflen > olen + mlen) { 4760*7c478bd9Sstevel@tonic-gate int n; 4761*7c478bd9Sstevel@tonic-gate for (n = 0; n < mlen; n++) { 4762*7c478bd9Sstevel@tonic-gate *q++ = *p++; 4763*7c478bd9Sstevel@tonic-gate } 4764*7c478bd9Sstevel@tonic-gate olen += mlen; 4765*7c478bd9Sstevel@tonic-gate } else { 4766*7c478bd9Sstevel@tonic-gate *q = '\0'; 4767*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4768*7c478bd9Sstevel@tonic-gate } 4769*7c478bd9Sstevel@tonic-gate } 4770*7c478bd9Sstevel@tonic-gate } 4771*7c478bd9Sstevel@tonic-gate *q = '\0'; 4772*7c478bd9Sstevel@tonic-gate return ((size_t)(p - buf)); 4773*7c478bd9Sstevel@tonic-gate } 4774*7c478bd9Sstevel@tonic-gate } 4775*7c478bd9Sstevel@tonic-gate 4776*7c478bd9Sstevel@tonic-gate /* 4777*7c478bd9Sstevel@tonic-gate * defaults: 4778*7c478bd9Sstevel@tonic-gate * Read defaults from file. 4779*7c478bd9Sstevel@tonic-gate */ 4780*7c478bd9Sstevel@tonic-gate static void 4781*7c478bd9Sstevel@tonic-gate defaults(void) 4782*7c478bd9Sstevel@tonic-gate { 4783*7c478bd9Sstevel@tonic-gate int flags; 4784*7c478bd9Sstevel@tonic-gate char *ptr; 4785*7c478bd9Sstevel@tonic-gate 4786*7c478bd9Sstevel@tonic-gate if (defopen(DflFile) == 0) { 4787*7c478bd9Sstevel@tonic-gate /* 4788*7c478bd9Sstevel@tonic-gate * ignore case 4789*7c478bd9Sstevel@tonic-gate */ 4790*7c478bd9Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0); 4791*7c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 4792*7c478bd9Sstevel@tonic-gate defcntl(DC_SETFLAGS, flags); 4793*7c478bd9Sstevel@tonic-gate 4794*7c478bd9Sstevel@tonic-gate if ((ptr = defread("LOG_FROM_REMOTE=")) != NULL) { 4795*7c478bd9Sstevel@tonic-gate turnoff = strcasecmp(ptr, "NO") == 0; 4796*7c478bd9Sstevel@tonic-gate } 4797*7c478bd9Sstevel@tonic-gate 4798*7c478bd9Sstevel@tonic-gate (void) defopen((char *)NULL); 4799*7c478bd9Sstevel@tonic-gate } 4800*7c478bd9Sstevel@tonic-gate } 4801*7c478bd9Sstevel@tonic-gate 4802*7c478bd9Sstevel@tonic-gate /* 4803*7c478bd9Sstevel@tonic-gate * close all the input devices. 4804*7c478bd9Sstevel@tonic-gate */ 4805*7c478bd9Sstevel@tonic-gate static void 4806*7c478bd9Sstevel@tonic-gate shutdown_input(void) 4807*7c478bd9Sstevel@tonic-gate { 4808*7c478bd9Sstevel@tonic-gate int cnt; 4809*7c478bd9Sstevel@tonic-gate 4810*7c478bd9Sstevel@tonic-gate shutting_down = 1; 4811*7c478bd9Sstevel@tonic-gate 4812*7c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < Ninputs; cnt++) { 4813*7c478bd9Sstevel@tonic-gate (void) t_close(Nfd[cnt].fd); 4814*7c478bd9Sstevel@tonic-gate } 4815*7c478bd9Sstevel@tonic-gate 4816*7c478bd9Sstevel@tonic-gate (void) close(Pfd.fd); 4817*7c478bd9Sstevel@tonic-gate } 4818*7c478bd9Sstevel@tonic-gate 4819*7c478bd9Sstevel@tonic-gate /* 4820*7c478bd9Sstevel@tonic-gate * This is for the one thread that dedicates to resolve the 4821*7c478bd9Sstevel@tonic-gate * hostname. This will get the messages from net_poll() through 4822*7c478bd9Sstevel@tonic-gate * hnlq, and resolve the hostname, and push the messages back 4823*7c478bd9Sstevel@tonic-gate * into the inputq. 4824*7c478bd9Sstevel@tonic-gate */ 4825*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4826*7c478bd9Sstevel@tonic-gate static void * 4827*7c478bd9Sstevel@tonic-gate hostname_lookup(void *ap) 4828*7c478bd9Sstevel@tonic-gate { 4829*7c478bd9Sstevel@tonic-gate char *uap; 4830*7c478bd9Sstevel@tonic-gate log_message_t *mp; 4831*7c478bd9Sstevel@tonic-gate host_info_t *hip; 4832*7c478bd9Sstevel@tonic-gate char failsafe_addr[SYS_NMLN + 1]; 4833*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4834*7c478bd9Sstevel@tonic-gate 4835*7c478bd9Sstevel@tonic-gate if (Debug) { 4836*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4837*7c478bd9Sstevel@tonic-gate } 4838*7c478bd9Sstevel@tonic-gate 4839*7c478bd9Sstevel@tonic-gate DPRINT1(1, "hostname_lookup(%u): hostname_lookup started\n", 4840*7c478bd9Sstevel@tonic-gate mythreadno); 4841*7c478bd9Sstevel@tonic-gate 4842*7c478bd9Sstevel@tonic-gate for (;;) { 4843*7c478bd9Sstevel@tonic-gate (void) dataq_dequeue(&hnlq, (void **)&mp, 0); 4844*7c478bd9Sstevel@tonic-gate 4845*7c478bd9Sstevel@tonic-gate DPRINT3(5, "hostname_lookup(%u): dequeued msg %p" 4846*7c478bd9Sstevel@tonic-gate " from queue %p\n", mythreadno, mp, &hnlq); 4847*7c478bd9Sstevel@tonic-gate 4848*7c478bd9Sstevel@tonic-gate hip = (host_info_t *)mp->ptr; 4849*7c478bd9Sstevel@tonic-gate if ((uap = taddr2uaddr(hip->ncp, &hip->addr)) != NULL) { 4850*7c478bd9Sstevel@tonic-gate (void) strlcpy(failsafe_addr, uap, SYS_NMLN); 4851*7c478bd9Sstevel@tonic-gate free(uap); 4852*7c478bd9Sstevel@tonic-gate } else { 4853*7c478bd9Sstevel@tonic-gate (void) strlcpy(failsafe_addr, "<unknown>", SYS_NMLN); 4854*7c478bd9Sstevel@tonic-gate } 4855*7c478bd9Sstevel@tonic-gate 4856*7c478bd9Sstevel@tonic-gate mp->hlp = cvthname(&hip->addr, hip->ncp, failsafe_addr); 4857*7c478bd9Sstevel@tonic-gate 4858*7c478bd9Sstevel@tonic-gate if (mp->hlp == NULL) { 4859*7c478bd9Sstevel@tonic-gate mp->hlp = &NullHostName; 4860*7c478bd9Sstevel@tonic-gate } 4861*7c478bd9Sstevel@tonic-gate 4862*7c478bd9Sstevel@tonic-gate free(hip->addr.buf); 4863*7c478bd9Sstevel@tonic-gate free(hip); 4864*7c478bd9Sstevel@tonic-gate mp->ptr = NULL; 4865*7c478bd9Sstevel@tonic-gate 4866*7c478bd9Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) { 4867*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message from remote"); 4868*7c478bd9Sstevel@tonic-gate free_msg(mp); 4869*7c478bd9Sstevel@tonic-gate continue; 4870*7c478bd9Sstevel@tonic-gate } 4871*7c478bd9Sstevel@tonic-gate 4872*7c478bd9Sstevel@tonic-gate DPRINT3(5, "hostname_lookup(%u): enqueued msg %p on queue %p\n", 4873*7c478bd9Sstevel@tonic-gate mythreadno, mp, &inputq); 4874*7c478bd9Sstevel@tonic-gate } 4875*7c478bd9Sstevel@tonic-gate 4876*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4877*7c478bd9Sstevel@tonic-gate return (NULL); 4878*7c478bd9Sstevel@tonic-gate } 4879*7c478bd9Sstevel@tonic-gate 4880*7c478bd9Sstevel@tonic-gate /* 4881*7c478bd9Sstevel@tonic-gate * Does all HUP(re-configuration) process. 4882*7c478bd9Sstevel@tonic-gate */ 4883*7c478bd9Sstevel@tonic-gate static void 4884*7c478bd9Sstevel@tonic-gate reconfigure() 4885*7c478bd9Sstevel@tonic-gate { 4886*7c478bd9Sstevel@tonic-gate int cnt, loop, drops; 4887*7c478bd9Sstevel@tonic-gate int really_stuck; 4888*7c478bd9Sstevel@tonic-gate int console_stuck = 0; 4889*7c478bd9Sstevel@tonic-gate struct filed *f; 4890*7c478bd9Sstevel@tonic-gate char buf[LINE_MAX]; 4891*7c478bd9Sstevel@tonic-gate struct utsname up; 4892*7c478bd9Sstevel@tonic-gate char cbuf[30]; 4893*7c478bd9Sstevel@tonic-gate time_t tim; 4894*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 4895*7c478bd9Sstevel@tonic-gate 4896*7c478bd9Sstevel@tonic-gate if (Debug) { 4897*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 4898*7c478bd9Sstevel@tonic-gate } 4899*7c478bd9Sstevel@tonic-gate 4900*7c478bd9Sstevel@tonic-gate /* If we get here then we must need to regen */ 4901*7c478bd9Sstevel@tonic-gate flushmsg(0); 4902*7c478bd9Sstevel@tonic-gate 4903*7c478bd9Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_INFO, "syslogd: configuration restart", 4904*7c478bd9Sstevel@tonic-gate ADDDATE, 0) == -1) { 4905*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("dropping message"); 4906*7c478bd9Sstevel@tonic-gate } 4907*7c478bd9Sstevel@tonic-gate 4908*7c478bd9Sstevel@tonic-gate /* 4909*7c478bd9Sstevel@tonic-gate * make sure the logmsg thread is not in the waiting state. 4910*7c478bd9Sstevel@tonic-gate * Otherwise, changing hup_state will prevent the logmsg thread 4911*7c478bd9Sstevel@tonic-gate * getting out from the waiting loop. 4912*7c478bd9Sstevel@tonic-gate */ 4913*7c478bd9Sstevel@tonic-gate 4914*7c478bd9Sstevel@tonic-gate if (Debug) { 4915*7c478bd9Sstevel@tonic-gate tim = time(NULL); 4916*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logmsg()" 4917*7c478bd9Sstevel@tonic-gate " moving to the safe place\n", 4918*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 4919*7c478bd9Sstevel@tonic-gate } 4920*7c478bd9Sstevel@tonic-gate 4921*7c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 4922*7c478bd9Sstevel@tonic-gate /* we don't need the mutex to read */ 4923*7c478bd9Sstevel@tonic-gate if (hup_state == HUP_ACCEPTABLE) 4924*7c478bd9Sstevel@tonic-gate break; 4925*7c478bd9Sstevel@tonic-gate (void) sleep(1); 4926*7c478bd9Sstevel@tonic-gate } 4927*7c478bd9Sstevel@tonic-gate if (hup_state != HUP_ACCEPTABLE) { 4928*7c478bd9Sstevel@tonic-gate goto thread_stuck; 4929*7c478bd9Sstevel@tonic-gate } 4930*7c478bd9Sstevel@tonic-gate 4931*7c478bd9Sstevel@tonic-gate if (Debug) { 4932*7c478bd9Sstevel@tonic-gate tim = time(NULL); 4933*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() will accept HUP\n", 4934*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 4935*7c478bd9Sstevel@tonic-gate } 4936*7c478bd9Sstevel@tonic-gate 4937*7c478bd9Sstevel@tonic-gate /* 4938*7c478bd9Sstevel@tonic-gate * Prevent logging until we are truly done processing the HUP 4939*7c478bd9Sstevel@tonic-gate */ 4940*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 4941*7c478bd9Sstevel@tonic-gate hup_state = HUP_INPROGRESS; 4942*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 4943*7c478bd9Sstevel@tonic-gate 4944*7c478bd9Sstevel@tonic-gate /* 4945*7c478bd9Sstevel@tonic-gate * We will be going into a critical state. Any error message 4946*7c478bd9Sstevel@tonic-gate * from syslogd needs to be dumped to the console by default 4947*7c478bd9Sstevel@tonic-gate * immediately. Also, those error messages are quened in a temporary 4948*7c478bd9Sstevel@tonic-gate * queue to be able to post into the regular stream later. 4949*7c478bd9Sstevel@tonic-gate */ 4950*7c478bd9Sstevel@tonic-gate disable_errorlog(); 4951*7c478bd9Sstevel@tonic-gate 4952*7c478bd9Sstevel@tonic-gate if (Debug) { 4953*7c478bd9Sstevel@tonic-gate tim = time(NULL); 4954*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: sending SHUTDOWN\n", 4955*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 4956*7c478bd9Sstevel@tonic-gate } 4957*7c478bd9Sstevel@tonic-gate 4958*7c478bd9Sstevel@tonic-gate /* stop configured threads */ 4959*7c478bd9Sstevel@tonic-gate if (shutdown_msg() == -1) { 4960*7c478bd9Sstevel@tonic-gate /* 4961*7c478bd9Sstevel@tonic-gate * No memory, message will be dumped to the console. 4962*7c478bd9Sstevel@tonic-gate */ 4963*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("unable to restart syslogd"); 4964*7c478bd9Sstevel@tonic-gate goto out; 4965*7c478bd9Sstevel@tonic-gate } 4966*7c478bd9Sstevel@tonic-gate 4967*7c478bd9Sstevel@tonic-gate /* make sure logmsg() is in suspended state */ 4968*7c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) { 4969*7c478bd9Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED) 4970*7c478bd9Sstevel@tonic-gate break; 4971*7c478bd9Sstevel@tonic-gate (void) sleep(1); 4972*7c478bd9Sstevel@tonic-gate } 4973*7c478bd9Sstevel@tonic-gate 4974*7c478bd9Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) { 4975*7c478bd9Sstevel@tonic-gate if (Debug) { 4976*7c478bd9Sstevel@tonic-gate tim = time(NULL); 4977*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() does not " 4978*7c478bd9Sstevel@tonic-gate "stop. enforcing\n", 4979*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 4980*7c478bd9Sstevel@tonic-gate } 4981*7c478bd9Sstevel@tonic-gate 4982*7c478bd9Sstevel@tonic-gate /* probably we have too long input queue, or really stuck */ 4983*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 4984*7c478bd9Sstevel@tonic-gate hup_state |= HUP_SUSP_LOGMSG_REQD; 4985*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 4986*7c478bd9Sstevel@tonic-gate 4987*7c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 4988*7c478bd9Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED) 4989*7c478bd9Sstevel@tonic-gate break; 4990*7c478bd9Sstevel@tonic-gate (void) sleep(1); 4991*7c478bd9Sstevel@tonic-gate } 4992*7c478bd9Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) { 4993*7c478bd9Sstevel@tonic-gate if (Debug) { 4994*7c478bd9Sstevel@tonic-gate tim = time(NULL); 4995*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg()" 4996*7c478bd9Sstevel@tonic-gate " does not stop. give up\n", 4997*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 4998*7c478bd9Sstevel@tonic-gate } 4999*7c478bd9Sstevel@tonic-gate logerror("could not suspend logmsg - fatal"); 5000*7c478bd9Sstevel@tonic-gate goto thread_stuck; 5001*7c478bd9Sstevel@tonic-gate } 5002*7c478bd9Sstevel@tonic-gate } 5003*7c478bd9Sstevel@tonic-gate 5004*7c478bd9Sstevel@tonic-gate if (Debug) { 5005*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5006*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() suspended\n", 5007*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 5008*7c478bd9Sstevel@tonic-gate } 5009*7c478bd9Sstevel@tonic-gate 5010*7c478bd9Sstevel@tonic-gate /* 5011*7c478bd9Sstevel@tonic-gate * Will wait for LOOP_MAX secs with watching queue lengths for the 5012*7c478bd9Sstevel@tonic-gate * each logger threads. If they have backlogs, and no change in the 5013*7c478bd9Sstevel@tonic-gate * length of queue found in 30 seconds, those will be counted as 5014*7c478bd9Sstevel@tonic-gate * "really stuck". 5015*7c478bd9Sstevel@tonic-gate * If all running logger threads become "really stuck" state, there 5016*7c478bd9Sstevel@tonic-gate * should be no worth waiting for them to quit. 5017*7c478bd9Sstevel@tonic-gate * In that case, we will go ahead and close out file descriptors to 5018*7c478bd9Sstevel@tonic-gate * have them pull out from hanging system call, and give them a last 5019*7c478bd9Sstevel@tonic-gate * chance(LOOP_INTERVAL sec) to quit. 5020*7c478bd9Sstevel@tonic-gate */ 5021*7c478bd9Sstevel@tonic-gate 5022*7c478bd9Sstevel@tonic-gate if (Debug) { 5023*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5024*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logit() to be" 5025*7c478bd9Sstevel@tonic-gate " shutdown\n", mythreadno, ctime_r(&tim, cbuf)+4); 5026*7c478bd9Sstevel@tonic-gate } 5027*7c478bd9Sstevel@tonic-gate 5028*7c478bd9Sstevel@tonic-gate cnt = 0; 5029*7c478bd9Sstevel@tonic-gate really_stuck = 0; 5030*7c478bd9Sstevel@tonic-gate while (cnt < (LOOP_MAX/LOOP_INTERVAL) && 5031*7c478bd9Sstevel@tonic-gate conf_threads > really_stuck) { 5032*7c478bd9Sstevel@tonic-gate 5033*7c478bd9Sstevel@tonic-gate /* save initial queue count */ 5034*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 5035*7c478bd9Sstevel@tonic-gate f->f_prev_queue_count = (f->f_type == F_UNUSED) ? 5036*7c478bd9Sstevel@tonic-gate -1 : f->f_queue_count; 5037*7c478bd9Sstevel@tonic-gate } 5038*7c478bd9Sstevel@tonic-gate 5039*7c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) { 5040*7c478bd9Sstevel@tonic-gate if (conf_threads == 0) 5041*7c478bd9Sstevel@tonic-gate break; 5042*7c478bd9Sstevel@tonic-gate (void) sleep(1); 5043*7c478bd9Sstevel@tonic-gate } 5044*7c478bd9Sstevel@tonic-gate 5045*7c478bd9Sstevel@tonic-gate if (conf_threads == 0) 5046*7c478bd9Sstevel@tonic-gate break; 5047*7c478bd9Sstevel@tonic-gate 5048*7c478bd9Sstevel@tonic-gate if (Debug) { 5049*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5050*7c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: " 5051*7c478bd9Sstevel@tonic-gate "%d threads are still alive.\n", 5052*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, 5053*7c478bd9Sstevel@tonic-gate conf_threads); 5054*7c478bd9Sstevel@tonic-gate } 5055*7c478bd9Sstevel@tonic-gate 5056*7c478bd9Sstevel@tonic-gate really_stuck = 0; 5057*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 5058*7c478bd9Sstevel@tonic-gate if (f->f_type == F_UNUSED) { 5059*7c478bd9Sstevel@tonic-gate f->f_prev_queue_count = -1; 5060*7c478bd9Sstevel@tonic-gate continue; 5061*7c478bd9Sstevel@tonic-gate } 5062*7c478bd9Sstevel@tonic-gate if (f->f_prev_queue_count == f->f_queue_count) { 5063*7c478bd9Sstevel@tonic-gate really_stuck++; 5064*7c478bd9Sstevel@tonic-gate f->f_prev_queue_count = 1; 5065*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): " 5066*7c478bd9Sstevel@tonic-gate "tid=%d is really stuck.\n", 5067*7c478bd9Sstevel@tonic-gate mythreadno, f->f_thread); 5068*7c478bd9Sstevel@tonic-gate } else { 5069*7c478bd9Sstevel@tonic-gate f->f_prev_queue_count = 0; 5070*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): " 5071*7c478bd9Sstevel@tonic-gate "tid=%d is still active.\n", 5072*7c478bd9Sstevel@tonic-gate mythreadno, f->f_thread); 5073*7c478bd9Sstevel@tonic-gate } 5074*7c478bd9Sstevel@tonic-gate } 5075*7c478bd9Sstevel@tonic-gate /* 5076*7c478bd9Sstevel@tonic-gate * Here we have one of following values in the 5077*7c478bd9Sstevel@tonic-gate * f_prev_queue_count: 5078*7c478bd9Sstevel@tonic-gate * 0: logger thread is still actively working. 5079*7c478bd9Sstevel@tonic-gate * 1: logger thread is really stuck. 5080*7c478bd9Sstevel@tonic-gate * -1: logger thread has already died. 5081*7c478bd9Sstevel@tonic-gate */ 5082*7c478bd9Sstevel@tonic-gate 5083*7c478bd9Sstevel@tonic-gate cnt++; 5084*7c478bd9Sstevel@tonic-gate } 5085*7c478bd9Sstevel@tonic-gate 5086*7c478bd9Sstevel@tonic-gate if (Debug) { 5087*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5088*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s:" 5089*7c478bd9Sstevel@tonic-gate " complete awaiting logit()\n", 5090*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 5091*7c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %d threads alive." 5092*7c478bd9Sstevel@tonic-gate " %d threads stuck\n", 5093*7c478bd9Sstevel@tonic-gate mythreadno, conf_threads, really_stuck); 5094*7c478bd9Sstevel@tonic-gate } 5095*7c478bd9Sstevel@tonic-gate 5096*7c478bd9Sstevel@tonic-gate /* 5097*7c478bd9Sstevel@tonic-gate * Still running? If so, mark it as UNUSED, and close 5098*7c478bd9Sstevel@tonic-gate * the fd so that logger threads can bail out from the loop. 5099*7c478bd9Sstevel@tonic-gate */ 5100*7c478bd9Sstevel@tonic-gate drops = 0; 5101*7c478bd9Sstevel@tonic-gate if (conf_threads) { 5102*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 5103*7c478bd9Sstevel@tonic-gate if (f->f_type == F_CONSOLE && 5104*7c478bd9Sstevel@tonic-gate f->f_prev_queue_count == 1) { 5105*7c478bd9Sstevel@tonic-gate /* console is really stuck */ 5106*7c478bd9Sstevel@tonic-gate console_stuck = 1; 5107*7c478bd9Sstevel@tonic-gate } 5108*7c478bd9Sstevel@tonic-gate if (f->f_type == F_USERS || f->f_type == F_WALL || 5109*7c478bd9Sstevel@tonic-gate f->f_type == F_UNUSED) 5110*7c478bd9Sstevel@tonic-gate continue; 5111*7c478bd9Sstevel@tonic-gate cnt = f->f_queue_count; 5112*7c478bd9Sstevel@tonic-gate drops += (cnt > 0) ? cnt - 1: 0; 5113*7c478bd9Sstevel@tonic-gate f->f_type = F_UNUSED; 5114*7c478bd9Sstevel@tonic-gate 5115*7c478bd9Sstevel@tonic-gate if (f->f_orig_type == F_FORW) 5116*7c478bd9Sstevel@tonic-gate t_close(f->f_file); 5117*7c478bd9Sstevel@tonic-gate else 5118*7c478bd9Sstevel@tonic-gate close(f->f_file); 5119*7c478bd9Sstevel@tonic-gate } 5120*7c478bd9Sstevel@tonic-gate 5121*7c478bd9Sstevel@tonic-gate if (Debug) { 5122*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5123*7c478bd9Sstevel@tonic-gate DPRINT1(3, "reconfigure(%u): terminating logit()\n", 5124*7c478bd9Sstevel@tonic-gate mythreadno); 5125*7c478bd9Sstevel@tonic-gate } 5126*7c478bd9Sstevel@tonic-gate 5127*7c478bd9Sstevel@tonic-gate /* last chance to exit */ 5128*7c478bd9Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) { 5129*7c478bd9Sstevel@tonic-gate if (conf_threads == 0) 5130*7c478bd9Sstevel@tonic-gate break; 5131*7c478bd9Sstevel@tonic-gate (void) sleep(1); 5132*7c478bd9Sstevel@tonic-gate } 5133*7c478bd9Sstevel@tonic-gate 5134*7c478bd9Sstevel@tonic-gate if (Debug) { 5135*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5136*7c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: %d alive\n", 5137*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, 5138*7c478bd9Sstevel@tonic-gate conf_threads); 5139*7c478bd9Sstevel@tonic-gate } 5140*7c478bd9Sstevel@tonic-gate } 5141*7c478bd9Sstevel@tonic-gate 5142*7c478bd9Sstevel@tonic-gate if (conf_threads == 0 && drops) { 5143*7c478bd9Sstevel@tonic-gate errno = 0; 5144*7c478bd9Sstevel@tonic-gate logerror("Could not completely output pending messages" 5145*7c478bd9Sstevel@tonic-gate " while preparing re-configuration"); 5146*7c478bd9Sstevel@tonic-gate logerror("discarded %d messages and restart configuration.", 5147*7c478bd9Sstevel@tonic-gate drops); 5148*7c478bd9Sstevel@tonic-gate if (Debug) { 5149*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5150*7c478bd9Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: " 5151*7c478bd9Sstevel@tonic-gate "discarded %d messages\n", 5152*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4, drops); 5153*7c478bd9Sstevel@tonic-gate } 5154*7c478bd9Sstevel@tonic-gate } 5155*7c478bd9Sstevel@tonic-gate 5156*7c478bd9Sstevel@tonic-gate /* 5157*7c478bd9Sstevel@tonic-gate * If all threads still haven't exited 5158*7c478bd9Sstevel@tonic-gate * something is stuck or hosed. We just 5159*7c478bd9Sstevel@tonic-gate * have no option but to exit. 5160*7c478bd9Sstevel@tonic-gate */ 5161*7c478bd9Sstevel@tonic-gate if (conf_threads) { 5162*7c478bd9Sstevel@tonic-gate thread_stuck: 5163*7c478bd9Sstevel@tonic-gate if (Debug) { 5164*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5165*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: really stuck\n", 5166*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 5167*7c478bd9Sstevel@tonic-gate } 5168*7c478bd9Sstevel@tonic-gate 5169*7c478bd9Sstevel@tonic-gate shutdown_input(); 5170*7c478bd9Sstevel@tonic-gate delete_doorfiles(); 5171*7c478bd9Sstevel@tonic-gate uname(&up); 5172*7c478bd9Sstevel@tonic-gate 5173*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, 5174*7c478bd9Sstevel@tonic-gate "syslogd(%s): some logger thread(s) " 5175*7c478bd9Sstevel@tonic-gate "are stuck%s; syslogd is shutting down.", 5176*7c478bd9Sstevel@tonic-gate up.nodename, 5177*7c478bd9Sstevel@tonic-gate console_stuck ? " (including the console)" : ""); 5178*7c478bd9Sstevel@tonic-gate 5179*7c478bd9Sstevel@tonic-gate if (console_stuck) { 5180*7c478bd9Sstevel@tonic-gate FILE *m = popen(MAILCMD, "w"); 5181*7c478bd9Sstevel@tonic-gate 5182*7c478bd9Sstevel@tonic-gate if (m != NULL) { 5183*7c478bd9Sstevel@tonic-gate fprintf(m, "%s\n", buf); 5184*7c478bd9Sstevel@tonic-gate pclose(m); 5185*7c478bd9Sstevel@tonic-gate } 5186*7c478bd9Sstevel@tonic-gate } 5187*7c478bd9Sstevel@tonic-gate 5188*7c478bd9Sstevel@tonic-gate disable_errorlog(); 5189*7c478bd9Sstevel@tonic-gate logerror(buf); 5190*7c478bd9Sstevel@tonic-gate exit(1); 5191*7c478bd9Sstevel@tonic-gate } 5192*7c478bd9Sstevel@tonic-gate 5193*7c478bd9Sstevel@tonic-gate /* Free up some resources */ 5194*7c478bd9Sstevel@tonic-gate if (Files != (struct filed *)&fallback) { 5195*7c478bd9Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) { 5196*7c478bd9Sstevel@tonic-gate (void) pthread_join(f->f_thread, NULL); 5197*7c478bd9Sstevel@tonic-gate filed_destroy(f); 5198*7c478bd9Sstevel@tonic-gate } 5199*7c478bd9Sstevel@tonic-gate free(Files); 5200*7c478bd9Sstevel@tonic-gate } 5201*7c478bd9Sstevel@tonic-gate 5202*7c478bd9Sstevel@tonic-gate dealloc_stacks(nlogs); 5203*7c478bd9Sstevel@tonic-gate 5204*7c478bd9Sstevel@tonic-gate if (Debug) { 5205*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5206*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: cleanup complete\n", 5207*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 5208*7c478bd9Sstevel@tonic-gate } 5209*7c478bd9Sstevel@tonic-gate 5210*7c478bd9Sstevel@tonic-gate hnc_init(1); /* purge hostname cache */ 5211*7c478bd9Sstevel@tonic-gate conf_init(); /* start reconfigure */ 5212*7c478bd9Sstevel@tonic-gate 5213*7c478bd9Sstevel@tonic-gate out:; 5214*7c478bd9Sstevel@tonic-gate /* Now should be ready to dispatch error messages from syslogd. */ 5215*7c478bd9Sstevel@tonic-gate enable_errorlog(); 5216*7c478bd9Sstevel@tonic-gate 5217*7c478bd9Sstevel@tonic-gate /* Wake up the log thread */ 5218*7c478bd9Sstevel@tonic-gate 5219*7c478bd9Sstevel@tonic-gate if (Debug) { 5220*7c478bd9Sstevel@tonic-gate tim = time(NULL); 5221*7c478bd9Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: resuming logmsg()\n", 5222*7c478bd9Sstevel@tonic-gate mythreadno, ctime_r(&tim, cbuf)+4); 5223*7c478bd9Sstevel@tonic-gate } 5224*7c478bd9Sstevel@tonic-gate 5225*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock); 5226*7c478bd9Sstevel@tonic-gate hup_state = HUP_COMPLETED; 5227*7c478bd9Sstevel@tonic-gate (void) pthread_cond_signal(&hup_done); 5228*7c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock); 5229*7c478bd9Sstevel@tonic-gate } 5230*7c478bd9Sstevel@tonic-gate 5231*7c478bd9Sstevel@tonic-gate /* 5232*7c478bd9Sstevel@tonic-gate * The following function implements simple hostname cache mechanism. 5233*7c478bd9Sstevel@tonic-gate * Host name cache consists of single linked list structure which contains 5234*7c478bd9Sstevel@tonic-gate * host_list_t and netbuf pair. All cache entries(hnc_size) are allocated 5235*7c478bd9Sstevel@tonic-gate * initially and linked to "hnc_freeq". If cache register request comes, 5236*7c478bd9Sstevel@tonic-gate * then one element will be pulled from freeq, and will be linked to 5237*7c478bd9Sstevel@tonic-gate * "hnc_active" with given netbuf, host_list_t and expiration time. All valid 5238*7c478bd9Sstevel@tonic-gate * cahces are linked from hnc_active. If the cache element has run 5239*7c478bd9Sstevel@tonic-gate * out, most unused element will be re-used for the new request. 5240*7c478bd9Sstevel@tonic-gate * 5241*7c478bd9Sstevel@tonic-gate * hnc_init(): 5242*7c478bd9Sstevel@tonic-gate * allocate and initialize the cache. If reinit is set, 5243*7c478bd9Sstevel@tonic-gate * invalidate all cache entries. 5244*7c478bd9Sstevel@tonic-gate * hnc_look(): 5245*7c478bd9Sstevel@tonic-gate * lookup the cache entries by following single linked list 5246*7c478bd9Sstevel@tonic-gate * from hnc_active. If cached entry was found, it will be 5247*7c478bd9Sstevel@tonic-gate * put in the head of the list, and return. While going through 5248*7c478bd9Sstevel@tonic-gate * the entries, an entry which has already expired will be invalidated. 5249*7c478bd9Sstevel@tonic-gate * hnc_register(): 5250*7c478bd9Sstevel@tonic-gate * take one element from freeq, and put the new entry at the top 5251*7c478bd9Sstevel@tonic-gate * of hnc_active. 5252*7c478bd9Sstevel@tonic-gate * hnc_unreg(): 5253*7c478bd9Sstevel@tonic-gate * invalidate the cache. i.e unlink from hnc_active, and linked the 5254*7c478bd9Sstevel@tonic-gate * element to freeq. 5255*7c478bd9Sstevel@tonic-gate */ 5256*7c478bd9Sstevel@tonic-gate 5257*7c478bd9Sstevel@tonic-gate static void 5258*7c478bd9Sstevel@tonic-gate hnc_init(int reinit) 5259*7c478bd9Sstevel@tonic-gate { 5260*7c478bd9Sstevel@tonic-gate struct hostname_cache **hpp; 5261*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5262*7c478bd9Sstevel@tonic-gate 5263*7c478bd9Sstevel@tonic-gate if (Debug) { 5264*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 5265*7c478bd9Sstevel@tonic-gate } 5266*7c478bd9Sstevel@tonic-gate 5267*7c478bd9Sstevel@tonic-gate if (reinit) { 5268*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&hnc_mutex); 5269*7c478bd9Sstevel@tonic-gate 5270*7c478bd9Sstevel@tonic-gate for (hpp = &hnc_active; *hpp != NULL; ) { 5271*7c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 5272*7c478bd9Sstevel@tonic-gate } 5273*7c478bd9Sstevel@tonic-gate 5274*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hnc_mutex); 5275*7c478bd9Sstevel@tonic-gate DPRINT1(2, "hnc_init(%u): hostname cache re-configured\n", 5276*7c478bd9Sstevel@tonic-gate mythreadno); 5277*7c478bd9Sstevel@tonic-gate } else { 5278*7c478bd9Sstevel@tonic-gate int i; 5279*7c478bd9Sstevel@tonic-gate 5280*7c478bd9Sstevel@tonic-gate hnc_cache = malloc(hnc_size * sizeof (struct hostname_cache)); 5281*7c478bd9Sstevel@tonic-gate 5282*7c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 5283*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("hostname cache"); 5284*7c478bd9Sstevel@tonic-gate logerror("hostname cache disabled"); 5285*7c478bd9Sstevel@tonic-gate return; 5286*7c478bd9Sstevel@tonic-gate } 5287*7c478bd9Sstevel@tonic-gate 5288*7c478bd9Sstevel@tonic-gate for (i = 0; i < hnc_size; i++) { 5289*7c478bd9Sstevel@tonic-gate hnc_cache[i].h = NULL; 5290*7c478bd9Sstevel@tonic-gate hnc_cache[i].next = hnc_cache + i + 1; 5291*7c478bd9Sstevel@tonic-gate } 5292*7c478bd9Sstevel@tonic-gate 5293*7c478bd9Sstevel@tonic-gate hnc_cache[hnc_size - 1].next = NULL; 5294*7c478bd9Sstevel@tonic-gate hnc_freeq = hnc_cache; 5295*7c478bd9Sstevel@tonic-gate hnc_active = NULL; 5296*7c478bd9Sstevel@tonic-gate 5297*7c478bd9Sstevel@tonic-gate DPRINT3(1, "hnc_init(%u): hostname cache configured %d entry" 5298*7c478bd9Sstevel@tonic-gate " ttl:%d\n", mythreadno, hnc_size, hnc_ttl); 5299*7c478bd9Sstevel@tonic-gate } 5300*7c478bd9Sstevel@tonic-gate } 5301*7c478bd9Sstevel@tonic-gate 5302*7c478bd9Sstevel@tonic-gate static host_list_t * 5303*7c478bd9Sstevel@tonic-gate hnc_lookup(struct netbuf *nbp, struct netconfig *ncp) 5304*7c478bd9Sstevel@tonic-gate { 5305*7c478bd9Sstevel@tonic-gate struct hostname_cache **hpp, *hp; 5306*7c478bd9Sstevel@tonic-gate time_t now; 5307*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5308*7c478bd9Sstevel@tonic-gate 5309*7c478bd9Sstevel@tonic-gate if (Debug) { 5310*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 5311*7c478bd9Sstevel@tonic-gate } 5312*7c478bd9Sstevel@tonic-gate 5313*7c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 5314*7c478bd9Sstevel@tonic-gate return (NULL); 5315*7c478bd9Sstevel@tonic-gate } 5316*7c478bd9Sstevel@tonic-gate 5317*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&hnc_mutex); 5318*7c478bd9Sstevel@tonic-gate now = time(0); 5319*7c478bd9Sstevel@tonic-gate 5320*7c478bd9Sstevel@tonic-gate for (hpp = &hnc_active; (hp = *hpp) != NULL; ) { 5321*7c478bd9Sstevel@tonic-gate DPRINT4(10, "hnc_lookup(%u): check %p on %p for %s\n", 5322*7c478bd9Sstevel@tonic-gate mythreadno, hp->h, hp, hp->h->hl_hosts[0]); 5323*7c478bd9Sstevel@tonic-gate 5324*7c478bd9Sstevel@tonic-gate if (hp->expire < now) { 5325*7c478bd9Sstevel@tonic-gate DPRINT2(9, "hnc_lookup(%u): purge %p\n", 5326*7c478bd9Sstevel@tonic-gate mythreadno, hp); 5327*7c478bd9Sstevel@tonic-gate /* Note: hnc_unreg changes *hpp */ 5328*7c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 5329*7c478bd9Sstevel@tonic-gate continue; 5330*7c478bd9Sstevel@tonic-gate } 5331*7c478bd9Sstevel@tonic-gate 5332*7c478bd9Sstevel@tonic-gate if (ncp == hp->ncp && same_addr(&hp->addr, nbp)) { 5333*7c478bd9Sstevel@tonic-gate /* 5334*7c478bd9Sstevel@tonic-gate * found! 5335*7c478bd9Sstevel@tonic-gate * Put the entry at the top. 5336*7c478bd9Sstevel@tonic-gate */ 5337*7c478bd9Sstevel@tonic-gate 5338*7c478bd9Sstevel@tonic-gate if (hp != hnc_active) { 5339*7c478bd9Sstevel@tonic-gate /* unlink from active list */ 5340*7c478bd9Sstevel@tonic-gate *hpp = (*hpp)->next; 5341*7c478bd9Sstevel@tonic-gate /* push it onto the top */ 5342*7c478bd9Sstevel@tonic-gate hp->next = hnc_active; 5343*7c478bd9Sstevel@tonic-gate hnc_active = hp; 5344*7c478bd9Sstevel@tonic-gate } 5345*7c478bd9Sstevel@tonic-gate 5346*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&hp->h->hl_mutex); 5347*7c478bd9Sstevel@tonic-gate hp->h->hl_refcnt++; 5348*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hp->h->hl_mutex); 5349*7c478bd9Sstevel@tonic-gate 5350*7c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_lookup(%u): found %p on %p for %s\n", 5351*7c478bd9Sstevel@tonic-gate mythreadno, hp->h, hp, hp->h->hl_hosts[0]); 5352*7c478bd9Sstevel@tonic-gate 5353*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hnc_mutex); 5354*7c478bd9Sstevel@tonic-gate return (hp->h); 5355*7c478bd9Sstevel@tonic-gate } 5356*7c478bd9Sstevel@tonic-gate 5357*7c478bd9Sstevel@tonic-gate hpp = &hp->next; 5358*7c478bd9Sstevel@tonic-gate } 5359*7c478bd9Sstevel@tonic-gate 5360*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hnc_mutex); 5361*7c478bd9Sstevel@tonic-gate return (NULL); 5362*7c478bd9Sstevel@tonic-gate } 5363*7c478bd9Sstevel@tonic-gate 5364*7c478bd9Sstevel@tonic-gate static void 5365*7c478bd9Sstevel@tonic-gate hnc_register(struct netbuf *nbp, struct netconfig *ncp, host_list_t *h) 5366*7c478bd9Sstevel@tonic-gate { 5367*7c478bd9Sstevel@tonic-gate struct hostname_cache **hpp, **tailp, *hp; 5368*7c478bd9Sstevel@tonic-gate void *addrbuf; 5369*7c478bd9Sstevel@tonic-gate time_t now; 5370*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5371*7c478bd9Sstevel@tonic-gate 5372*7c478bd9Sstevel@tonic-gate if (Debug) { 5373*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 5374*7c478bd9Sstevel@tonic-gate } 5375*7c478bd9Sstevel@tonic-gate 5376*7c478bd9Sstevel@tonic-gate if (hnc_cache == NULL) { 5377*7c478bd9Sstevel@tonic-gate return; 5378*7c478bd9Sstevel@tonic-gate } 5379*7c478bd9Sstevel@tonic-gate 5380*7c478bd9Sstevel@tonic-gate if ((addrbuf = malloc(nbp->len)) == NULL) { 5381*7c478bd9Sstevel@tonic-gate MALLOC_FAIL("pushing hostname cache"); 5382*7c478bd9Sstevel@tonic-gate return; 5383*7c478bd9Sstevel@tonic-gate } 5384*7c478bd9Sstevel@tonic-gate 5385*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&hnc_mutex); 5386*7c478bd9Sstevel@tonic-gate 5387*7c478bd9Sstevel@tonic-gate if (hnc_freeq == NULL) { 5388*7c478bd9Sstevel@tonic-gate DPRINT1(9, "hnc_register(%u): freeq empty\n", mythreadno); 5389*7c478bd9Sstevel@tonic-gate now = time(NULL); 5390*7c478bd9Sstevel@tonic-gate /* 5391*7c478bd9Sstevel@tonic-gate * first go through active list, and discard the 5392*7c478bd9Sstevel@tonic-gate * caches which has been invalid. 5393*7c478bd9Sstevel@tonic-gate */ 5394*7c478bd9Sstevel@tonic-gate for (hpp = &hnc_active; (hp = *hpp) != NULL; ) { 5395*7c478bd9Sstevel@tonic-gate tailp = hpp; 5396*7c478bd9Sstevel@tonic-gate 5397*7c478bd9Sstevel@tonic-gate if (hp->expire < now) { 5398*7c478bd9Sstevel@tonic-gate DPRINT2(9, "hnc_register(%u): discard %p\n", 5399*7c478bd9Sstevel@tonic-gate mythreadno, hp); 5400*7c478bd9Sstevel@tonic-gate hnc_unreg(hpp); 5401*7c478bd9Sstevel@tonic-gate } else { 5402*7c478bd9Sstevel@tonic-gate hpp = &hp->next; 5403*7c478bd9Sstevel@tonic-gate } 5404*7c478bd9Sstevel@tonic-gate } 5405*7c478bd9Sstevel@tonic-gate 5406*7c478bd9Sstevel@tonic-gate if (hnc_freeq == NULL) { 5407*7c478bd9Sstevel@tonic-gate DPRINT2(9, "hnc_register(%u): stealing %p\n", 5408*7c478bd9Sstevel@tonic-gate mythreadno, *tailp); 5409*7c478bd9Sstevel@tonic-gate /* 5410*7c478bd9Sstevel@tonic-gate * If still no inactive cache, then steal the least 5411*7c478bd9Sstevel@tonic-gate * active element. 5412*7c478bd9Sstevel@tonic-gate */ 5413*7c478bd9Sstevel@tonic-gate hnc_unreg(tailp); 5414*7c478bd9Sstevel@tonic-gate } 5415*7c478bd9Sstevel@tonic-gate } 5416*7c478bd9Sstevel@tonic-gate 5417*7c478bd9Sstevel@tonic-gate hp = hnc_freeq; 5418*7c478bd9Sstevel@tonic-gate hnc_freeq = hnc_freeq->next; 5419*7c478bd9Sstevel@tonic-gate 5420*7c478bd9Sstevel@tonic-gate /* push it on the top */ 5421*7c478bd9Sstevel@tonic-gate hp->next = hnc_active; 5422*7c478bd9Sstevel@tonic-gate hnc_active = hp; 5423*7c478bd9Sstevel@tonic-gate 5424*7c478bd9Sstevel@tonic-gate (void) memcpy(addrbuf, nbp->buf, nbp->len); 5425*7c478bd9Sstevel@tonic-gate hp->addr.len = nbp->len; 5426*7c478bd9Sstevel@tonic-gate hp->addr.buf = addrbuf; 5427*7c478bd9Sstevel@tonic-gate hp->ncp = ncp; 5428*7c478bd9Sstevel@tonic-gate hp->h = h; 5429*7c478bd9Sstevel@tonic-gate hp->expire = time(NULL) + hnc_ttl; 5430*7c478bd9Sstevel@tonic-gate 5431*7c478bd9Sstevel@tonic-gate /* 5432*7c478bd9Sstevel@tonic-gate * As far as cache is valid, corresponding host_list must 5433*7c478bd9Sstevel@tonic-gate * also be valid. Increments the refcnt to avoid freeing 5434*7c478bd9Sstevel@tonic-gate * host_list. 5435*7c478bd9Sstevel@tonic-gate */ 5436*7c478bd9Sstevel@tonic-gate h->hl_refcnt++; 5437*7c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_register(%u): reg %p onto %p for %s\n", 5438*7c478bd9Sstevel@tonic-gate mythreadno, h, hp, hp->h->hl_hosts[0]); 5439*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&hnc_mutex); 5440*7c478bd9Sstevel@tonic-gate } 5441*7c478bd9Sstevel@tonic-gate 5442*7c478bd9Sstevel@tonic-gate static void 5443*7c478bd9Sstevel@tonic-gate hnc_unreg(struct hostname_cache **hpp) 5444*7c478bd9Sstevel@tonic-gate { 5445*7c478bd9Sstevel@tonic-gate struct hostname_cache *hp = *hpp; 5446*7c478bd9Sstevel@tonic-gate pthread_t mythreadno; 5447*7c478bd9Sstevel@tonic-gate 5448*7c478bd9Sstevel@tonic-gate if (Debug) { 5449*7c478bd9Sstevel@tonic-gate mythreadno = pthread_self(); 5450*7c478bd9Sstevel@tonic-gate } 5451*7c478bd9Sstevel@tonic-gate 5452*7c478bd9Sstevel@tonic-gate DPRINT4(9, "hnc_unreg(%u): unreg %p on %p for %s\n", 5453*7c478bd9Sstevel@tonic-gate mythreadno, hp->h, hp, hp->h->hl_hosts[0]); 5454*7c478bd9Sstevel@tonic-gate free(hp->addr.buf); 5455*7c478bd9Sstevel@tonic-gate freehl(hp->h); 5456*7c478bd9Sstevel@tonic-gate 5457*7c478bd9Sstevel@tonic-gate /* unlink from active list */ 5458*7c478bd9Sstevel@tonic-gate *hpp = (*hpp)->next; 5459*7c478bd9Sstevel@tonic-gate 5460*7c478bd9Sstevel@tonic-gate /* put in freeq */ 5461*7c478bd9Sstevel@tonic-gate hp->next = hnc_freeq; 5462*7c478bd9Sstevel@tonic-gate hnc_freeq = hp; 5463*7c478bd9Sstevel@tonic-gate } 5464*7c478bd9Sstevel@tonic-gate 5465*7c478bd9Sstevel@tonic-gate /* 5466*7c478bd9Sstevel@tonic-gate * Once this is called, error messages through logerror() will go to 5467*7c478bd9Sstevel@tonic-gate * the console immediately. Also, messages are queued into the tmpq 5468*7c478bd9Sstevel@tonic-gate * to be able to later put them into inputq. 5469*7c478bd9Sstevel@tonic-gate */ 5470*7c478bd9Sstevel@tonic-gate static void 5471*7c478bd9Sstevel@tonic-gate disable_errorlog() 5472*7c478bd9Sstevel@tonic-gate { 5473*7c478bd9Sstevel@tonic-gate dataq_init(&tmpq); 5474*7c478bd9Sstevel@tonic-gate 5475*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&logerror_lock); 5476*7c478bd9Sstevel@tonic-gate interrorlog = 0; 5477*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&logerror_lock); 5478*7c478bd9Sstevel@tonic-gate } 5479*7c478bd9Sstevel@tonic-gate 5480*7c478bd9Sstevel@tonic-gate /* 5481*7c478bd9Sstevel@tonic-gate * Turn internal error messages to regular input stream. 5482*7c478bd9Sstevel@tonic-gate * All pending messages are pulled and pushed into the regular 5483*7c478bd9Sstevel@tonic-gate * input queue. 5484*7c478bd9Sstevel@tonic-gate */ 5485*7c478bd9Sstevel@tonic-gate static void 5486*7c478bd9Sstevel@tonic-gate enable_errorlog() 5487*7c478bd9Sstevel@tonic-gate { 5488*7c478bd9Sstevel@tonic-gate log_message_t *mp; 5489*7c478bd9Sstevel@tonic-gate 5490*7c478bd9Sstevel@tonic-gate pthread_mutex_lock(&logerror_lock); 5491*7c478bd9Sstevel@tonic-gate interrorlog = 1; 5492*7c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&logerror_lock); 5493*7c478bd9Sstevel@tonic-gate 5494*7c478bd9Sstevel@tonic-gate /* 5495*7c478bd9Sstevel@tonic-gate * push all the pending messages into inputq. 5496*7c478bd9Sstevel@tonic-gate */ 5497*7c478bd9Sstevel@tonic-gate while (dataq_dequeue(&tmpq, (void **)&mp, 1) == 0) { 5498*7c478bd9Sstevel@tonic-gate (void) dataq_enqueue(&inputq, mp); 5499*7c478bd9Sstevel@tonic-gate } 5500*7c478bd9Sstevel@tonic-gate dataq_destroy(&tmpq); 5501*7c478bd9Sstevel@tonic-gate } 5502