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