10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51914Scasper * Common Development and Distribution License (the "License").
61914Scasper * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
226358Snakanon * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
280Sstevel@tonic-gate * All Rights Reserved
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
330Sstevel@tonic-gate * The Regents of the University of California
340Sstevel@tonic-gate * All Rights Reserved
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
370Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
380Sstevel@tonic-gate * contributors.
390Sstevel@tonic-gate */
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * syslogd -- log system messages
430Sstevel@tonic-gate *
440Sstevel@tonic-gate * This program implements a system log. It takes a series of lines.
450Sstevel@tonic-gate * Each line may have a priority, signified as "<n>" as
460Sstevel@tonic-gate * the first characters of the line. If this is
470Sstevel@tonic-gate * not present, a default priority is used.
480Sstevel@tonic-gate *
490Sstevel@tonic-gate * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
500Sstevel@tonic-gate * cause it to reconfigure.
510Sstevel@tonic-gate *
520Sstevel@tonic-gate * Defined Constants:
530Sstevel@tonic-gate *
540Sstevel@tonic-gate * MAXLINE -- the maximimum line length that can be handled.
550Sstevel@tonic-gate * DEFUPRI -- the default priority for user messages.
560Sstevel@tonic-gate * DEFSPRI -- the default priority for kernel messages.
570Sstevel@tonic-gate *
580Sstevel@tonic-gate */
590Sstevel@tonic-gate
600Sstevel@tonic-gate #include <unistd.h>
610Sstevel@tonic-gate #include <note.h>
620Sstevel@tonic-gate #include <errno.h>
630Sstevel@tonic-gate #include <sys/types.h>
640Sstevel@tonic-gate #include <stdio.h>
651914Scasper #include <stdio_ext.h>
660Sstevel@tonic-gate #include <stdlib.h>
670Sstevel@tonic-gate #include <ctype.h>
680Sstevel@tonic-gate #include <signal.h>
690Sstevel@tonic-gate #include <string.h>
700Sstevel@tonic-gate #include <strings.h>
712104Sjjj #include <libscf.h>
720Sstevel@tonic-gate #include <netconfig.h>
730Sstevel@tonic-gate #include <netdir.h>
740Sstevel@tonic-gate #include <pwd.h>
750Sstevel@tonic-gate #include <sys/socket.h>
760Sstevel@tonic-gate #include <tiuser.h>
770Sstevel@tonic-gate #include <utmpx.h>
780Sstevel@tonic-gate #include <limits.h>
790Sstevel@tonic-gate #include <pthread.h>
800Sstevel@tonic-gate #include <fcntl.h>
810Sstevel@tonic-gate #include <stropts.h>
820Sstevel@tonic-gate #include <assert.h>
830Sstevel@tonic-gate #include <sys/statvfs.h>
840Sstevel@tonic-gate
850Sstevel@tonic-gate #include <sys/param.h>
860Sstevel@tonic-gate #include <sys/sysmacros.h>
870Sstevel@tonic-gate #include <sys/syslog.h>
880Sstevel@tonic-gate #include <sys/strlog.h>
890Sstevel@tonic-gate #include <sys/stat.h>
900Sstevel@tonic-gate #include <sys/time.h>
910Sstevel@tonic-gate #include <sys/utsname.h>
920Sstevel@tonic-gate #include <sys/poll.h>
930Sstevel@tonic-gate #include <sys/wait.h>
940Sstevel@tonic-gate #include <sys/resource.h>
950Sstevel@tonic-gate #include <sys/mman.h>
960Sstevel@tonic-gate #include <sys/note.h>
970Sstevel@tonic-gate #include <door.h>
980Sstevel@tonic-gate
990Sstevel@tonic-gate #include <wchar.h>
1000Sstevel@tonic-gate #include <locale.h>
1010Sstevel@tonic-gate #include <stdarg.h>
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate #include "dataq.h"
1040Sstevel@tonic-gate #include "conf.h"
1050Sstevel@tonic-gate #include "syslogd.h"
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate #define DOORFILE "/var/run/syslog_door"
1080Sstevel@tonic-gate #define RELATIVE_DOORFILE "../var/run/syslog_door"
1090Sstevel@tonic-gate #define OLD_DOORFILE "/etc/.syslog_door"
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate #define PIDFILE "/var/run/syslog.pid"
1120Sstevel@tonic-gate #define RELATIVE_PIDFILE "../var/run/syslog.pid"
1130Sstevel@tonic-gate #define OLD_PIDFILE "/etc/syslog.pid"
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate static char *LogName = "/dev/log";
1160Sstevel@tonic-gate static char *ConfFile = "/etc/syslog.conf";
1170Sstevel@tonic-gate static char ctty[] = "/dev/console";
1180Sstevel@tonic-gate static char sysmsg[] = "/dev/sysmsg";
1190Sstevel@tonic-gate static int DoorFd = -1;
1200Sstevel@tonic-gate static int DoorCreated = 0;
1210Sstevel@tonic-gate static int PidfileCreated = 0;
1220Sstevel@tonic-gate static char *DoorFileName = DOORFILE;
1230Sstevel@tonic-gate static char *PidFileName = PIDFILE;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * configuration file directives
1270Sstevel@tonic-gate */
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate static struct code PriNames[] = {
1300Sstevel@tonic-gate "panic", LOG_EMERG,
1310Sstevel@tonic-gate "emerg", LOG_EMERG,
1320Sstevel@tonic-gate "alert", LOG_ALERT,
1330Sstevel@tonic-gate "crit", LOG_CRIT,
1340Sstevel@tonic-gate "err", LOG_ERR,
1350Sstevel@tonic-gate "error", LOG_ERR,
1360Sstevel@tonic-gate "warn", LOG_WARNING,
1370Sstevel@tonic-gate "warning", LOG_WARNING,
1380Sstevel@tonic-gate "notice", LOG_NOTICE,
1390Sstevel@tonic-gate "info", LOG_INFO,
1400Sstevel@tonic-gate "debug", LOG_DEBUG,
1410Sstevel@tonic-gate "none", NOPRI,
1420Sstevel@tonic-gate NULL, -1
1430Sstevel@tonic-gate };
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate static struct code FacNames[] = {
1460Sstevel@tonic-gate "kern", LOG_KERN,
1470Sstevel@tonic-gate "user", LOG_USER,
1480Sstevel@tonic-gate "mail", LOG_MAIL,
1490Sstevel@tonic-gate "daemon", LOG_DAEMON,
1500Sstevel@tonic-gate "auth", LOG_AUTH,
1510Sstevel@tonic-gate "security", LOG_AUTH,
1520Sstevel@tonic-gate "mark", LOG_MARK,
1530Sstevel@tonic-gate "syslog", LOG_SYSLOG,
1540Sstevel@tonic-gate "lpr", LOG_LPR,
1550Sstevel@tonic-gate "news", LOG_NEWS,
1560Sstevel@tonic-gate "uucp", LOG_UUCP,
1570Sstevel@tonic-gate "audit", LOG_AUDIT,
1580Sstevel@tonic-gate "cron", LOG_CRON,
1590Sstevel@tonic-gate "local0", LOG_LOCAL0,
1600Sstevel@tonic-gate "local1", LOG_LOCAL1,
1610Sstevel@tonic-gate "local2", LOG_LOCAL2,
1620Sstevel@tonic-gate "local3", LOG_LOCAL3,
1630Sstevel@tonic-gate "local4", LOG_LOCAL4,
1640Sstevel@tonic-gate "local5", LOG_LOCAL5,
1650Sstevel@tonic-gate "local6", LOG_LOCAL6,
1660Sstevel@tonic-gate "local7", LOG_LOCAL7,
1670Sstevel@tonic-gate NULL, -1
1680Sstevel@tonic-gate };
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate static char *TypeNames[7] = {
1710Sstevel@tonic-gate "UNUSED", "FILE", "TTY", "CONSOLE",
1720Sstevel@tonic-gate "FORW", "USERS", "WALL"
1730Sstevel@tonic-gate };
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate * we allocate our own thread stacks so we can create them
1770Sstevel@tonic-gate * without the MAP_NORESERVE option. We need to be sure
1780Sstevel@tonic-gate * we have stack space even if the machine runs out of swap
1790Sstevel@tonic-gate */
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate #define DEFAULT_STACKSIZE (100 * 1024) /* 100 k stack */
1820Sstevel@tonic-gate #define DEFAULT_REDZONESIZE (8 * 1024) /* 8k redzone */
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate static pthread_mutex_t wmp = PTHREAD_MUTEX_INITIALIZER; /* wallmsg lock */
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate static pthread_mutex_t cft = PTHREAD_MUTEX_INITIALIZER;
1870Sstevel@tonic-gate static int conf_threads = 0;
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate static pthread_mutex_t hup_lock = PTHREAD_MUTEX_INITIALIZER;
1900Sstevel@tonic-gate static pthread_cond_t hup_done = PTHREAD_COND_INITIALIZER;
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate static pthread_mutex_t logerror_lock = PTHREAD_MUTEX_INITIALIZER;
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate #define HUP_ACCEPTABLE 0x0000 /* can start SIGHUP process */
1950Sstevel@tonic-gate #define HUP_INPROGRESS 0x0001 /* SIGHUP process in progress */
1960Sstevel@tonic-gate #define HUP_COMPLETED 0x0002 /* SIGHUP process completed */
1970Sstevel@tonic-gate #define HUP_SUSP_LOGMSG_REQD 0x1000 /* request to suspend */
1980Sstevel@tonic-gate #define HUP_LOGMSG_SUSPENDED 0x2000 /* logmsg is suspended */
1990Sstevel@tonic-gate static int hup_state = HUP_ACCEPTABLE;
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate static size_t stacksize; /* thread stack size */
2020Sstevel@tonic-gate static size_t redzonesize; /* thread stack redzone size */
2030Sstevel@tonic-gate static char *stack_ptr; /* ptr to allocated stacks */
2040Sstevel@tonic-gate static char *cstack_ptr; /* ptr to conf_thr stacks */
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate static time_t start_time;
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate static pthread_t sys_thread; /* queues messages from us */
2090Sstevel@tonic-gate static pthread_t net_thread; /* queues messages from the net */
2100Sstevel@tonic-gate static pthread_t log_thread; /* message processing thread */
2110Sstevel@tonic-gate static pthread_t hnl_thread; /* hostname lookup thread */
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate static dataq_t inputq; /* the input queue */
2140Sstevel@tonic-gate static dataq_t tmpq; /* temporary queue for err msg */
2150Sstevel@tonic-gate static dataq_t hnlq; /* hostname lookup queue */
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate static struct filed fallback[2];
2180Sstevel@tonic-gate static struct filed *Files;
2190Sstevel@tonic-gate static int nlogs;
2200Sstevel@tonic-gate static int Debug; /* debug flag */
2210Sstevel@tonic-gate static host_list_t LocalHostName; /* our hostname */
2220Sstevel@tonic-gate static host_list_t NullHostName; /* in case of lookup failure */
2230Sstevel@tonic-gate static int debuglev = 1; /* debug print level */
2240Sstevel@tonic-gate static int interrorlog; /* internal error logging */
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate static int MarkInterval = 20; /* interval between marks (mins) */
2270Sstevel@tonic-gate static int Marking = 0; /* non-zero if marking some file */
2280Sstevel@tonic-gate static int Ninputs = 0; /* number of network inputs */
2290Sstevel@tonic-gate static int curalarm = 0; /* current timeout value (secs) */
2300Sstevel@tonic-gate static int sys_msg_count = 0; /* total msgs rcvd from local log */
2310Sstevel@tonic-gate static int sys_init_msg_count = 0; /* initially received */
2320Sstevel@tonic-gate static int net_msg_count = 0; /* total msgs rcvd from net */
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate static struct pollfd Pfd; /* Pollfd for local the log device */
2350Sstevel@tonic-gate static struct pollfd *Nfd; /* Array of pollfds for udp ports */
2360Sstevel@tonic-gate static struct netconfig *Ncf;
2370Sstevel@tonic-gate static struct netbuf **Myaddrs;
2380Sstevel@tonic-gate static struct t_unitdata **Udp;
2390Sstevel@tonic-gate static struct t_uderr **Errp;
2400Sstevel@tonic-gate static int turnoff = 0;
2410Sstevel@tonic-gate static int shutting_down;
2420Sstevel@tonic-gate
2436358Snakanon /* for managing door server threads */
2446358Snakanon static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER;
2456358Snakanon static uint_t door_server_cnt = 0;
2466358Snakanon static pthread_attr_t door_thr_attr;
2476358Snakanon
248955Spd155743 static struct hostname_cache **hnc_cache;
2490Sstevel@tonic-gate static pthread_mutex_t hnc_mutex = PTHREAD_MUTEX_INITIALIZER;
2500Sstevel@tonic-gate static size_t hnc_size = DEF_HNC_SIZE;
2510Sstevel@tonic-gate static unsigned int hnc_ttl = DEF_HNC_TTL;
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate #define DPRINT0(d, m) if ((Debug) && debuglev >= (d)) \
2540Sstevel@tonic-gate (void) fprintf(stderr, m)
2550Sstevel@tonic-gate #define DPRINT1(d, m, a) if ((Debug) && debuglev >= (d)) \
2560Sstevel@tonic-gate (void) fprintf(stderr, m, a)
2570Sstevel@tonic-gate #define DPRINT2(d, m, a, b) if ((Debug) && debuglev >= (d)) \
2580Sstevel@tonic-gate (void) fprintf(stderr, m, a, b)
2590Sstevel@tonic-gate #define DPRINT3(d, m, a, b, c) if ((Debug) && debuglev >= (d)) \
2600Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c)
2610Sstevel@tonic-gate #define DPRINT4(d, m, a, b, c, e) if ((Debug) && debuglev >= (d)) \
2620Sstevel@tonic-gate (void) fprintf(stderr, m, a, b, c, e)
2630Sstevel@tonic-gate #define MALLOC_FAIL(x) \
2640Sstevel@tonic-gate logerror("malloc failed: " x)
2650Sstevel@tonic-gate #define MALLOC_FAIL_EXIT \
2660Sstevel@tonic-gate logerror("malloc failed - fatal"); \
2670Sstevel@tonic-gate exit(1)
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate #define MAILCMD "mailx -s \"syslogd shut down\" root"
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * Number of seconds to wait before giving up on threads that won't
2740Sstevel@tonic-gate * shutdown: (that's right, 10 minutes!)
2750Sstevel@tonic-gate */
2760Sstevel@tonic-gate #define LOOP_MAX (10 * 60)
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate * Interval(sec) to check the status of output queue while processing
2800Sstevel@tonic-gate * HUP signal.
2810Sstevel@tonic-gate */
2820Sstevel@tonic-gate #define LOOP_INTERVAL (15)
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate int
main(int argc,char ** argv)2850Sstevel@tonic-gate main(int argc, char **argv)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate int i;
2880Sstevel@tonic-gate char *pstr;
2890Sstevel@tonic-gate int sig, fd;
2900Sstevel@tonic-gate int tflag = 0, Tflag = 0;
2910Sstevel@tonic-gate sigset_t sigs, allsigs;
2920Sstevel@tonic-gate struct rlimit rlim;
2930Sstevel@tonic-gate char *debugstr;
2940Sstevel@tonic-gate int mcount = 0;
2950Sstevel@tonic-gate struct sigaction act;
2960Sstevel@tonic-gate pthread_t mythreadno = 0;
2970Sstevel@tonic-gate char cbuf [30];
2980Sstevel@tonic-gate struct stat sb;
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate #ifdef DEBUG
3010Sstevel@tonic-gate #define DEBUGDIR "/var/tmp"
3020Sstevel@tonic-gate if (chdir(DEBUGDIR))
3030Sstevel@tonic-gate DPRINT2(1, "main(%u): Unable to cd to %s\n", mythreadno,
3046358Snakanon DEBUGDIR);
3050Sstevel@tonic-gate #endif /* DEBUG */
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate if ((debugstr = getenv("SYSLOGD_DEBUG")) != NULL)
3100Sstevel@tonic-gate if ((debuglev = atoi(debugstr)) == 0)
3110Sstevel@tonic-gate debuglev = 1;
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate #if ! defined(TEXT_DOMAIN) /* should be defined by cc -D */
3140Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
3150Sstevel@tonic-gate #endif
3160Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate (void) time(&start_time);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate if (lstat("/var/run", &sb) != 0 || !(S_ISDIR(sb.st_mode))) {
3210Sstevel@tonic-gate DoorFileName = OLD_DOORFILE;
3220Sstevel@tonic-gate PidFileName = OLD_PIDFILE;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate
3252104Sjjj properties();
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate while ((i = getopt(argc, argv, "df:p:m:tT")) != EOF) {
3280Sstevel@tonic-gate switch (i) {
3290Sstevel@tonic-gate case 'f': /* configuration file */
3300Sstevel@tonic-gate ConfFile = optarg;
3310Sstevel@tonic-gate break;
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate case 'd': /* debug */
3340Sstevel@tonic-gate Debug++;
3350Sstevel@tonic-gate break;
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate case 'p': /* path */
3380Sstevel@tonic-gate LogName = optarg;
3390Sstevel@tonic-gate break;
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate case 'm': /* mark interval */
3420Sstevel@tonic-gate for (pstr = optarg; *pstr; pstr++) {
3430Sstevel@tonic-gate if (! (isdigit(*pstr))) {
3440Sstevel@tonic-gate (void) fprintf(stderr,
3456358Snakanon "Illegal interval\n");
3460Sstevel@tonic-gate usage();
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate MarkInterval = atoi(optarg);
3500Sstevel@tonic-gate if (MarkInterval < 1 || MarkInterval > INT_MAX) {
3510Sstevel@tonic-gate (void) fprintf(stderr,
3526358Snakanon "Interval must be between 1 and %d\n",
3536358Snakanon INT_MAX);
3540Sstevel@tonic-gate usage();
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate break;
3570Sstevel@tonic-gate case 't': /* turn off remote reception */
3580Sstevel@tonic-gate tflag++;
3590Sstevel@tonic-gate turnoff++;
3600Sstevel@tonic-gate break;
3610Sstevel@tonic-gate case 'T': /* turn on remote reception */
3620Sstevel@tonic-gate Tflag++;
3630Sstevel@tonic-gate turnoff = 0;
3640Sstevel@tonic-gate break;
3650Sstevel@tonic-gate default:
3660Sstevel@tonic-gate usage();
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if (optind < argc)
3710Sstevel@tonic-gate usage();
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate if (tflag && Tflag) {
3740Sstevel@tonic-gate (void) fprintf(stderr, "specify only one of -t and -T\n");
3750Sstevel@tonic-gate usage();
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate /*
3790Sstevel@tonic-gate * close all fd's except 0-2
3800Sstevel@tonic-gate */
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate closefrom(3);
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate if (!Debug) {
3850Sstevel@tonic-gate if (fork())
3860Sstevel@tonic-gate return (0);
3870Sstevel@tonic-gate (void) close(0);
3880Sstevel@tonic-gate (void) open("/", 0);
3890Sstevel@tonic-gate (void) dup2(0, 1);
3900Sstevel@tonic-gate (void) dup2(0, 2);
3910Sstevel@tonic-gate untty();
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate if (Debug) {
3950Sstevel@tonic-gate mythreadno = pthread_self();
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate /*
3990Sstevel@tonic-gate * DO NOT call logerror() until tmpq is initialized.
4000Sstevel@tonic-gate */
4010Sstevel@tonic-gate disable_errorlog();
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate /*
4040Sstevel@tonic-gate * ensure that file descriptor limit is "high enough"
4050Sstevel@tonic-gate */
4060Sstevel@tonic-gate (void) getrlimit(RLIMIT_NOFILE, &rlim);
4070Sstevel@tonic-gate if (rlim.rlim_cur < rlim.rlim_max)
4080Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max;
4090Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
4100Sstevel@tonic-gate logerror("Unable to increase file descriptor limit.");
4111914Scasper (void) enable_extended_FILE_stdio(-1, -1);
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /* block all signals from all threads initially */
4140Sstevel@tonic-gate (void) sigfillset(&allsigs);
4150Sstevel@tonic-gate (void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL);
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate DPRINT2(1, "main(%u): Started at time %s", mythreadno,
4186358Snakanon ctime_r(&start_time, cbuf));
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate init(); /* read configuration, start threads */
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate DPRINT1(1, "main(%u): off & running....\n", mythreadno);
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /* now set up to catch signals we care about */
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate (void) sigemptyset(&sigs);
4270Sstevel@tonic-gate (void) sigaddset(&sigs, SIGHUP); /* reconfigure */
4280Sstevel@tonic-gate (void) sigaddset(&sigs, SIGALRM); /* mark & flush timer */
4290Sstevel@tonic-gate (void) sigaddset(&sigs, SIGTERM); /* exit */
4300Sstevel@tonic-gate (void) sigaddset(&sigs, SIGINT); /* exit if debugging */
4310Sstevel@tonic-gate (void) sigaddset(&sigs, SIGQUIT); /* exit if debugging */
4320Sstevel@tonic-gate (void) sigaddset(&sigs, SIGPIPE); /* catch & discard */
4330Sstevel@tonic-gate (void) sigaddset(&sigs, SIGUSR1); /* dump debug stats */
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate * We must set up to catch these signals, even though sigwait
4370Sstevel@tonic-gate * will get them before the isr does. Setting SA_SIGINFO ensures
4380Sstevel@tonic-gate * that signals will be enqueued.
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
4420Sstevel@tonic-gate act.sa_sigaction = signull;
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate (void) sigaction(SIGHUP, &act, NULL);
4450Sstevel@tonic-gate (void) sigaction(SIGALRM, &act, NULL);
4460Sstevel@tonic-gate (void) sigaction(SIGTERM, &act, NULL);
4470Sstevel@tonic-gate (void) sigaction(SIGINT, &act, NULL);
4480Sstevel@tonic-gate (void) sigaction(SIGQUIT, &act, NULL);
4490Sstevel@tonic-gate (void) sigaction(SIGPIPE, &act, NULL);
4500Sstevel@tonic-gate (void) sigaction(SIGUSR1, &act, NULL);
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /* we now turn into the signal handling thread */
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate DPRINT1(2, "main(%u): now handling signals\n", mythreadno);
4550Sstevel@tonic-gate for (;;) {
4560Sstevel@tonic-gate (void) sigwait(&sigs, &sig);
4570Sstevel@tonic-gate DPRINT2(2, "main(%u): received signal %d\n", mythreadno, sig);
4580Sstevel@tonic-gate switch (sig) {
4590Sstevel@tonic-gate case SIGALRM:
4600Sstevel@tonic-gate DPRINT1(1, "main(%u): Got SIGALRM\n",
4616358Snakanon mythreadno);
4620Sstevel@tonic-gate flushmsg(NOCOPY);
4630Sstevel@tonic-gate if (Marking && (++mcount % MARKCOUNT == 0)) {
4640Sstevel@tonic-gate if (logmymsg(LOG_INFO, "-- MARK --",
4656358Snakanon ADDDATE|MARK|NOCOPY, 0) == -1) {
4660Sstevel@tonic-gate MALLOC_FAIL(
4676358Snakanon "dropping MARK message");
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate mcount = 0;
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT;
4730Sstevel@tonic-gate (void) alarm((unsigned)curalarm);
4740Sstevel@tonic-gate DPRINT2(2, "main(%u): Next alarm in %d "
4756358Snakanon "seconds\n", mythreadno, curalarm);
4760Sstevel@tonic-gate break;
4770Sstevel@tonic-gate case SIGHUP:
4780Sstevel@tonic-gate DPRINT1(1, "main(%u): got SIGHUP - "
4796358Snakanon "reconfiguring\n", mythreadno);
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate reconfigure();
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate DPRINT1(1, "main(%u): done processing SIGHUP\n",
4846358Snakanon mythreadno);
4850Sstevel@tonic-gate break;
4860Sstevel@tonic-gate case SIGQUIT:
4870Sstevel@tonic-gate case SIGINT:
4880Sstevel@tonic-gate if (!Debug) {
4890Sstevel@tonic-gate /* allow these signals if debugging */
4900Sstevel@tonic-gate break;
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate /* FALLTHROUGH */
4930Sstevel@tonic-gate case SIGTERM:
4940Sstevel@tonic-gate DPRINT2(1, "main(%u): going down on signal %d\n",
4956358Snakanon mythreadno, sig);
4960Sstevel@tonic-gate (void) alarm(0);
4970Sstevel@tonic-gate flushmsg(0);
4980Sstevel@tonic-gate errno = 0;
4990Sstevel@tonic-gate t_errno = 0;
5000Sstevel@tonic-gate logerror("going down on signal %d", sig);
5010Sstevel@tonic-gate disable_errorlog(); /* force msg to console */
5020Sstevel@tonic-gate (void) shutdown_msg(); /* stop threads */
5030Sstevel@tonic-gate shutdown_input();
5040Sstevel@tonic-gate close_door();
5050Sstevel@tonic-gate delete_doorfiles();
5060Sstevel@tonic-gate return (0);
5070Sstevel@tonic-gate break;
5080Sstevel@tonic-gate case SIGUSR1: /* secret debug dump mode */
5090Sstevel@tonic-gate /* if in debug mode, use stdout */
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate if (Debug) {
5120Sstevel@tonic-gate dumpstats(STDOUT_FILENO);
5130Sstevel@tonic-gate break;
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate /* otherwise dump to a debug file */
5160Sstevel@tonic-gate if ((fd = open(DEBUGFILE,
5176358Snakanon (O_WRONLY|O_CREAT|O_TRUNC|O_EXCL),
5186358Snakanon 0644)) < 0)
5190Sstevel@tonic-gate break;
5200Sstevel@tonic-gate dumpstats(fd);
5210Sstevel@tonic-gate (void) close(fd);
5220Sstevel@tonic-gate break;
5230Sstevel@tonic-gate default:
5240Sstevel@tonic-gate DPRINT2(2, "main(%u): unexpected signal %d\n",
5256358Snakanon mythreadno, sig);
5260Sstevel@tonic-gate break;
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate /*
5320Sstevel@tonic-gate * Attempts to open the local log device
5330Sstevel@tonic-gate * and return a file descriptor.
5340Sstevel@tonic-gate */
5350Sstevel@tonic-gate static int
openklog(char * name,int mode)5360Sstevel@tonic-gate openklog(char *name, int mode)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate int fd;
5390Sstevel@tonic-gate struct strioctl str;
5400Sstevel@tonic-gate pthread_t mythreadno;
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate if (Debug) {
5430Sstevel@tonic-gate mythreadno = pthread_self();
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate if ((fd = open(name, mode)) < 0) {
5470Sstevel@tonic-gate logerror("cannot open %s", name);
5480Sstevel@tonic-gate DPRINT3(1, "openklog(%u): cannot create %s (%d)\n",
5496358Snakanon mythreadno, name, errno);
5500Sstevel@tonic-gate return (-1);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate str.ic_cmd = I_CONSLOG;
5530Sstevel@tonic-gate str.ic_timout = 0;
5540Sstevel@tonic-gate str.ic_len = 0;
5550Sstevel@tonic-gate str.ic_dp = NULL;
5560Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) < 0) {
5570Sstevel@tonic-gate logerror("cannot register to log console messages");
5580Sstevel@tonic-gate DPRINT2(1, "openklog(%u): cannot register to log "
5596358Snakanon "console messages (%d)\n", mythreadno, errno);
5600Sstevel@tonic-gate return (-1);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate return (fd);
5630Sstevel@tonic-gate }
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate /*
5670Sstevel@tonic-gate * Open the log device, and pull up all pending messages.
5680Sstevel@tonic-gate */
5690Sstevel@tonic-gate static void
prepare_sys_poll()5700Sstevel@tonic-gate prepare_sys_poll()
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate int nfds, funix;
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate if ((funix = openklog(LogName, O_RDONLY)) < 0) {
5750Sstevel@tonic-gate logerror("can't open kernel log device - fatal");
5760Sstevel@tonic-gate exit(1);
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate Pfd.fd = funix;
5800Sstevel@tonic-gate Pfd.events = POLLIN;
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate for (;;) {
5830Sstevel@tonic-gate nfds = poll(&Pfd, 1, 0);
5840Sstevel@tonic-gate if (nfds <= 0) {
5850Sstevel@tonic-gate if (sys_init_msg_count > 0)
5860Sstevel@tonic-gate flushmsg(SYNC_FILE);
5870Sstevel@tonic-gate break;
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate if (Pfd.revents & POLLIN) {
5910Sstevel@tonic-gate getkmsg(0);
5920Sstevel@tonic-gate } else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
5930Sstevel@tonic-gate logerror("kernel log driver poll error");
5940Sstevel@tonic-gate break;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate * this thread listens to the local stream log driver for log messages
6020Sstevel@tonic-gate * generated by this host, formats them, and queues them to the logger
6030Sstevel@tonic-gate * thread.
6040Sstevel@tonic-gate */
6050Sstevel@tonic-gate /*ARGSUSED*/
6060Sstevel@tonic-gate static void *
sys_poll(void * ap)6070Sstevel@tonic-gate sys_poll(void *ap)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate int nfds;
6100Sstevel@tonic-gate static int klogerrs = 0;
6110Sstevel@tonic-gate pthread_t mythreadno;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate if (Debug) {
6140Sstevel@tonic-gate mythreadno = pthread_self();
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate DPRINT1(1, "sys_poll(%u): sys_thread started\n", mythreadno);
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate * Try to process as many messages as we can without blocking on poll.
6210Sstevel@tonic-gate * We count such "initial" messages with sys_init_msg_count and
6220Sstevel@tonic-gate * enqueue them without the SYNC_FILE flag. When no more data is
6230Sstevel@tonic-gate * waiting on the local log device, we set timeout to INFTIM,
6240Sstevel@tonic-gate * clear sys_init_msg_count, and generate a flush message to sync
6250Sstevel@tonic-gate * the previously counted initial messages out to disk.
6260Sstevel@tonic-gate */
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate sys_init_msg_count = 0;
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate for (;;) {
6310Sstevel@tonic-gate errno = 0;
6320Sstevel@tonic-gate t_errno = 0;
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate nfds = poll(&Pfd, 1, INFTIM);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate if (nfds == 0)
6370Sstevel@tonic-gate continue;
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate if (nfds < 0) {
6400Sstevel@tonic-gate if (errno != EINTR)
6410Sstevel@tonic-gate logerror("poll");
6420Sstevel@tonic-gate continue;
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate if (Pfd.revents & POLLIN) {
6450Sstevel@tonic-gate getkmsg(INFTIM);
6460Sstevel@tonic-gate } else {
6470Sstevel@tonic-gate if (shutting_down) {
6480Sstevel@tonic-gate pthread_exit(0);
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
6510Sstevel@tonic-gate logerror("kernel log driver poll error");
6520Sstevel@tonic-gate (void) close(Pfd.fd);
6530Sstevel@tonic-gate Pfd.fd = -1;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate while (Pfd.fd == -1 && klogerrs++ < 10) {
6580Sstevel@tonic-gate Pfd.fd = openklog(LogName, O_RDONLY);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate if (klogerrs >= 10) {
6610Sstevel@tonic-gate logerror("can't reopen kernel log device - fatal");
6620Sstevel@tonic-gate exit(1);
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate /*NOTREACHED*/
6660Sstevel@tonic-gate return (NULL);
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate * Pull up one message from log driver.
6710Sstevel@tonic-gate */
6720Sstevel@tonic-gate static void
getkmsg(int timeout)6730Sstevel@tonic-gate getkmsg(int timeout)
6740Sstevel@tonic-gate {
6750Sstevel@tonic-gate int flags = 0, i;
6760Sstevel@tonic-gate char *lastline;
6770Sstevel@tonic-gate struct strbuf ctl, dat;
6780Sstevel@tonic-gate struct log_ctl hdr;
6790Sstevel@tonic-gate char buf[MAXLINE+1];
6800Sstevel@tonic-gate size_t buflen;
6810Sstevel@tonic-gate size_t len;
6820Sstevel@tonic-gate char tmpbuf[MAXLINE+1];
6830Sstevel@tonic-gate pthread_t mythreadno;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate if (Debug) {
6860Sstevel@tonic-gate mythreadno = pthread_self();
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate dat.maxlen = MAXLINE;
6900Sstevel@tonic-gate dat.buf = buf;
6910Sstevel@tonic-gate ctl.maxlen = sizeof (struct log_ctl);
6920Sstevel@tonic-gate ctl.buf = (caddr_t)&hdr;
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) {
6950Sstevel@tonic-gate lastline = &dat.buf[dat.len];
6960Sstevel@tonic-gate *lastline = '\0';
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate DPRINT2(5, "sys_poll:(%u): getmsg: dat.len = %d\n",
6996358Snakanon mythreadno, dat.len);
7000Sstevel@tonic-gate buflen = strlen(buf);
7010Sstevel@tonic-gate len = findnl_bkwd(buf, buflen);
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate (void) memcpy(tmpbuf, buf, len);
7040Sstevel@tonic-gate tmpbuf[len] = '\0';
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate /*
7070Sstevel@tonic-gate * Format sys will enqueue the log message.
7080Sstevel@tonic-gate * Set the sync flag if timeout != 0, which
7090Sstevel@tonic-gate * means that we're done handling all the
7100Sstevel@tonic-gate * initial messages ready during startup.
7110Sstevel@tonic-gate */
7120Sstevel@tonic-gate if (timeout == 0) {
7130Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 0);
7140Sstevel@tonic-gate sys_init_msg_count++;
7150Sstevel@tonic-gate } else {
7160Sstevel@tonic-gate formatsys(&hdr, tmpbuf, 1);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate sys_msg_count++;
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate if (len != buflen) {
7210Sstevel@tonic-gate /* If anything remains in buf */
7220Sstevel@tonic-gate size_t remlen;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate if (buf[len] == '\n') {
7250Sstevel@tonic-gate /* skip newline */
7260Sstevel@tonic-gate len++;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate /*
7300Sstevel@tonic-gate * Move the remaining bytes to
7310Sstevel@tonic-gate * the beginnning of buf.
7320Sstevel@tonic-gate */
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate remlen = buflen - len;
7350Sstevel@tonic-gate (void) memcpy(buf, &buf[len], remlen);
7360Sstevel@tonic-gate dat.maxlen = MAXLINE - remlen;
7370Sstevel@tonic-gate dat.buf = &buf[remlen];
7380Sstevel@tonic-gate } else {
7390Sstevel@tonic-gate dat.maxlen = MAXLINE;
7400Sstevel@tonic-gate dat.buf = buf;
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate if (i == 0 && dat.len > 0) {
7450Sstevel@tonic-gate dat.buf[dat.len] = '\0';
7460Sstevel@tonic-gate /*
7470Sstevel@tonic-gate * Format sys will enqueue the log message.
7480Sstevel@tonic-gate * Set the sync flag if timeout != 0, which
7490Sstevel@tonic-gate * means that we're done handling all the
7500Sstevel@tonic-gate * initial messages ready during startup.
7510Sstevel@tonic-gate */
7520Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.maxlen = %d\n",
7536358Snakanon mythreadno, dat.maxlen);
7540Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.len = %d\n",
7556358Snakanon mythreadno, dat.len);
7560Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: strlen(dat.buf) = %d\n",
7576358Snakanon mythreadno, strlen(dat.buf));
7580Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): getmsg: dat.buf = \"%s\"\n",
7596358Snakanon mythreadno, dat.buf);
7600Sstevel@tonic-gate DPRINT2(5, "getkmsg(%u): buf len = %d\n",
7616358Snakanon mythreadno, strlen(buf));
7620Sstevel@tonic-gate if (timeout == 0) {
7630Sstevel@tonic-gate formatsys(&hdr, buf, 0);
7640Sstevel@tonic-gate sys_init_msg_count++;
7650Sstevel@tonic-gate } else {
7660Sstevel@tonic-gate formatsys(&hdr, buf, 1);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate sys_msg_count++;
7690Sstevel@tonic-gate } else if (i < 0 && errno != EINTR) {
7700Sstevel@tonic-gate if (!shutting_down) {
7710Sstevel@tonic-gate logerror("kernel log driver read error");
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate (void) close(Pfd.fd);
7740Sstevel@tonic-gate Pfd.fd = -1;
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate /*
7790Sstevel@tonic-gate * this thread polls all the network interfaces for syslog messages
7800Sstevel@tonic-gate * forwarded to us, tags them with the hostname they are received
7810Sstevel@tonic-gate * from, and queues them to the logger thread.
7820Sstevel@tonic-gate */
7830Sstevel@tonic-gate /*ARGSUSED*/
7840Sstevel@tonic-gate static void *
net_poll(void * ap)7850Sstevel@tonic-gate net_poll(void *ap)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate int nfds, i;
7880Sstevel@tonic-gate int flags = 0;
7890Sstevel@tonic-gate struct t_unitdata *udp;
7900Sstevel@tonic-gate struct t_uderr *errp;
7910Sstevel@tonic-gate char buf[MAXLINE+1];
7920Sstevel@tonic-gate char *uap;
7930Sstevel@tonic-gate log_message_t *mp;
7940Sstevel@tonic-gate host_info_t *hinfo;
7950Sstevel@tonic-gate pthread_t mythreadno;
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate if (Debug) {
7980Sstevel@tonic-gate mythreadno = pthread_self();
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): net_thread started\n", mythreadno);
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate for (;;) {
8060Sstevel@tonic-gate errno = 0;
8070Sstevel@tonic-gate t_errno = 0;
8080Sstevel@tonic-gate nfds = poll(Nfd, Ninputs, -1);
8090Sstevel@tonic-gate if (nfds == 0)
8100Sstevel@tonic-gate continue;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate if (nfds < 0) {
8130Sstevel@tonic-gate if (errno != EINTR)
8140Sstevel@tonic-gate logerror("poll");
8150Sstevel@tonic-gate continue;
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate for (i = 0; nfds > 0 && i < Ninputs; i++) {
8180Sstevel@tonic-gate if ((Nfd[i].revents & POLLIN) == 0) {
8190Sstevel@tonic-gate if (shutting_down) {
8200Sstevel@tonic-gate pthread_exit(0);
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate if (Nfd[i].revents &
8236358Snakanon (POLLNVAL|POLLHUP|POLLERR)) {
8240Sstevel@tonic-gate logerror("POLLNVAL|POLLHUP|POLLERR");
8250Sstevel@tonic-gate (void) t_close(Nfd[i].fd);
8260Sstevel@tonic-gate Nfd[i].fd = -1;
8270Sstevel@tonic-gate nfds--;
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate continue;
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate udp = Udp[i];
8330Sstevel@tonic-gate udp->udata.buf = buf;
8340Sstevel@tonic-gate udp->udata.maxlen = MAXLINE;
8350Sstevel@tonic-gate udp->udata.len = 0;
8360Sstevel@tonic-gate flags = 0;
8370Sstevel@tonic-gate if (t_rcvudata(Nfd[i].fd, udp, &flags) < 0) {
8380Sstevel@tonic-gate errp = Errp[i];
8390Sstevel@tonic-gate if (t_errno == TLOOK) {
8400Sstevel@tonic-gate if (t_rcvuderr(Nfd[i].fd, errp) < 0) {
8410Sstevel@tonic-gate if (!shutting_down) {
8420Sstevel@tonic-gate logerror("t_rcvuderr");
8430Sstevel@tonic-gate }
8442104Sjjj (void) t_close(Nfd[i].fd);
8450Sstevel@tonic-gate Nfd[i].fd = -1;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate } else {
8480Sstevel@tonic-gate if (!shutting_down) {
8490Sstevel@tonic-gate logerror("t_rcvudata");
8500Sstevel@tonic-gate }
8512104Sjjj (void) t_close(Nfd[i].fd);
8520Sstevel@tonic-gate Nfd[i].fd = -1;
8530Sstevel@tonic-gate }
8540Sstevel@tonic-gate nfds--;
8550Sstevel@tonic-gate if (shutting_down) {
8560Sstevel@tonic-gate pthread_exit(0);
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate continue;
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate nfds--;
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate if (udp->udata.len == 0) {
8630Sstevel@tonic-gate if (Debug) {
8640Sstevel@tonic-gate uap = NULL;
8650Sstevel@tonic-gate if (udp->addr.len > 0) {
8660Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i],
8676358Snakanon &udp->addr);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate DPRINT2(1, "net_poll(%u):"
8706358Snakanon " received empty packet"
8716358Snakanon " from %s\n", mythreadno,
8726358Snakanon uap ? uap : "<unknown>");
8730Sstevel@tonic-gate if (uap)
8740Sstevel@tonic-gate free(uap);
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate continue; /* No data */
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate if (udp->addr.len == 0) {
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate * The previous message was larger than
8810Sstevel@tonic-gate * MAXLINE, and T_MORE should have been set.
8820Sstevel@tonic-gate * Further data needs to be discarded as
8830Sstevel@tonic-gate * we've already received MAXLINE.
8840Sstevel@tonic-gate */
8850Sstevel@tonic-gate DPRINT1(1, "net_poll(%u): discarding packet "
8866358Snakanon "exceeds max line size\n", mythreadno);
8870Sstevel@tonic-gate continue;
8880Sstevel@tonic-gate }
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate net_msg_count++;
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
8930Sstevel@tonic-gate MALLOC_FAIL("dropping message from "
8946358Snakanon "remote");
8950Sstevel@tonic-gate continue;
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate buf[udp->udata.len] = '\0';
8990Sstevel@tonic-gate formatnet(&udp->udata, mp);
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate if (Debug) {
9020Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[i], &udp->addr);
9030Sstevel@tonic-gate DPRINT2(1, "net_poll(%u): received message"
9046358Snakanon " from %s\n", mythreadno,
9056358Snakanon uap ? uap : "<unknown>");
9060Sstevel@tonic-gate free(uap);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate if ((hinfo = malloc(sizeof (*hinfo))) == NULL ||
9096358Snakanon (hinfo->addr.buf =
9106358Snakanon malloc(udp->addr.len)) == NULL) {
9110Sstevel@tonic-gate MALLOC_FAIL("dropping message from "
9126358Snakanon "remote");
9130Sstevel@tonic-gate if (hinfo) {
9140Sstevel@tonic-gate free(hinfo);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate free_msg(mp);
9170Sstevel@tonic-gate continue;
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate hinfo->ncp = &Ncf[i];
9210Sstevel@tonic-gate hinfo->addr.len = udp->addr.len;
9220Sstevel@tonic-gate (void) memcpy(hinfo->addr.buf, udp->addr.buf,
9236358Snakanon udp->addr.len);
9240Sstevel@tonic-gate mp->ptr = hinfo;
9250Sstevel@tonic-gate if (dataq_enqueue(&hnlq, (void *)mp) == -1) {
9260Sstevel@tonic-gate MALLOC_FAIL("dropping message from "
9276358Snakanon "remote");
9280Sstevel@tonic-gate free_msg(mp);
9290Sstevel@tonic-gate free(hinfo->addr.buf);
9300Sstevel@tonic-gate free(hinfo);
9310Sstevel@tonic-gate continue;
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate DPRINT3(5, "net_poll(%u): enqueued msg %p "
9346358Snakanon "on queue %p\n", mythreadno, (void *)mp,
9356358Snakanon (void *)&hnlq);
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate /*NOTREACHED*/
9390Sstevel@tonic-gate return (NULL);
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate static void
usage(void)9430Sstevel@tonic-gate usage(void)
9440Sstevel@tonic-gate {
9450Sstevel@tonic-gate (void) fprintf(stderr,
9460Sstevel@tonic-gate "usage: syslogd [-d] [-t|-T] [-mmarkinterval] [-ppath]"
9470Sstevel@tonic-gate " [-fconffile]\n");
9480Sstevel@tonic-gate exit(1);
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate static void
untty(void)9520Sstevel@tonic-gate untty(void)
9530Sstevel@tonic-gate {
9540Sstevel@tonic-gate if (!Debug)
9550Sstevel@tonic-gate (void) setsid();
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate /*
9590Sstevel@tonic-gate * generate a log message internally. The original version of syslogd
9600Sstevel@tonic-gate * simply called logmsg directly, but because everything is now based
9610Sstevel@tonic-gate * on message passing, we need an internal way to generate and queue
9620Sstevel@tonic-gate * log messages from within syslogd itself.
9630Sstevel@tonic-gate */
9640Sstevel@tonic-gate static int
logmymsg(int pri,char * msg,int flags,int pending)9650Sstevel@tonic-gate logmymsg(int pri, char *msg, int flags, int pending)
9660Sstevel@tonic-gate {
9670Sstevel@tonic-gate log_message_t *mp;
9680Sstevel@tonic-gate pthread_t mythreadno;
9690Sstevel@tonic-gate dataq_t *qptr;
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate if (Debug) {
9720Sstevel@tonic-gate mythreadno = pthread_self();
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
9760Sstevel@tonic-gate return (-1);
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
9800Sstevel@tonic-gate mp->pri = pri;
9810Sstevel@tonic-gate mp->hlp = &LocalHostName;
9820Sstevel@tonic-gate (void) strlcpy(mp->msg, msg, MAXLINE+1);
9830Sstevel@tonic-gate mp->flags = flags;
9840Sstevel@tonic-gate (void) time(&mp->ts);
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate qptr = pending ? &tmpq : &inputq;
9870Sstevel@tonic-gate if (dataq_enqueue(qptr, (void *)mp) == -1) {
9880Sstevel@tonic-gate free_msg(mp);
9890Sstevel@tonic-gate return (-1);
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate DPRINT3(5, "logmymsg(%u): enqueued msg %p on queue %p\n",
9936358Snakanon mythreadno, (void *)mp, (void *)qptr);
9940Sstevel@tonic-gate DPRINT2(5, "logmymsg(%u): Message content: %s\n", mythreadno, msg);
9950Sstevel@tonic-gate return (0);
9960Sstevel@tonic-gate }
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate /*
9990Sstevel@tonic-gate * Generate an internal shutdown message
10000Sstevel@tonic-gate */
10010Sstevel@tonic-gate static int
shutdown_msg(void)10020Sstevel@tonic-gate shutdown_msg(void)
10030Sstevel@tonic-gate {
10040Sstevel@tonic-gate pthread_t mythreadno;
10050Sstevel@tonic-gate log_message_t *mp;
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate if (Debug) {
10080Sstevel@tonic-gate mythreadno = pthread_self();
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
10120Sstevel@tonic-gate return (-1);
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
10160Sstevel@tonic-gate mp->flags = SHUTDOWN;
10170Sstevel@tonic-gate mp->hlp = &LocalHostName;
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) {
10200Sstevel@tonic-gate free_msg(mp);
10210Sstevel@tonic-gate return (-1);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate DPRINT3(5, "shutdown_msg(%u): enqueued msg %p on queue %p\n",
10256358Snakanon mythreadno, (void *)mp, (void *)&inputq);
10260Sstevel@tonic-gate return (0);
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate /*
10300Sstevel@tonic-gate * Generate an internal flush message
10310Sstevel@tonic-gate */
10320Sstevel@tonic-gate static void
flushmsg(int flags)10330Sstevel@tonic-gate flushmsg(int flags)
10340Sstevel@tonic-gate {
10350Sstevel@tonic-gate log_message_t *mp;
10360Sstevel@tonic-gate pthread_t mythreadno;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (Debug) {
10390Sstevel@tonic-gate mythreadno = pthread_self();
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
10430Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg");
10440Sstevel@tonic-gate return;
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
10480Sstevel@tonic-gate mp->flags = FLUSHMSG | flags;
10490Sstevel@tonic-gate mp->hlp = &LocalHostName;
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) {
10520Sstevel@tonic-gate free_msg(mp);
10530Sstevel@tonic-gate MALLOC_FAIL("dropping flush msg");
10540Sstevel@tonic-gate return;
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate DPRINT4(5, "flush_msg(%u): enqueued msg %p on queue %p, flags "
10586358Snakanon "0x%x\n", mythreadno, (void *)mp, (void *)&inputq, flags);
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate /*
10620Sstevel@tonic-gate * Do some processing on messages received from the net
10630Sstevel@tonic-gate */
10640Sstevel@tonic-gate static void
formatnet(struct netbuf * nbp,log_message_t * mp)10650Sstevel@tonic-gate formatnet(struct netbuf *nbp, log_message_t *mp)
10660Sstevel@tonic-gate {
10670Sstevel@tonic-gate char *p;
10680Sstevel@tonic-gate int pri;
10690Sstevel@tonic-gate pthread_t mythreadno;
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate if (Debug) {
10720Sstevel@tonic-gate mythreadno = pthread_self();
10730Sstevel@tonic-gate }
10740Sstevel@tonic-gate
10752104Sjjj DPRINT2(5, "formatnet(%u): called for msg %p\n", mythreadno,
10766358Snakanon (void *)mp);
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate mp->flags = NETWORK;
10790Sstevel@tonic-gate (void) time(&mp->ts);
10800Sstevel@tonic-gate
10810Sstevel@tonic-gate /* test for special codes */
10820Sstevel@tonic-gate pri = DEFUPRI;
10830Sstevel@tonic-gate p = nbp->buf;
10840Sstevel@tonic-gate DPRINT2(9, "formatnet(%u): Message content:\n>%s<\n", mythreadno,
10856358Snakanon p);
10860Sstevel@tonic-gate if (*p == '<' && isdigit(*(p+1))) {
10870Sstevel@tonic-gate pri = 0;
10880Sstevel@tonic-gate while (isdigit(*++p))
10890Sstevel@tonic-gate pri = 10 * pri + (*p - '0');
10900Sstevel@tonic-gate if (*p == '>')
10910Sstevel@tonic-gate ++p;
10920Sstevel@tonic-gate if (pri <= 0 || pri >= (LOG_NFACILITIES << 3))
10930Sstevel@tonic-gate pri = DEFUPRI;
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate mp->pri = pri;
10970Sstevel@tonic-gate (void) strlcpy(mp->msg, p, MAXLINE+1);
10980Sstevel@tonic-gate }
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate /*
11010Sstevel@tonic-gate * Do some processing on messages generated by this host
11020Sstevel@tonic-gate * and then enqueue the log message.
11030Sstevel@tonic-gate */
11040Sstevel@tonic-gate static void
formatsys(struct log_ctl * lp,char * msg,int sync)11050Sstevel@tonic-gate formatsys(struct log_ctl *lp, char *msg, int sync)
11060Sstevel@tonic-gate {
11070Sstevel@tonic-gate char *p, *q;
11080Sstevel@tonic-gate char line[MAXLINE + 1];
11090Sstevel@tonic-gate size_t msglen;
11100Sstevel@tonic-gate log_message_t *mp;
11110Sstevel@tonic-gate char cbuf[30];
11120Sstevel@tonic-gate pthread_t mythreadno;
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate if (Debug) {
11150Sstevel@tonic-gate mythreadno = pthread_self();
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate DPRINT3(3, "formatsys(%u): log_ctl.mid = %d, log_ctl.sid = %d\n",
11196358Snakanon mythreadno, lp->mid, lp->sid);
11200Sstevel@tonic-gate DPRINT2(9, "formatsys(%u): Message Content:\n>%s<\n", mythreadno,
11216358Snakanon msg);
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate /* msglen includes the null termination */
11240Sstevel@tonic-gate msglen = strlen(msg) + 1;
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate for (p = msg; *p != '\0'; ) {
11270Sstevel@tonic-gate size_t linelen;
11280Sstevel@tonic-gate size_t len;
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate * Allocate a log_message_t structure.
11320Sstevel@tonic-gate * We should do it here since a single message (msg)
11330Sstevel@tonic-gate * could be composed of many lines.
11340Sstevel@tonic-gate */
11350Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
11380Sstevel@tonic-gate MALLOC_FAIL("dropping message");
11390Sstevel@tonic-gate /*
11400Sstevel@tonic-gate * Should bail out from the loop.
11410Sstevel@tonic-gate */
11420Sstevel@tonic-gate break;
11430Sstevel@tonic-gate }
11440Sstevel@tonic-gate
11450Sstevel@tonic-gate mp->flags &= ~NETWORK;
11460Sstevel@tonic-gate mp->hlp = &LocalHostName;
11470Sstevel@tonic-gate mp->ts = lp->ttime;
11480Sstevel@tonic-gate if (lp->flags & SL_LOGONLY)
11490Sstevel@tonic-gate mp->flags |= IGN_CONS;
11500Sstevel@tonic-gate if (lp->flags & SL_CONSONLY)
11510Sstevel@tonic-gate mp->flags |= IGN_FILE;
11520Sstevel@tonic-gate
11530Sstevel@tonic-gate /* extract facility */
11540Sstevel@tonic-gate if ((lp->pri & LOG_FACMASK) == LOG_KERN) {
11550Sstevel@tonic-gate (void) sprintf(line, "%.15s ",
11566358Snakanon ctime_r(&mp->ts, cbuf) + 4);
11570Sstevel@tonic-gate } else {
11580Sstevel@tonic-gate (void) sprintf(line, "");
11590Sstevel@tonic-gate }
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate linelen = strlen(line);
11620Sstevel@tonic-gate q = line + linelen;
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): msglen = %d\n", mythreadno, msglen);
11650Sstevel@tonic-gate len = copynl_frwd(q, MAXLINE + 1 - linelen, p, msglen);
11660Sstevel@tonic-gate DPRINT2(5, "formatsys(%u): len (copynl_frwd) = %d\n",
11676358Snakanon mythreadno, len);
11680Sstevel@tonic-gate
11690Sstevel@tonic-gate p += len;
11700Sstevel@tonic-gate msglen -= len;
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate if (*p == '\n') {
11730Sstevel@tonic-gate /* skip newline */
11740Sstevel@tonic-gate p++;
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate if (sync && ((lp->pri & LOG_FACMASK) == LOG_KERN))
11780Sstevel@tonic-gate mp->flags |= SYNC_FILE; /* fsync file after write */
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate if (len != 0) {
11810Sstevel@tonic-gate (void) strlcpy(mp->msg, line, MAXLINE+1);
11820Sstevel@tonic-gate mp->pri = lp->pri;
11830Sstevel@tonic-gate
11840Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) {
11850Sstevel@tonic-gate free_msg(mp);
11860Sstevel@tonic-gate MALLOC_FAIL("dropping message");
11870Sstevel@tonic-gate break;
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate
11900Sstevel@tonic-gate DPRINT3(5, "formatsys(%u): sys_thread enqueued msg "
11916358Snakanon "%p on queue %p\n", mythreadno, (void *)mp,
11926358Snakanon (void *)&inputq);
11930Sstevel@tonic-gate } else
11940Sstevel@tonic-gate free_msg(mp);
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate
11980Sstevel@tonic-gate /*
11990Sstevel@tonic-gate * Log a message to the appropriate log files, users, etc. based on
12000Sstevel@tonic-gate * the priority.
12010Sstevel@tonic-gate */
12020Sstevel@tonic-gate /*ARGSUSED*/
12030Sstevel@tonic-gate static void *
logmsg(void * ap)12040Sstevel@tonic-gate logmsg(void *ap)
12050Sstevel@tonic-gate {
12060Sstevel@tonic-gate struct filed *f;
12070Sstevel@tonic-gate int fac, prilev, flags, refcnt;
12080Sstevel@tonic-gate int fake_shutdown, skip_shutdown;
12090Sstevel@tonic-gate log_message_t *mp, *save_mp;
12100Sstevel@tonic-gate pthread_t mythreadno;
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate if (Debug) {
12130Sstevel@tonic-gate mythreadno = pthread_self();
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate DPRINT1(1, "logmsg(%u): msg dispatcher started\n", mythreadno);
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate fake_shutdown = skip_shutdown = 0;
12190Sstevel@tonic-gate save_mp = NULL;
12200Sstevel@tonic-gate for (;;) {
12210Sstevel@tonic-gate if (save_mp) {
12220Sstevel@tonic-gate /*
12230Sstevel@tonic-gate * If we have set aside a message in order to fake a
12240Sstevel@tonic-gate * SHUTDOWN, use that message before picking from the
12250Sstevel@tonic-gate * queue again.
12260Sstevel@tonic-gate */
12270Sstevel@tonic-gate mp = save_mp;
12280Sstevel@tonic-gate save_mp = NULL;
12290Sstevel@tonic-gate } else {
12300Sstevel@tonic-gate (void) dataq_dequeue(&inputq, (void **)&mp, 0);
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
12330Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): msg dispatcher dequeued %p from "
12346358Snakanon "queue %p\n", mythreadno, (void *)mp,
12356358Snakanon (void *)&inputq);
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate /*
12380Sstevel@tonic-gate * In most cases, if the message traffic is low, logmsg() wakes
12390Sstevel@tonic-gate * up when it receives the SHUTDOWN msg, and will sleep until
12400Sstevel@tonic-gate * HUP process is complete. However, if the inputq is too
12410Sstevel@tonic-gate * long, logmsg() may not receive SHUTDOWN before reconfigure()
12420Sstevel@tonic-gate * releases the logger fds, filed and logit threads. That, in
12430Sstevel@tonic-gate * turn, will cause logmsg to refer to invalid fileds.
12440Sstevel@tonic-gate *
12450Sstevel@tonic-gate * logmsg() needs to respond to the SHUTDOWN message within
12460Sstevel@tonic-gate * LOOP_INTERVAL seconds when reconfigure() enqueues it. It
12470Sstevel@tonic-gate * does so in most cases. When it does not respond in time,
12480Sstevel@tonic-gate * logmsg() needs to be in suspended state immediately, since
12490Sstevel@tonic-gate * filed may have been invalidated. reconfigure() will set the
12500Sstevel@tonic-gate * HUP_SUSP_LOGMSG_REQD bit in hup_state and wait another
12510Sstevel@tonic-gate * LOOP_INTERVAL seconds before proceeding.
12520Sstevel@tonic-gate *
12530Sstevel@tonic-gate * When HUP_SUSP_LOGMSG_REQD is set, we will create a fake
12540Sstevel@tonic-gate * SHUTDOWN message, and dispatch it to the various logit
12550Sstevel@tonic-gate * threads, and logmsg() itself will suspend. In order to
12560Sstevel@tonic-gate * ignore the real SHUTDOWN which will arrive later, we keep a
12570Sstevel@tonic-gate * counter (skip_shutdown) and decrement it when the SHUTDOWN
12580Sstevel@tonic-gate * message arrives.
12590Sstevel@tonic-gate */
12600Sstevel@tonic-gate if ((hup_state & HUP_SUSP_LOGMSG_REQD) &&
12616358Snakanon (mp->flags & SHUTDOWN) == 0) {
12620Sstevel@tonic-gate DPRINT1(3, "logmsg(%u): suspend request\n",
12636358Snakanon mythreadno);
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate save_mp = mp;
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate /* create a fake SHUTDOWN msg */
12680Sstevel@tonic-gate if ((mp = new_msg()) == NULL) {
12690Sstevel@tonic-gate MALLOC_FAIL("dropping message");
12700Sstevel@tonic-gate if (mp->flags & SHUTDOWN) {
12710Sstevel@tonic-gate (void) logerror_to_console(1,
12726358Snakanon "unable to shutdown "
12736358Snakanon "logger thread");
12740Sstevel@tonic-gate }
12750Sstevel@tonic-gate continue;
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate mp->flags = SHUTDOWN;
12780Sstevel@tonic-gate mp->hlp = &LocalHostName;
12790Sstevel@tonic-gate fake_shutdown = 1;
12800Sstevel@tonic-gate skip_shutdown++;
12810Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): pending SHUTDOWN %d\n",
12826358Snakanon mythreadno, skip_shutdown);
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate /*
12860Sstevel@tonic-gate * is it a shutdown or flush message ?
12870Sstevel@tonic-gate */
12880Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) || (mp->flags & FLUSHMSG)) {
12892104Sjjj (void) pthread_mutex_lock(&mp->msg_mutex);
12900Sstevel@tonic-gate
12910Sstevel@tonic-gate if ((mp->flags & SHUTDOWN) &&
12926358Snakanon !fake_shutdown && skip_shutdown > 0) {
12930Sstevel@tonic-gate skip_shutdown--;
12942104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
12950Sstevel@tonic-gate free_msg(mp);
12960Sstevel@tonic-gate DPRINT2(3, "logmsg(%u): released late "
12976358Snakanon "arrived SHUTDOWN. pending %d\n",
12986358Snakanon mythreadno, skip_shutdown);
12990Sstevel@tonic-gate continue;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
13032104Sjjj (void) pthread_mutex_lock(&f->filed_mutex);
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate if (f->f_type == F_UNUSED) {
13062104Sjjj (void) pthread_mutex_unlock(
13072104Sjjj &f->filed_mutex);
13080Sstevel@tonic-gate continue;
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate f->f_queue_count++;
13120Sstevel@tonic-gate mp->refcnt++;
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue,
13156358Snakanon (void *)mp) == -1) {
13160Sstevel@tonic-gate f->f_queue_count--;
13170Sstevel@tonic-gate mp->refcnt--;
13182104Sjjj (void) pthread_mutex_unlock(
13192104Sjjj &f->filed_mutex);
13200Sstevel@tonic-gate MALLOC_FAIL("dropping message");
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate if (mp->flags & SHUTDOWN) {
13230Sstevel@tonic-gate (void) logerror_to_console(1,
13246358Snakanon "unable to shutdown "
13256358Snakanon "logger thread");
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate
13280Sstevel@tonic-gate continue;
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p "
13316358Snakanon "on queue %p\n", mythreadno,
13326358Snakanon (void *)mp, (void *)&f->f_queue);
13332104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
13340Sstevel@tonic-gate }
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate /*
13370Sstevel@tonic-gate * flags value needs to be saved because mp may
13380Sstevel@tonic-gate * have been freed before SHUTDOWN test below.
13390Sstevel@tonic-gate */
13400Sstevel@tonic-gate flags = mp->flags;
13410Sstevel@tonic-gate refcnt = mp->refcnt;
13420Sstevel@tonic-gate
13432104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
13440Sstevel@tonic-gate if (refcnt == 0)
13450Sstevel@tonic-gate free_msg(mp);
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate if (flags & SHUTDOWN) {
13482104Sjjj (void) pthread_mutex_lock(&hup_lock);
13490Sstevel@tonic-gate while (hup_state != HUP_COMPLETED) {
13500Sstevel@tonic-gate hup_state |= HUP_LOGMSG_SUSPENDED;
13510Sstevel@tonic-gate (void) pthread_cond_wait(&hup_done,
13526358Snakanon &hup_lock);
13530Sstevel@tonic-gate hup_state &= ~HUP_LOGMSG_SUSPENDED;
13540Sstevel@tonic-gate }
13550Sstevel@tonic-gate hup_state = HUP_ACCEPTABLE;
13562104Sjjj (void) pthread_mutex_unlock(&hup_lock);
13570Sstevel@tonic-gate fake_shutdown = 0;
13580Sstevel@tonic-gate }
13590Sstevel@tonic-gate continue;
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate
13620Sstevel@tonic-gate /*
13630Sstevel@tonic-gate * Check to see if msg looks non-standard.
13640Sstevel@tonic-gate */
13650Sstevel@tonic-gate if ((int)strlen(mp->msg) < 16 || mp->msg[3] != ' ' ||
13666358Snakanon mp->msg[6] != ' ' || mp->msg[9] != ':' ||
13676358Snakanon mp->msg[12] != ':' || mp->msg[15] != ' ')
13680Sstevel@tonic-gate mp->flags |= ADDDATE;
13690Sstevel@tonic-gate
13700Sstevel@tonic-gate /* extract facility and priority level */
13710Sstevel@tonic-gate fac = (mp->pri & LOG_FACMASK) >> 3;
13720Sstevel@tonic-gate if (mp->flags & MARK)
13730Sstevel@tonic-gate fac = LOG_NFACILITIES;
13740Sstevel@tonic-gate prilev = mp->pri & LOG_PRIMASK;
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate DPRINT3(3, "logmsg(%u): fac = %d, pri = %d\n",
13776358Snakanon mythreadno, fac, prilev);
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate /*
13800Sstevel@tonic-gate * Because different devices log at different speeds,
13810Sstevel@tonic-gate * it's important to hold the mutex for the current
13820Sstevel@tonic-gate * message until it's been enqueued to all log files,
13830Sstevel@tonic-gate * so the reference count is accurate before any
13840Sstevel@tonic-gate * of the log threads can decrement it.
13850Sstevel@tonic-gate */
13860Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mp))
13870Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW)
13882104Sjjj (void) pthread_mutex_lock(&mp->msg_mutex);
13890Sstevel@tonic-gate
13900Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
13910Sstevel@tonic-gate /* skip messages that are incorrect priority */
13920Sstevel@tonic-gate if (f->f_pmask[fac] < (unsigned)prilev ||
13936358Snakanon f->f_pmask[fac] == NOPRI)
13940Sstevel@tonic-gate continue;
13950Sstevel@tonic-gate if (f->f_queue_count > Q_HIGHWATER_MARK) {
13960Sstevel@tonic-gate DPRINT4(5, "logmsg(%u): Dropping message "
13976358Snakanon "%p on file %p, count = %d\n",
13986358Snakanon mythreadno, (void *)mp, (void *)f,
13996358Snakanon f->f_queue_count);
14000Sstevel@tonic-gate continue;
14010Sstevel@tonic-gate }
14020Sstevel@tonic-gate
14030Sstevel@tonic-gate /*
14040Sstevel@tonic-gate * Need to grab filed_mutex before testing the f_type.
14050Sstevel@tonic-gate * Otherwise logit() may set F_UNUSED after the test
14060Sstevel@tonic-gate * below, and start pulling out the pending messages.
14070Sstevel@tonic-gate */
14080Sstevel@tonic-gate
14092104Sjjj (void) pthread_mutex_lock(&f->filed_mutex);
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate if (f->f_type == F_UNUSED ||
14120Sstevel@tonic-gate (f->f_type == F_FILE && (mp->flags & IGN_FILE)) ||
14130Sstevel@tonic-gate (f->f_type == F_CONSOLE &&
14146358Snakanon (mp->flags & IGN_CONS))) {
14152104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
14160Sstevel@tonic-gate continue;
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate
14190Sstevel@tonic-gate f->f_queue_count++;
14200Sstevel@tonic-gate mp->refcnt++;
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate if (dataq_enqueue(&f->f_queue, (void *)mp) == -1) {
14230Sstevel@tonic-gate f->f_queue_count--;
14240Sstevel@tonic-gate mp->refcnt--;
14252104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
14260Sstevel@tonic-gate MALLOC_FAIL("dropping message");
14270Sstevel@tonic-gate continue;
14280Sstevel@tonic-gate }
14290Sstevel@tonic-gate
14300Sstevel@tonic-gate DPRINT3(5, "logmsg(%u): enqueued msg %p on queue "
14316358Snakanon "%p\n", mythreadno, (void *)mp,
14326358Snakanon (void *)&f->f_queue);
14332104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate refcnt = mp->refcnt;
14362104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
14370Sstevel@tonic-gate if (refcnt == 0)
14380Sstevel@tonic-gate free_msg(mp);
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate /*NOTREACHED*/
14410Sstevel@tonic-gate return (NULL);
14420Sstevel@tonic-gate }
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate /*
14450Sstevel@tonic-gate * function to actually write the log message to the selected file.
14460Sstevel@tonic-gate * each file has a logger thread that runs this routine. The function
14470Sstevel@tonic-gate * is called with a pointer to its file structure.
14480Sstevel@tonic-gate */
14490Sstevel@tonic-gate static void *
logit(void * ap)14500Sstevel@tonic-gate logit(void *ap)
14510Sstevel@tonic-gate {
14520Sstevel@tonic-gate struct filed *f = ap;
14530Sstevel@tonic-gate log_message_t *mp;
14540Sstevel@tonic-gate int forwardingloop = 0;
14552104Sjjj const char *errmsg = "logit(%u): %s to %s forwarding loop detected\n";
14560Sstevel@tonic-gate int i, currofst, prevofst, refcnt;
14570Sstevel@tonic-gate host_list_t *hlp;
14580Sstevel@tonic-gate
14590Sstevel@tonic-gate assert(f != NULL);
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate DPRINT4(5, "logit(%u): logger started for \"%s\" (queue %p, filed "
14626358Snakanon "%p)\n", f->f_thread, f->f_un.f_fname, (void *)&f->f_queue,
14636358Snakanon (void *)f);
14640Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW);
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate while (f->f_type != F_UNUSED) {
14670Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
14680Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
14696358Snakanon "%p\n", f->f_thread, (void *)mp, (void *)&f->f_queue);
14702104Sjjj (void) pthread_mutex_lock(&f->filed_mutex);
14710Sstevel@tonic-gate assert(f->f_queue_count > 0);
14720Sstevel@tonic-gate f->f_queue_count--;
14732104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
14740Sstevel@tonic-gate assert(mp->refcnt > 0);
14750Sstevel@tonic-gate
14760Sstevel@tonic-gate /*
14770Sstevel@tonic-gate * is it a shutdown message ?
14780Sstevel@tonic-gate */
14790Sstevel@tonic-gate if (mp->flags & SHUTDOWN) {
14802104Sjjj (void) pthread_mutex_lock(&mp->msg_mutex);
14810Sstevel@tonic-gate refcnt = --mp->refcnt;
14822104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
14830Sstevel@tonic-gate if (refcnt == 0)
14840Sstevel@tonic-gate free_msg(mp);
14850Sstevel@tonic-gate break;
14860Sstevel@tonic-gate }
14870Sstevel@tonic-gate
14880Sstevel@tonic-gate /*
14890Sstevel@tonic-gate * Is it a logsync message?
14900Sstevel@tonic-gate */
14910Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | LOGSYNC)) ==
14920Sstevel@tonic-gate (FLUSHMSG | LOGSYNC)) {
14930Sstevel@tonic-gate if (f->f_type != F_FILE)
14940Sstevel@tonic-gate goto out; /* nothing to do */
14950Sstevel@tonic-gate (void) close(f->f_file);
14960Sstevel@tonic-gate f->f_file = open64(f->f_un.f_fname,
14976358Snakanon O_WRONLY|O_APPEND|O_NOCTTY);
14980Sstevel@tonic-gate if (f->f_file < 0) {
14990Sstevel@tonic-gate f->f_type = F_UNUSED;
15000Sstevel@tonic-gate logerror(f->f_un.f_fname);
15010Sstevel@tonic-gate f->f_stat.errs++;
15020Sstevel@tonic-gate }
15030Sstevel@tonic-gate goto out;
15040Sstevel@tonic-gate }
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate /*
15070Sstevel@tonic-gate * If the message flags include both flush and sync,
15080Sstevel@tonic-gate * then just sync the file out to disk if appropriate.
15090Sstevel@tonic-gate */
15100Sstevel@tonic-gate if ((mp->flags & (FLUSHMSG | SYNC_FILE)) ==
15110Sstevel@tonic-gate (FLUSHMSG | SYNC_FILE)) {
15120Sstevel@tonic-gate if (f->f_type == F_FILE) {
15130Sstevel@tonic-gate DPRINT2(5, "logit(%u): got FLUSH|SYNC "
15146358Snakanon "for filed %p\n", f->f_thread,
15156358Snakanon (void *)f);
15160Sstevel@tonic-gate (void) fsync(f->f_file);
15170Sstevel@tonic-gate }
15180Sstevel@tonic-gate goto out;
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate /*
15220Sstevel@tonic-gate * Otherwise if it's a standard flush message, write
15230Sstevel@tonic-gate * out any saved messages to the file.
15240Sstevel@tonic-gate */
15250Sstevel@tonic-gate if ((mp->flags & FLUSHMSG) && (f->f_prevcount > 0)) {
15260Sstevel@tonic-gate set_flush_msg(f);
15270Sstevel@tonic-gate writemsg(SAVED, f);
15280Sstevel@tonic-gate goto out;
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate (void) strlcpy(f->f_current.msg, mp->msg, MAXLINE+1);
15320Sstevel@tonic-gate (void) strlcpy(f->f_current.host, mp->hlp->hl_hosts[0],
15336358Snakanon SYS_NMLN);
15340Sstevel@tonic-gate f->f_current.pri = mp->pri;
15350Sstevel@tonic-gate f->f_current.flags = mp->flags;
15360Sstevel@tonic-gate f->f_current.time = mp->ts;
15370Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID;
15380Sstevel@tonic-gate hlp = mp->hlp;
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
15410Sstevel@tonic-gate currofst = (f->f_current.flags & ADDDATE) ? 0 : 16;
15420Sstevel@tonic-gate
15430Sstevel@tonic-gate if (f->f_type == F_FORW) {
15440Sstevel@tonic-gate /*
15450Sstevel@tonic-gate * Should not forward MARK messages, as they are
15460Sstevel@tonic-gate * not defined outside of the current system.
15470Sstevel@tonic-gate */
15480Sstevel@tonic-gate
15490Sstevel@tonic-gate if (mp->flags & MARK) {
15500Sstevel@tonic-gate DPRINT1(1, "logit(%u): cannot forward "
15516358Snakanon "Mark\n", f->f_thread);
15520Sstevel@tonic-gate goto out;
15530Sstevel@tonic-gate }
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate /*
15560Sstevel@tonic-gate * can not forward message if we do
15570Sstevel@tonic-gate * not have a host to forward to
15580Sstevel@tonic-gate */
15590Sstevel@tonic-gate if (hlp == (host_list_t *)NULL)
15600Sstevel@tonic-gate goto out;
15610Sstevel@tonic-gate /*
15620Sstevel@tonic-gate * a forwarding loop is created on machines
15630Sstevel@tonic-gate * with multiple interfaces because the
15640Sstevel@tonic-gate * network address of the sender is different
15650Sstevel@tonic-gate * to the receiver even though it is the
15660Sstevel@tonic-gate * same machine. Instead, if the
15670Sstevel@tonic-gate * hostname the source and target are
15680Sstevel@tonic-gate * the same the message if thrown away
15690Sstevel@tonic-gate */
15700Sstevel@tonic-gate forwardingloop = 0;
15710Sstevel@tonic-gate for (i = 0; i < hlp->hl_cnt; i++) {
15720Sstevel@tonic-gate if (strcmp(hlp->hl_hosts[i],
15736358Snakanon f->f_un.f_forw.f_hname) == 0) {
15740Sstevel@tonic-gate DPRINT3(1, errmsg, f->f_thread,
15756358Snakanon f->f_un.f_forw.f_hname,
15766358Snakanon hlp->hl_hosts[i]);
15770Sstevel@tonic-gate forwardingloop = 1;
15780Sstevel@tonic-gate break;
15790Sstevel@tonic-gate }
15800Sstevel@tonic-gate }
15810Sstevel@tonic-gate
15820Sstevel@tonic-gate if (forwardingloop == 1) {
15830Sstevel@tonic-gate f->f_stat.cantfwd++;
15840Sstevel@tonic-gate goto out;
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate }
15870Sstevel@tonic-gate
15880Sstevel@tonic-gate f->f_msgflag |= CURRENT_VALID;
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate /* check for dup message */
15910Sstevel@tonic-gate if (f->f_type != F_FORW &&
15926358Snakanon (f->f_msgflag & OLD_VALID) &&
15936358Snakanon prevofst == currofst &&
15946358Snakanon (strcmp(f->f_prevmsg.msg + prevofst,
15956358Snakanon f->f_current.msg + currofst) == 0) &&
15966358Snakanon (strcmp(f->f_prevmsg.host,
15976358Snakanon f->f_current.host) == 0)) {
15980Sstevel@tonic-gate /* a dup */
15990Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is dup - %p\n",
16006358Snakanon f->f_thread, (void *)mp);
16010Sstevel@tonic-gate if (currofst == 16) {
16020Sstevel@tonic-gate (void) strncpy(f->f_prevmsg.msg,
16036358Snakanon f->f_current.msg, 15); /* update time */
16040Sstevel@tonic-gate }
16050Sstevel@tonic-gate f->f_prevcount++;
16060Sstevel@tonic-gate f->f_stat.dups++;
16070Sstevel@tonic-gate f->f_stat.total++;
16080Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID;
16090Sstevel@tonic-gate } else {
16100Sstevel@tonic-gate /* new: mark or prior dups exist */
16110Sstevel@tonic-gate if (f->f_current.flags & MARK || f->f_prevcount > 0) {
16120Sstevel@tonic-gate if (f->f_prevcount > 0 && f->f_type != F_FORW) {
16130Sstevel@tonic-gate set_flush_msg(f);
16140Sstevel@tonic-gate if (f->f_msgflag & OLD_VALID) {
16150Sstevel@tonic-gate writemsg(SAVED, f);
16160Sstevel@tonic-gate }
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate if (f->f_msgflag & CURRENT_VALID)
16190Sstevel@tonic-gate writemsg(CURRENT, f);
16200Sstevel@tonic-gate if (!(mp->flags & NOCOPY))
16210Sstevel@tonic-gate copy_msg(f);
16220Sstevel@tonic-gate if (f->f_current.flags & MARK) {
16230Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is "
16246358Snakanon "mark - %p)\n", f->f_thread,
16256358Snakanon (void *)mp);
16260Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID;
16270Sstevel@tonic-gate } else {
16280Sstevel@tonic-gate DPRINT2(2, "logit(%u): saving "
16296358Snakanon "message - %p\n", f->f_thread,
16306358Snakanon (void *)mp);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate f->f_stat.total++;
16330Sstevel@tonic-gate } else { /* new message */
16340Sstevel@tonic-gate DPRINT2(2, "logit(%u): msg is new "
16356358Snakanon "- %p\n", f->f_thread, (void *)mp);
16360Sstevel@tonic-gate writemsg(CURRENT, f);
16370Sstevel@tonic-gate if (!(mp->flags & NOCOPY))
16380Sstevel@tonic-gate copy_msg(f);
16390Sstevel@tonic-gate f->f_stat.total++;
16400Sstevel@tonic-gate }
16410Sstevel@tonic-gate }
16420Sstevel@tonic-gate /*
16430Sstevel@tonic-gate * if message refcnt goes to zero after we decrement
16440Sstevel@tonic-gate * it here, we are the last consumer of the message,
16450Sstevel@tonic-gate * and we should free it. We need to hold the lock
16460Sstevel@tonic-gate * between decrementing the count and checking for
16470Sstevel@tonic-gate * zero so another thread doesn't beat us to it.
16480Sstevel@tonic-gate */
16490Sstevel@tonic-gate out:
16502104Sjjj (void) pthread_mutex_lock(&mp->msg_mutex);
16510Sstevel@tonic-gate refcnt = --mp->refcnt;
16522104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
16530Sstevel@tonic-gate if (refcnt == 0)
16540Sstevel@tonic-gate free_msg(mp);
16550Sstevel@tonic-gate }
16560Sstevel@tonic-gate /* register our exit */
16570Sstevel@tonic-gate
16580Sstevel@tonic-gate /*
16590Sstevel@tonic-gate * Pull out all pending messages, if they exist.
16600Sstevel@tonic-gate */
16610Sstevel@tonic-gate
16622104Sjjj (void) pthread_mutex_lock(&f->filed_mutex);
16630Sstevel@tonic-gate
16640Sstevel@tonic-gate while (f->f_queue_count > 0) {
16650Sstevel@tonic-gate (void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
16660Sstevel@tonic-gate DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
16676358Snakanon "%p\n",
16686358Snakanon f->f_thread, (void *)mp, (void *)&f->f_queue);
16692104Sjjj (void) pthread_mutex_lock(&mp->msg_mutex);
16700Sstevel@tonic-gate refcnt = --mp->refcnt;
16712104Sjjj (void) pthread_mutex_unlock(&mp->msg_mutex);
16720Sstevel@tonic-gate if (refcnt == 0)
16730Sstevel@tonic-gate free_msg(mp);
16740Sstevel@tonic-gate f->f_queue_count--;
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate
16772104Sjjj (void) pthread_mutex_unlock(&f->filed_mutex);
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate if (f->f_type != F_USERS && f->f_type != F_WALL &&
16806358Snakanon f->f_type != F_UNUSED) {
16810Sstevel@tonic-gate if (f->f_type == F_FORW)
16820Sstevel@tonic-gate (void) t_close(f->f_file);
16830Sstevel@tonic-gate else
16840Sstevel@tonic-gate (void) close(f->f_file);
16850Sstevel@tonic-gate }
16860Sstevel@tonic-gate
16870Sstevel@tonic-gate /*
16880Sstevel@tonic-gate * Since f_type may have been changed before this point, we need
16890Sstevel@tonic-gate * to test orig_type.
16900Sstevel@tonic-gate */
16910Sstevel@tonic-gate if (f->f_orig_type == F_FORW) {
16920Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf);
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate f->f_type = F_UNUSED;
16962104Sjjj (void) pthread_mutex_lock(&cft);
16970Sstevel@tonic-gate --conf_threads;
16982104Sjjj (void) pthread_mutex_unlock(&cft);
16990Sstevel@tonic-gate DPRINT1(5, "logit(%u): logging thread exited\n", f->f_thread);
17000Sstevel@tonic-gate return (NULL);
17010Sstevel@tonic-gate }
17020Sstevel@tonic-gate
17030Sstevel@tonic-gate /*
17040Sstevel@tonic-gate * change the previous message to a flush message, stating how
17050Sstevel@tonic-gate * many repeats occurred since the last flush
17060Sstevel@tonic-gate */
17070Sstevel@tonic-gate static void
set_flush_msg(struct filed * f)17080Sstevel@tonic-gate set_flush_msg(struct filed *f)
17090Sstevel@tonic-gate {
17100Sstevel@tonic-gate char tbuf[10];
17110Sstevel@tonic-gate int prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
17120Sstevel@tonic-gate
17130Sstevel@tonic-gate if (f->f_prevcount == 1)
17140Sstevel@tonic-gate (void) strncpy(tbuf, "time", sizeof (tbuf));
17150Sstevel@tonic-gate else
17160Sstevel@tonic-gate (void) strncpy(tbuf, "times", sizeof (tbuf));
17170Sstevel@tonic-gate
17182104Sjjj (void) snprintf(f->f_prevmsg.msg+prevofst,
17192104Sjjj sizeof (f->f_prevmsg.msg) - prevofst,
17202104Sjjj "last message repeated %d %s", f->f_prevcount, tbuf);
17210Sstevel@tonic-gate f->f_prevcount = 0;
17220Sstevel@tonic-gate f->f_msgflag |= OLD_VALID;
17230Sstevel@tonic-gate }
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate /*
17270Sstevel@tonic-gate * the actual writing of the message is broken into a separate function
17280Sstevel@tonic-gate * because each file has a current and saved message associated with
17290Sstevel@tonic-gate * it (for duplicate message detection). It is necessary to be able
17300Sstevel@tonic-gate * to write either the saved message or the current message.
17310Sstevel@tonic-gate */
17320Sstevel@tonic-gate static void
writemsg(int selection,struct filed * f)17330Sstevel@tonic-gate writemsg(int selection, struct filed *f)
17340Sstevel@tonic-gate {
17350Sstevel@tonic-gate char *cp, *p;
17360Sstevel@tonic-gate int pri;
17370Sstevel@tonic-gate int flags;
17380Sstevel@tonic-gate int l;
17390Sstevel@tonic-gate time_t ts;
17400Sstevel@tonic-gate struct t_unitdata ud;
17410Sstevel@tonic-gate char *eomp, *eomp2, *from, *text, *msg;
17420Sstevel@tonic-gate char line[MAXLINE*2];
17430Sstevel@tonic-gate char head[MAXLINE+1];
17440Sstevel@tonic-gate char tmpbuf[MAXLINE+1];
17450Sstevel@tonic-gate char cbuf[30];
17460Sstevel@tonic-gate char *filtered;
17470Sstevel@tonic-gate char *msgid_start, *msgid_end;
17480Sstevel@tonic-gate pthread_t mythreadno;
17490Sstevel@tonic-gate size_t hlen, filter_len;
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate if (Debug) {
17520Sstevel@tonic-gate mythreadno = pthread_self();
17530Sstevel@tonic-gate }
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate switch (selection) {
17560Sstevel@tonic-gate default:
17570Sstevel@tonic-gate case CURRENT: /* print current message */
17580Sstevel@tonic-gate msg = f->f_current.msg;
17590Sstevel@tonic-gate from = f->f_current.host;
17600Sstevel@tonic-gate pri = f->f_current.pri;
17610Sstevel@tonic-gate flags = f->f_current.flags;
17620Sstevel@tonic-gate ts = f->f_current.time;
17630Sstevel@tonic-gate f->f_msgflag &= ~CURRENT_VALID;
17640Sstevel@tonic-gate break;
17650Sstevel@tonic-gate case SAVED: /* print saved message */
17660Sstevel@tonic-gate msg = f->f_prevmsg.msg;
17670Sstevel@tonic-gate from = f->f_prevmsg.host;
17680Sstevel@tonic-gate pri = f->f_prevmsg.pri;
17690Sstevel@tonic-gate flags = f->f_prevmsg.flags;
17700Sstevel@tonic-gate ts = f->f_prevmsg.time;
17710Sstevel@tonic-gate f->f_msgflag &= ~OLD_VALID;
17720Sstevel@tonic-gate break;
17730Sstevel@tonic-gate }
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate if (msg[0] == '\0')
17760Sstevel@tonic-gate return;
17770Sstevel@tonic-gate
17780Sstevel@tonic-gate cp = line;
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate if (flags & ADDDATE)
17810Sstevel@tonic-gate (void) strncpy(cp, ctime_r(&ts, cbuf) + 4, 15);
17820Sstevel@tonic-gate else
17830Sstevel@tonic-gate (void) strncpy(cp, msg, 15);
17840Sstevel@tonic-gate
17850Sstevel@tonic-gate line[15] = '\0';
17860Sstevel@tonic-gate (void) strcat(cp, " ");
17870Sstevel@tonic-gate (void) strcat(cp, from);
17880Sstevel@tonic-gate (void) strcat(cp, " ");
17890Sstevel@tonic-gate text = cp + strlen(cp);
17900Sstevel@tonic-gate
17910Sstevel@tonic-gate if (flags & ADDDATE)
17920Sstevel@tonic-gate (void) strcat(cp, msg);
17930Sstevel@tonic-gate else
17940Sstevel@tonic-gate (void) strcat(cp, msg+16);
17950Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
17960Sstevel@tonic-gate
17970Sstevel@tonic-gate errno = 0;
17980Sstevel@tonic-gate t_errno = 0;
17990Sstevel@tonic-gate switch (f->f_type) {
18000Sstevel@tonic-gate case F_UNUSED:
18010Sstevel@tonic-gate DPRINT1(1, "writemsg(%u): UNUSED\n", mythreadno);
18020Sstevel@tonic-gate break;
18030Sstevel@tonic-gate case F_FORW:
18040Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
18056358Snakanon mythreadno, msg, TypeNames[f->f_type],
18066358Snakanon f->f_un.f_forw.f_hname);
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate hlen = snprintf(head, sizeof (head),
18096358Snakanon "<%d>%.15s ", pri, cp);
18100Sstevel@tonic-gate
18110Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): head = \"%s\"\n", mythreadno, head);
18120Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): hlen = %d\n", mythreadno, hlen);
18130Sstevel@tonic-gate
18140Sstevel@tonic-gate l = strlen(text);
18150Sstevel@tonic-gate p = text;
18160Sstevel@tonic-gate
18170Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
18180Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(text) = %d\n", mythreadno, l);
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate (void) strncpy(tmpbuf, head, hlen);
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate while (l > 0) {
18230Sstevel@tonic-gate size_t len;
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate len = copy_frwd(tmpbuf + hlen, sizeof (tmpbuf) - hlen,
18266358Snakanon p, l);
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): tmpbuf = \"%s\"\n",
18296358Snakanon mythreadno, tmpbuf);
18300Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): len = %d\n", mythreadno,
18316358Snakanon len);
18320Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(tmpbuf) = %d\n",
18336358Snakanon mythreadno, strlen(tmpbuf));
18340Sstevel@tonic-gate
18350Sstevel@tonic-gate ud.opt.buf = NULL;
18360Sstevel@tonic-gate ud.opt.len = 0;
18370Sstevel@tonic-gate ud.udata.buf = tmpbuf;
18380Sstevel@tonic-gate ud.udata.len = len + hlen;
18390Sstevel@tonic-gate ud.addr.maxlen = f->f_un.f_forw.f_addr.maxlen;
18400Sstevel@tonic-gate ud.addr.buf = f->f_un.f_forw.f_addr.buf;
18410Sstevel@tonic-gate ud.addr.len = f->f_un.f_forw.f_addr.len;
18420Sstevel@tonic-gate if (t_sndudata(f->f_file, &ud) < 0) {
18430Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) &&
18446358Snakanon f->f_type == F_UNUSED) {
18450Sstevel@tonic-gate break;
18460Sstevel@tonic-gate }
18470Sstevel@tonic-gate (void) t_close(f->f_file);
18480Sstevel@tonic-gate f->f_type = F_UNUSED;
18490Sstevel@tonic-gate logerror("t_sndudata");
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate /*
18520Sstevel@tonic-gate * Since it has already failed, it's not worth
18530Sstevel@tonic-gate * continuing output from the middle of
18540Sstevel@tonic-gate * message string.
18550Sstevel@tonic-gate */
18560Sstevel@tonic-gate break;
18570Sstevel@tonic-gate }
18580Sstevel@tonic-gate p += len;
18590Sstevel@tonic-gate l -= len;
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate break;
18620Sstevel@tonic-gate case F_CONSOLE:
18630Sstevel@tonic-gate case F_TTY:
18640Sstevel@tonic-gate case F_FILE:
18650Sstevel@tonic-gate case F_USERS:
18660Sstevel@tonic-gate case F_WALL:
18670Sstevel@tonic-gate DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
18686358Snakanon mythreadno, msg, TypeNames[f->f_type],
18696358Snakanon ((f->f_type == F_USERS) || (f->f_type == F_WALL)) ?
18706358Snakanon "" : f->f_un.f_fname);
18710Sstevel@tonic-gate /*
18720Sstevel@tonic-gate * filter the string in preparation for writing it
18730Sstevel@tonic-gate * save the original for possible forwarding.
18740Sstevel@tonic-gate * In case every byte in cp is a control character,
18750Sstevel@tonic-gate * allocates large enough buffer for filtered.
18760Sstevel@tonic-gate */
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate filter_len = strlen(cp) * 4 + 1;
18790Sstevel@tonic-gate filtered = (char *)malloc(filter_len);
18800Sstevel@tonic-gate if (!filtered) {
18810Sstevel@tonic-gate MALLOC_FAIL("dropping message");
18820Sstevel@tonic-gate /* seems we can just return */
18830Sstevel@tonic-gate return;
18840Sstevel@tonic-gate }
18850Sstevel@tonic-gate DPRINT3(5, "writemsg(%u): "
18866358Snakanon "filtered allocated (%p: %d bytes)\n",
18876358Snakanon mythreadno, (void *)filtered, filter_len);
18880Sstevel@tonic-gate /* -3 : we may add "\r\n" to ecomp(filtered) later */
18890Sstevel@tonic-gate filter_string(cp, filtered, filter_len - 3);
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): strlen(filtered) = %d\n",
18926358Snakanon mythreadno, strlen(filtered));
18930Sstevel@tonic-gate /*
18940Sstevel@tonic-gate * If we're writing to the console, strip out the message ID
18950Sstevel@tonic-gate * to reduce visual clutter.
18960Sstevel@tonic-gate */
18970Sstevel@tonic-gate if ((msgid_start = strstr(filtered, "[ID ")) != NULL &&
18986358Snakanon (msgid_end = strstr(msgid_start, "] ")) != NULL &&
18996358Snakanon f->f_type == F_CONSOLE)
19000Sstevel@tonic-gate (void) strcpy(msgid_start, msgid_end + 2);
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate eomp = filtered + strlen(filtered);
19030Sstevel@tonic-gate
19040Sstevel@tonic-gate if ((f->f_type == F_USERS) || (f->f_type == F_WALL)) {
19050Sstevel@tonic-gate /* CSTYLED */
19060Sstevel@tonic-gate (void) strcat(eomp, "\r\n"); /*lint !e669*/
19070Sstevel@tonic-gate /*
19080Sstevel@tonic-gate * Since wallmsg messes with utmpx we need
19090Sstevel@tonic-gate * to guarantee single threadedness...
19100Sstevel@tonic-gate */
19110Sstevel@tonic-gate (void) pthread_mutex_lock(&wmp);
19120Sstevel@tonic-gate wallmsg(f, from, filtered);
19130Sstevel@tonic-gate (void) pthread_mutex_unlock(&wmp);
19140Sstevel@tonic-gate
19150Sstevel@tonic-gate /*
19160Sstevel@tonic-gate * The contents of filtered have been copied
19170Sstevel@tonic-gate * out to the struct walldev. We should free it here.
19180Sstevel@tonic-gate */
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate free(filtered);
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate /* exiting the switch */
19230Sstevel@tonic-gate break;
19240Sstevel@tonic-gate } else if (f->f_type != F_FILE) {
19250Sstevel@tonic-gate /* CSTYLED */
19260Sstevel@tonic-gate (void) strncpy(eomp, "\r\n", 3); /*lint !e669*/
19270Sstevel@tonic-gate } else {
19280Sstevel@tonic-gate if ((eomp2 = strchr(filtered, '\r')) != NULL) {
19290Sstevel@tonic-gate (void) strncpy(eomp2, "\n", 2);
19300Sstevel@tonic-gate } else {
19310Sstevel@tonic-gate /* CSTYLED */
19320Sstevel@tonic-gate (void) strncpy(eomp, "\n", 2); /*lint !e669*/
19330Sstevel@tonic-gate }
19340Sstevel@tonic-gate }
19350Sstevel@tonic-gate if (write(f->f_file, filtered, strlen(filtered)) < 0) {
19360Sstevel@tonic-gate int e = errno;
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate if ((hup_state & HUP_INPROGRESS) &&
19396358Snakanon f->f_type == F_UNUSED) {
19400Sstevel@tonic-gate free(filtered);
19410Sstevel@tonic-gate break;
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate (void) close(f->f_file);
19440Sstevel@tonic-gate /*
19450Sstevel@tonic-gate * Check for EBADF on TTY's due
19460Sstevel@tonic-gate * to vhangup() XXX
19470Sstevel@tonic-gate */
19480Sstevel@tonic-gate if (e == EBADF && f->f_type != F_FILE) {
19490Sstevel@tonic-gate f->f_file = open(f->f_un.f_fname,
19506358Snakanon O_WRONLY|O_APPEND|O_NOCTTY);
19510Sstevel@tonic-gate if (f->f_file < 0) {
19520Sstevel@tonic-gate f->f_type = F_UNUSED;
19530Sstevel@tonic-gate logerror(f->f_un.f_fname);
19540Sstevel@tonic-gate f->f_stat.errs++;
19550Sstevel@tonic-gate }
19560Sstevel@tonic-gate untty();
19570Sstevel@tonic-gate } else {
19580Sstevel@tonic-gate f->f_type = F_UNUSED;
19590Sstevel@tonic-gate f->f_stat.errs++;
19600Sstevel@tonic-gate errno = e;
19610Sstevel@tonic-gate logerror(f->f_un.f_fname);
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate } else if (flags & SYNC_FILE)
19640Sstevel@tonic-gate if (((pri & LOG_FACMASK) >> 3) == LOG_KERN)
19650Sstevel@tonic-gate (void) fsync(f->f_file);
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate DPRINT2(5, "writemsg(%u): freeing filtered (%p)\n",
19686358Snakanon mythreadno, (void *)filtered);
19690Sstevel@tonic-gate
19700Sstevel@tonic-gate free(filtered);
19710Sstevel@tonic-gate break;
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate }
19740Sstevel@tonic-gate
19750Sstevel@tonic-gate /*
19760Sstevel@tonic-gate * WALLMSG -- Write a message to the world at large
19770Sstevel@tonic-gate *
19780Sstevel@tonic-gate * Write the specified message to either the entire
19790Sstevel@tonic-gate * world, or a list of approved users.
19800Sstevel@tonic-gate */
19810Sstevel@tonic-gate static void
wallmsg(struct filed * f,char * from,char * msg)19820Sstevel@tonic-gate wallmsg(struct filed *f, char *from, char *msg)
19830Sstevel@tonic-gate {
19840Sstevel@tonic-gate int i;
19850Sstevel@tonic-gate size_t len, clen;
19860Sstevel@tonic-gate char *buf = NULL;
19870Sstevel@tonic-gate struct utmpx *utxp;
19880Sstevel@tonic-gate time_t now;
19890Sstevel@tonic-gate char line[512], dev[100];
19900Sstevel@tonic-gate char cp[MAXLINE+1];
19910Sstevel@tonic-gate struct stat statbuf;
19920Sstevel@tonic-gate walldev_t *w;
19930Sstevel@tonic-gate char cbuf[30];
19940Sstevel@tonic-gate pthread_t mythreadno;
19950Sstevel@tonic-gate
19960Sstevel@tonic-gate if (Debug) {
19970Sstevel@tonic-gate mythreadno = pthread_self();
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate
20000Sstevel@tonic-gate if (access(UTMPX_FILE, R_OK) != 0 || stat(UTMPX_FILE, &statbuf) != 0) {
20010Sstevel@tonic-gate logerror(UTMPX_FILE);
20020Sstevel@tonic-gate return;
20030Sstevel@tonic-gate } else if (statbuf.st_uid != 0 || (statbuf.st_mode & 07777) != 0644) {
20042104Sjjj (void) snprintf(line, sizeof (line), "%s %s", UTMPX_FILE,
20056358Snakanon "not owned by root or not mode 644.\n"
20066358Snakanon "This file must be owned by root "
20076358Snakanon "and not writable by\n"
20086358Snakanon "anyone other than root. This alert is being "
20096358Snakanon "dropped because of\n"
20106358Snakanon "this problem.");
20110Sstevel@tonic-gate logerror(line);
20120Sstevel@tonic-gate return;
20130Sstevel@tonic-gate }
20140Sstevel@tonic-gate
20150Sstevel@tonic-gate if (f->f_type == F_WALL) {
20160Sstevel@tonic-gate (void) time(&now);
20170Sstevel@tonic-gate len = snprintf(line, sizeof (line),
20186358Snakanon "\r\n\7Message from syslogd@%s "
20196358Snakanon "at %.24s ...\r\n", from, ctime_r(&now, cbuf));
20200Sstevel@tonic-gate len += strlen(msg + 16);
20210Sstevel@tonic-gate buf = (char *)malloc(len + 1);
20220Sstevel@tonic-gate if (!buf) {
20230Sstevel@tonic-gate MALLOC_FAIL("dropping message");
20240Sstevel@tonic-gate return;
20250Sstevel@tonic-gate }
20260Sstevel@tonic-gate DPRINT3(5, "wallmsg(%u): buf allocated (%p: %d bytes)\n",
20276358Snakanon mythreadno, (void *)buf, len + 1);
20280Sstevel@tonic-gate (void) strcpy(buf, line);
20290Sstevel@tonic-gate (void) strcat(buf, msg + 16);
20300Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), buf, len);
20310Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n",
20326358Snakanon mythreadno, clen);
20330Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): freeing buf (%p)\n",
20346358Snakanon mythreadno, (void *)buf);
20350Sstevel@tonic-gate free(buf);
20360Sstevel@tonic-gate } else {
20370Sstevel@tonic-gate clen = copy_frwd(cp, sizeof (cp), msg, strlen(msg));
20380Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): clen = %d\n",
20396358Snakanon mythreadno, clen);
20400Sstevel@tonic-gate }
20410Sstevel@tonic-gate /* scan the user login file */
20420Sstevel@tonic-gate setutxent();
20430Sstevel@tonic-gate while ((utxp = getutxent()) != NULL) {
20440Sstevel@tonic-gate /* is this slot used? */
20450Sstevel@tonic-gate if (utxp->ut_name[0] == '\0' ||
20466358Snakanon utxp->ut_line[0] == '\0' ||
20476358Snakanon utxp->ut_type != USER_PROCESS)
20480Sstevel@tonic-gate continue;
20490Sstevel@tonic-gate /* should we send the message to this user? */
20500Sstevel@tonic-gate if (f->f_type == F_USERS) {
20510Sstevel@tonic-gate for (i = 0; i < MAXUNAMES; i++) {
20520Sstevel@tonic-gate if (!f->f_un.f_uname[i][0]) {
20530Sstevel@tonic-gate i = MAXUNAMES;
20540Sstevel@tonic-gate break;
20550Sstevel@tonic-gate }
20560Sstevel@tonic-gate if (strncmp(f->f_un.f_uname[i],
20576358Snakanon utxp->ut_name, UNAMESZ) == 0)
20580Sstevel@tonic-gate break;
20590Sstevel@tonic-gate }
20600Sstevel@tonic-gate if (i >= MAXUNAMES)
20610Sstevel@tonic-gate continue;
20620Sstevel@tonic-gate }
20630Sstevel@tonic-gate
20640Sstevel@tonic-gate /* compute the device name */
20650Sstevel@tonic-gate if (utxp->ut_line[0] == '/') {
20660Sstevel@tonic-gate (void) strncpy(dev, utxp->ut_line, UDEVSZ);
20670Sstevel@tonic-gate } else {
20680Sstevel@tonic-gate (void) strcpy(dev, "/dev/");
20690Sstevel@tonic-gate (void) strncat(dev, utxp->ut_line, UDEVSZ);
20700Sstevel@tonic-gate }
20710Sstevel@tonic-gate DPRINT2(1, "wallmsg(%u): write to '%s'\n", mythreadno,
20726358Snakanon dev);
20730Sstevel@tonic-gate
20740Sstevel@tonic-gate if ((w = malloc(sizeof (walldev_t))) != NULL) {
20750Sstevel@tonic-gate int rc;
20760Sstevel@tonic-gate (void) pthread_attr_init(&w->thread_attr);
20770Sstevel@tonic-gate (void) pthread_attr_setdetachstate(&w->thread_attr,
20786358Snakanon PTHREAD_CREATE_DETACHED);
20790Sstevel@tonic-gate (void) strncpy(w->dev, dev, PATH_MAX);
20800Sstevel@tonic-gate (void) strncpy(w->msg, cp, MAXLINE+1);
20810Sstevel@tonic-gate (void) strncpy(w->ut_name, utxp->ut_name,
20820Sstevel@tonic-gate sizeof (w->ut_name));
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate if ((rc = pthread_create(&w->thread, &w->thread_attr,
20856358Snakanon writetodev, (void *) w)) != 0) {
20860Sstevel@tonic-gate DPRINT2(5, "wallmsg(%u): wallmsg thread "
20876358Snakanon "create failed rc = %d\n",
20886358Snakanon mythreadno, rc);
20890Sstevel@tonic-gate free(w);
20900Sstevel@tonic-gate break;
20910Sstevel@tonic-gate }
20920Sstevel@tonic-gate } else {
20930Sstevel@tonic-gate MALLOC_FAIL("dropping message to user");
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate }
20960Sstevel@tonic-gate /* close the user login file */
20970Sstevel@tonic-gate endutxent();
20980Sstevel@tonic-gate }
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate /*
21010Sstevel@tonic-gate * Each time we need to write to a tty device (a potentially expensive
21020Sstevel@tonic-gate * or long-running operation) this routine gets called as a new
21030Sstevel@tonic-gate * detached, unbound thread. This allows writes to many devices
21040Sstevel@tonic-gate * to proceed nearly in parallel, without having to resort to
21050Sstevel@tonic-gate * asynchronous I/O or forking.
21060Sstevel@tonic-gate */
21070Sstevel@tonic-gate static void *
writetodev(void * ap)21080Sstevel@tonic-gate writetodev(void *ap)
21090Sstevel@tonic-gate {
21100Sstevel@tonic-gate walldev_t *w = ap;
21110Sstevel@tonic-gate int ttyf;
21120Sstevel@tonic-gate int len;
21130Sstevel@tonic-gate struct stat statb;
21140Sstevel@tonic-gate struct passwd pw, *pwp;
21150Sstevel@tonic-gate char pwbuf[MAXLINE];
21160Sstevel@tonic-gate pthread_t mythreadno;
21170Sstevel@tonic-gate
21180Sstevel@tonic-gate if (Debug) {
21190Sstevel@tonic-gate mythreadno = pthread_self();
21200Sstevel@tonic-gate }
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread started\n",
21236358Snakanon mythreadno);
21240Sstevel@tonic-gate
21250Sstevel@tonic-gate len = strlen(w->msg);
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate ttyf = open(w->dev, O_WRONLY|O_NOCTTY|O_NDELAY);
21280Sstevel@tonic-gate if (ttyf >= 0) {
21290Sstevel@tonic-gate if (fstat(ttyf, &statb) != 0) {
21300Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't stat '%s'\n",
21316358Snakanon mythreadno, w->dev);
21320Sstevel@tonic-gate errno = 0;
21330Sstevel@tonic-gate logerror("Can't stat '%s'", w->dev);
21340Sstevel@tonic-gate } else if (!(statb.st_mode & S_IWRITE)) {
21350Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't write to "
21366358Snakanon "'%s'\n", mythreadno, w->dev);
21370Sstevel@tonic-gate } else if (!isatty(ttyf)) {
21380Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): '%s' not a tty\n",
21396358Snakanon mythreadno, w->dev);
21400Sstevel@tonic-gate /*
21410Sstevel@tonic-gate * We might hit dtremote here. Don't generate
21420Sstevel@tonic-gate * error message.
21430Sstevel@tonic-gate */
21440Sstevel@tonic-gate } else if (getpwuid_r(statb.st_uid, &pw, pwbuf,
21456358Snakanon sizeof (pwbuf), &pwp) != 0) {
21460Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't determine owner "
21476358Snakanon "of '%s'\n", mythreadno, w->dev);
21480Sstevel@tonic-gate errno = 0;
21490Sstevel@tonic-gate logerror("Can't determine owner of '%s'", w->dev);
21500Sstevel@tonic-gate } else if (strncmp(pw.pw_name, w->ut_name, UNAMESZ) != 0) {
21510Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Bad terminal owner '%s'"
21526358Snakanon "\n", mythreadno, w->dev);
21530Sstevel@tonic-gate errno = 0;
21540Sstevel@tonic-gate logerror("%s %s owns '%s' %s %.*s",
21556358Snakanon "Bad terminal owner;", pw.pw_name, w->dev,
21566358Snakanon "but utmpx says", UNAMESZ, w->ut_name);
21570Sstevel@tonic-gate } else if (write(ttyf, w->msg, len) != len) {
21580Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Write failed to "
21596358Snakanon "'%s'\n", mythreadno, w->dev);
21600Sstevel@tonic-gate errno = 0;
21610Sstevel@tonic-gate logerror("Write failed to '%s'", w->dev);
21620Sstevel@tonic-gate }
21630Sstevel@tonic-gate
21640Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): write to '%s' succeeded\n",
21656358Snakanon mythreadno, w->dev);
21660Sstevel@tonic-gate
21670Sstevel@tonic-gate (void) close(ttyf);
21680Sstevel@tonic-gate } else {
21690Sstevel@tonic-gate DPRINT2(1, "writetodev(%u): Can't open '%s'\n",
21706358Snakanon mythreadno, w->dev);
21710Sstevel@tonic-gate }
21720Sstevel@tonic-gate
21732104Sjjj (void) pthread_attr_destroy(&w->thread_attr);
21740Sstevel@tonic-gate free(w);
21750Sstevel@tonic-gate
21760Sstevel@tonic-gate DPRINT1(1, "writetodev(%u): Device writer thread exiting\n",
21776358Snakanon mythreadno);
21780Sstevel@tonic-gate
21790Sstevel@tonic-gate pthread_exit(0);
21800Sstevel@tonic-gate return (NULL);
21810Sstevel@tonic-gate /*NOTREACHED*/
21820Sstevel@tonic-gate }
21830Sstevel@tonic-gate
21840Sstevel@tonic-gate /*
21850Sstevel@tonic-gate * Return a printable representation of a host address. If unable to
21860Sstevel@tonic-gate * look up hostname, format the numeric address for display instead.
21870Sstevel@tonic-gate *
21880Sstevel@tonic-gate * First calls hnc_lookup to see if there is valid cache entry for
21890Sstevel@tonic-gate * given network address. If it failed, cvthname looks up hostname,
21900Sstevel@tonic-gate * and push the results into the hostname cache.
21910Sstevel@tonic-gate */
21920Sstevel@tonic-gate static host_list_t *
cvthname(struct netbuf * nbp,struct netconfig * ncp,char * failsafe_addr)21930Sstevel@tonic-gate cvthname(struct netbuf *nbp, struct netconfig *ncp, char *failsafe_addr)
21940Sstevel@tonic-gate {
21950Sstevel@tonic-gate int i;
21960Sstevel@tonic-gate host_list_t *h;
21970Sstevel@tonic-gate struct nd_hostservlist *hsp;
21980Sstevel@tonic-gate struct nd_hostserv *hspp;
21990Sstevel@tonic-gate pthread_t mythreadno;
2200955Spd155743 int hindex;
22010Sstevel@tonic-gate char *uap;
22020Sstevel@tonic-gate
22030Sstevel@tonic-gate if (Debug) {
22040Sstevel@tonic-gate mythreadno = pthread_self();
22050Sstevel@tonic-gate }
22060Sstevel@tonic-gate
22070Sstevel@tonic-gate if (Debug)
22080Sstevel@tonic-gate uap = taddr2uaddr(ncp, nbp);
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): looking up hostname for %s\n",
22116358Snakanon mythreadno, uap ? uap : "<unknown>");
22120Sstevel@tonic-gate
2213955Spd155743 if ((h = hnc_lookup(nbp, ncp, &hindex)) != NULL) {
22140Sstevel@tonic-gate DPRINT4(2, "cvthname(%u): Cache found %p for %s (%s)\n",
22156358Snakanon mythreadno, (void *)h, uap ? uap : "<unknown>",
22166358Snakanon h->hl_hosts[0]);
22170Sstevel@tonic-gate return (h);
22180Sstevel@tonic-gate }
22190Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): No cache found for %s\n",
22206358Snakanon mythreadno, uap ? uap : "<unknown>");
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate if (Debug)
22230Sstevel@tonic-gate free(uap);
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) {
22260Sstevel@tonic-gate return (NULL);
22270Sstevel@tonic-gate }
22280Sstevel@tonic-gate
22290Sstevel@tonic-gate /* memory allocation failure here is fatal */
22300Sstevel@tonic-gate if ((h = malloc(sizeof (host_list_t))) == NULL) {
22310Sstevel@tonic-gate MALLOC_FAIL("host name conversion");
22320Sstevel@tonic-gate return (NULL);
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate
22350Sstevel@tonic-gate if (netdir_getbyaddr(ncp, &hsp, nbp) == 0) {
22360Sstevel@tonic-gate if (hsp->h_cnt <= 0) {
22370Sstevel@tonic-gate out: netdir_free((void *)hsp, ND_HOSTSERVLIST);
22380Sstevel@tonic-gate free(h);
22390Sstevel@tonic-gate return (NULL);
22400Sstevel@tonic-gate }
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate hspp = hsp->h_hostservs;
22430Sstevel@tonic-gate h->hl_cnt = hsp->h_cnt;
22440Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *) * (h->hl_cnt));
22450Sstevel@tonic-gate if (h->hl_hosts == NULL) {
22460Sstevel@tonic-gate MALLOC_FAIL("host name conversion");
22470Sstevel@tonic-gate goto out;
22480Sstevel@tonic-gate }
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate DPRINT2(2, "cvthname(%u): Found %d hostnames\n",
22516358Snakanon mythreadno, h->hl_cnt);
22520Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) {
22530Sstevel@tonic-gate h->hl_hosts[i] = (char *)
22540Sstevel@tonic-gate malloc(sizeof (char) * (strlen(hspp->h_host) + 1));
22550Sstevel@tonic-gate if (h->hl_hosts[i] == NULL) {
22560Sstevel@tonic-gate int j;
22570Sstevel@tonic-gate for (j = 0; j < i; j++) {
22580Sstevel@tonic-gate free(h->hl_hosts[j]);
22590Sstevel@tonic-gate }
22600Sstevel@tonic-gate free(h->hl_hosts);
22610Sstevel@tonic-gate MALLOC_FAIL("host name conversion");
22620Sstevel@tonic-gate goto out;
22630Sstevel@tonic-gate }
22640Sstevel@tonic-gate (void) strcpy(h->hl_hosts[i], hspp->h_host);
22650Sstevel@tonic-gate hspp++;
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate netdir_free((void *)hsp, ND_HOSTSERVLIST);
22680Sstevel@tonic-gate } else { /* unknown address */
22690Sstevel@tonic-gate h->hl_cnt = 1;
22700Sstevel@tonic-gate h->hl_hosts = (char **)malloc(sizeof (char *));
22710Sstevel@tonic-gate if (h->hl_hosts == NULL) {
22720Sstevel@tonic-gate free(h);
22730Sstevel@tonic-gate MALLOC_FAIL("host name conversion");
22740Sstevel@tonic-gate return (NULL);
22750Sstevel@tonic-gate }
22760Sstevel@tonic-gate h->hl_hosts[0] = (char *)malloc(strlen(failsafe_addr) + 3);
22770Sstevel@tonic-gate if (h->hl_hosts[0] == NULL) {
22780Sstevel@tonic-gate free(h->hl_hosts);
22790Sstevel@tonic-gate free(h);
22800Sstevel@tonic-gate MALLOC_FAIL("host name conversion");
22810Sstevel@tonic-gate return (NULL);
22820Sstevel@tonic-gate }
22832104Sjjj /*LINTED*/
22840Sstevel@tonic-gate (void) sprintf(h->hl_hosts[0], "[%s]", failsafe_addr);
22850Sstevel@tonic-gate DPRINT2(1, "cvthname(%u): Hostname lookup failed "
22866358Snakanon "- using address %s instead\n",
22876358Snakanon mythreadno, h->hl_hosts[0]);
22880Sstevel@tonic-gate }
22890Sstevel@tonic-gate
22900Sstevel@tonic-gate h->hl_refcnt = 1;
22910Sstevel@tonic-gate if (pthread_mutex_init(&h->hl_mutex, NULL) != 0) {
22920Sstevel@tonic-gate logerror("pthread_mutex_init failed");
22930Sstevel@tonic-gate /* This host_list won't be shared by the cache. */
22940Sstevel@tonic-gate return (h);
22950Sstevel@tonic-gate }
2296955Spd155743 hnc_register(nbp, ncp, h, hindex);
22970Sstevel@tonic-gate DPRINT3(2, "cvthname(%u): returning %p for %s\n",
22986358Snakanon mythreadno, (void *)h, h->hl_hosts[0]);
22990Sstevel@tonic-gate return (h);
23000Sstevel@tonic-gate }
23010Sstevel@tonic-gate
23020Sstevel@tonic-gate /*
23030Sstevel@tonic-gate * Print syslogd errors some place. Need to be careful here, because
23040Sstevel@tonic-gate * this routine is called at times when we're not initialized and
23050Sstevel@tonic-gate * ready to log messages...in this case, fall back to using the console.
23060Sstevel@tonic-gate */
23070Sstevel@tonic-gate void
logerror(const char * type,...)23080Sstevel@tonic-gate logerror(const char *type, ...)
23090Sstevel@tonic-gate {
23100Sstevel@tonic-gate char buf[MAXLINE+1];
23110Sstevel@tonic-gate pthread_t mythreadno;
23120Sstevel@tonic-gate int flag;
23130Sstevel@tonic-gate va_list ap;
23140Sstevel@tonic-gate
23150Sstevel@tonic-gate if (Debug) {
23160Sstevel@tonic-gate mythreadno = pthread_self();
23170Sstevel@tonic-gate }
23180Sstevel@tonic-gate
23190Sstevel@tonic-gate va_start(ap, type);
23200Sstevel@tonic-gate logerror_format(type, buf, ap);
23210Sstevel@tonic-gate va_end(ap);
23220Sstevel@tonic-gate DPRINT2(1, "logerror(%u): %s\n", mythreadno, buf);
23230Sstevel@tonic-gate
23242104Sjjj (void) pthread_mutex_lock(&logerror_lock);
23250Sstevel@tonic-gate if (!interrorlog) {
23260Sstevel@tonic-gate flag = 0;
23270Sstevel@tonic-gate if (logerror_to_console(1, buf) == 0) {
23280Sstevel@tonic-gate /* has written to the console */
23290Sstevel@tonic-gate flag = IGN_CONS;
23300Sstevel@tonic-gate }
23310Sstevel@tonic-gate (void) logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE|flag, 1);
23320Sstevel@tonic-gate } else {
23330Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE, 0) == -1) {
23340Sstevel@tonic-gate (void) logerror_to_console(1, buf);
23350Sstevel@tonic-gate }
23360Sstevel@tonic-gate }
23372104Sjjj (void) pthread_mutex_unlock(&logerror_lock);
23380Sstevel@tonic-gate
23390Sstevel@tonic-gate errno = 0;
23400Sstevel@tonic-gate t_errno = 0;
23410Sstevel@tonic-gate }
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate static void
logerror_format(const char * type,char * buf,va_list ap)23440Sstevel@tonic-gate logerror_format(const char *type, char *buf, va_list ap)
23450Sstevel@tonic-gate {
23460Sstevel@tonic-gate char tmpbuf[MAXLINE + 1];
23470Sstevel@tonic-gate pthread_t mythreadno;
23480Sstevel@tonic-gate
23490Sstevel@tonic-gate if (Debug) {
23500Sstevel@tonic-gate mythreadno = pthread_self();
23510Sstevel@tonic-gate }
23520Sstevel@tonic-gate
23530Sstevel@tonic-gate (void) vsnprintf(tmpbuf, MAXLINE, type, ap);
23540Sstevel@tonic-gate
23550Sstevel@tonic-gate if (t_errno == 0 || t_errno == TSYSERR) {
23560Sstevel@tonic-gate char *errstr;
23570Sstevel@tonic-gate
23580Sstevel@tonic-gate if (errno == 0) {
23590Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %.*s",
23606358Snakanon MAXLINE, tmpbuf);
23610Sstevel@tonic-gate } else if ((errstr = strerror(errno)) == (char *)NULL) {
23620Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: error"
23636358Snakanon " %d", tmpbuf, errno);
23640Sstevel@tonic-gate } else {
23650Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
23666358Snakanon tmpbuf, errstr);
23670Sstevel@tonic-gate }
23680Sstevel@tonic-gate } else {
23690Sstevel@tonic-gate if (t_errno > t_nerr) {
23700Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s:"
23716358Snakanon " t_error %d", tmpbuf, t_errno);
23720Sstevel@tonic-gate } else {
23730Sstevel@tonic-gate (void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
23746358Snakanon tmpbuf, t_errlist[t_errno]);
23750Sstevel@tonic-gate }
23760Sstevel@tonic-gate }
23770Sstevel@tonic-gate
23780Sstevel@tonic-gate DPRINT2(5, "logerror_format(%u): out %s\n", mythreadno, buf);
23790Sstevel@tonic-gate }
23800Sstevel@tonic-gate
23810Sstevel@tonic-gate static int
logerror_to_console(int nonblock,const char * buf)23820Sstevel@tonic-gate logerror_to_console(int nonblock, const char *buf)
23830Sstevel@tonic-gate {
23840Sstevel@tonic-gate int cfd, modes;
23850Sstevel@tonic-gate pthread_t mythreadno;
23860Sstevel@tonic-gate int ret = 0, len;
23870Sstevel@tonic-gate char tmpbuf[MAXLINE + 1];
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate if (Debug) {
23900Sstevel@tonic-gate mythreadno = pthread_self();
23910Sstevel@tonic-gate }
23920Sstevel@tonic-gate
23930Sstevel@tonic-gate DPRINT2(1, "logerror_to_console(%u): %s\n", mythreadno, buf);
23940Sstevel@tonic-gate
23950Sstevel@tonic-gate /*
23960Sstevel@tonic-gate * must use open here instead of fopen, because
23970Sstevel@tonic-gate * we need the O_NOCTTY behavior - otherwise we
23980Sstevel@tonic-gate * could hang the console at boot time
23990Sstevel@tonic-gate */
24000Sstevel@tonic-gate
24010Sstevel@tonic-gate modes = (nonblock) ?
24026358Snakanon O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK :
24036358Snakanon O_WRONLY|O_APPEND|O_NOCTTY;
24040Sstevel@tonic-gate
24050Sstevel@tonic-gate if (((cfd = open(sysmsg, modes)) >= 0) ||
24060Sstevel@tonic-gate ((cfd = open(ctty, modes)) >= 0)) {
24070Sstevel@tonic-gate (void) snprintf(tmpbuf, MAXLINE, "%s\n", buf);
24080Sstevel@tonic-gate len = strlen(tmpbuf);
24090Sstevel@tonic-gate if (write(cfd, tmpbuf, len) != len) {
24100Sstevel@tonic-gate ret = 1;
24110Sstevel@tonic-gate }
24120Sstevel@tonic-gate (void) close(cfd);
24130Sstevel@tonic-gate } else {
24140Sstevel@tonic-gate ret = 1;
24150Sstevel@tonic-gate
24160Sstevel@tonic-gate /* punt */
24170Sstevel@tonic-gate DPRINT1(1, "logerror_console(%u): can't open console\n",
24186358Snakanon mythreadno);
24190Sstevel@tonic-gate }
24200Sstevel@tonic-gate return (ret);
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate
24230Sstevel@tonic-gate /*
24240Sstevel@tonic-gate * copy current message to saved message in filed structure.
24250Sstevel@tonic-gate */
24260Sstevel@tonic-gate static void
copy_msg(struct filed * f)24270Sstevel@tonic-gate copy_msg(struct filed *f)
24280Sstevel@tonic-gate {
24290Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.msg, f->f_current.msg, MAXLINE+1);
24300Sstevel@tonic-gate (void) strlcpy(f->f_prevmsg.host, f->f_current.host, SYS_NMLN);
24310Sstevel@tonic-gate f->f_prevmsg.pri = f->f_current.pri;
24320Sstevel@tonic-gate f->f_prevmsg.flags = f->f_current.flags;
24330Sstevel@tonic-gate f->f_prevmsg.time = f->f_current.time;
24340Sstevel@tonic-gate f->f_msgflag |= OLD_VALID;
24350Sstevel@tonic-gate }
24360Sstevel@tonic-gate
24370Sstevel@tonic-gate
24380Sstevel@tonic-gate /*
24390Sstevel@tonic-gate * function to free a host_list_t struct that was allocated
24400Sstevel@tonic-gate * out of cvthname(). There is a special case where we don't
24410Sstevel@tonic-gate * free the hostname list in LocalHostName, because that's
24420Sstevel@tonic-gate * our own addresses, and we just want to have to look it
24430Sstevel@tonic-gate * up once and save it. Also don't free it if it's
24440Sstevel@tonic-gate * NullHostName, because that's a special one we use if
24450Sstevel@tonic-gate * name service lookup fails.
24460Sstevel@tonic-gate *
24470Sstevel@tonic-gate * By having hostname cache, now host_list_t will be shared
24480Sstevel@tonic-gate * by messages and hostname cache. hl_refcnt is used for
24490Sstevel@tonic-gate * the purpose.
24500Sstevel@tonic-gate */
24510Sstevel@tonic-gate static void
freehl(host_list_t * h)24520Sstevel@tonic-gate freehl(host_list_t *h)
24530Sstevel@tonic-gate {
24540Sstevel@tonic-gate int i, refcnt;
24550Sstevel@tonic-gate pthread_t mythreadno;
24560Sstevel@tonic-gate
24570Sstevel@tonic-gate if (Debug) {
24580Sstevel@tonic-gate mythreadno = pthread_self();
24590Sstevel@tonic-gate }
24600Sstevel@tonic-gate
24612104Sjjj DPRINT2(2, "freehl(%u): releasing %p\n", mythreadno, (void *)h);
24620Sstevel@tonic-gate
24630Sstevel@tonic-gate if (h == NULL || h == &LocalHostName || h == &NullHostName) {
24640Sstevel@tonic-gate return;
24650Sstevel@tonic-gate }
24660Sstevel@tonic-gate
24672104Sjjj (void) pthread_mutex_lock(&h->hl_mutex);
24680Sstevel@tonic-gate refcnt = --h->hl_refcnt;
24692104Sjjj (void) pthread_mutex_unlock(&h->hl_mutex);
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate if (refcnt != 0) {
24720Sstevel@tonic-gate DPRINT3(5, "freehl(%u): %p has reference %d\n",
24736358Snakanon mythreadno, (void *)h, refcnt);
24740Sstevel@tonic-gate return;
24750Sstevel@tonic-gate }
24760Sstevel@tonic-gate
24772104Sjjj (void) pthread_mutex_destroy(&h->hl_mutex);
24782104Sjjj
24792104Sjjj DPRINT2(5, "freehl(%u): freeing %p\n", mythreadno, (void *)h);
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate for (i = 0; i < h->hl_cnt; i++) {
24820Sstevel@tonic-gate free(h->hl_hosts[i]);
24830Sstevel@tonic-gate }
24840Sstevel@tonic-gate
24850Sstevel@tonic-gate free(h->hl_hosts);
24860Sstevel@tonic-gate free(h);
24870Sstevel@tonic-gate }
24880Sstevel@tonic-gate
24890Sstevel@tonic-gate /*
24900Sstevel@tonic-gate * Create the door file and the pid file in /var/run. If the filesystem
24910Sstevel@tonic-gate * containing /etc is writable, create symlinks /etc/.syslog_door and
24920Sstevel@tonic-gate * /etc/syslog.pid to them. On systems that do not support /var/run, create
24930Sstevel@tonic-gate * /etc/.syslog_door and /etc/syslog.pid directly.
24940Sstevel@tonic-gate *
24950Sstevel@tonic-gate * Note: it is not considered fatal to fail to create the pid file or its
24960Sstevel@tonic-gate * symlink. Attempts to use them in the usual way will fail, of course, but
24970Sstevel@tonic-gate * syslogd will function nicely without it (not so for the door file).
24980Sstevel@tonic-gate */
24990Sstevel@tonic-gate
25000Sstevel@tonic-gate static void
open_door(void)25010Sstevel@tonic-gate open_door(void)
25020Sstevel@tonic-gate {
25030Sstevel@tonic-gate struct stat buf;
25040Sstevel@tonic-gate door_info_t info;
25050Sstevel@tonic-gate char line[MAXLINE+1];
25060Sstevel@tonic-gate pthread_t mythreadno;
25070Sstevel@tonic-gate int err;
25080Sstevel@tonic-gate
25090Sstevel@tonic-gate if (Debug) {
25100Sstevel@tonic-gate mythreadno = pthread_self();
25110Sstevel@tonic-gate }
25120Sstevel@tonic-gate
25130Sstevel@tonic-gate /*
25140Sstevel@tonic-gate * first see if another syslogd is running by trying
25150Sstevel@tonic-gate * a door call - if it succeeds, there is already
25160Sstevel@tonic-gate * a syslogd process active
25170Sstevel@tonic-gate */
25180Sstevel@tonic-gate
25190Sstevel@tonic-gate if (!DoorCreated) {
25200Sstevel@tonic-gate int door;
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
25230Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s opened "
25246358Snakanon "successfully\n", mythreadno, DoorFileName);
25250Sstevel@tonic-gate
25260Sstevel@tonic-gate if (door_info(door, &info) >= 0) {
25270Sstevel@tonic-gate DPRINT2(5, "open_door(%u): "
25286358Snakanon "door_info:info.di_target = %ld\n",
25296358Snakanon mythreadno, info.di_target);
25300Sstevel@tonic-gate
25310Sstevel@tonic-gate if (info.di_target > 0) {
25320Sstevel@tonic-gate (void) sprintf(line, "syslogd pid %ld"
25336358Snakanon " already running. Cannot "
25346358Snakanon "start another syslogd pid %ld",
25356358Snakanon info.di_target, getpid());
25360Sstevel@tonic-gate DPRINT2(5, "open_door(%u): error: "
25376358Snakanon "%s\n", mythreadno, line);
25380Sstevel@tonic-gate errno = 0;
25390Sstevel@tonic-gate logerror(line);
25400Sstevel@tonic-gate exit(1);
25410Sstevel@tonic-gate }
25420Sstevel@tonic-gate }
25430Sstevel@tonic-gate
25440Sstevel@tonic-gate (void) close(door);
25450Sstevel@tonic-gate } else {
25460Sstevel@tonic-gate if (lstat(DoorFileName, &buf) < 0) {
25470Sstevel@tonic-gate err = errno;
25480Sstevel@tonic-gate
25490Sstevel@tonic-gate DPRINT3(5, "open_door(%u): lstat() of %s "
25506358Snakanon "failed, errno=%d\n",
25516358Snakanon mythreadno, DoorFileName, err);
25520Sstevel@tonic-gate
25530Sstevel@tonic-gate if ((door = creat(DoorFileName, 0644)) < 0) {
25540Sstevel@tonic-gate err = errno;
25552104Sjjj (void) snprintf(line, sizeof (line),
25562104Sjjj "creat() of %s failed - fatal",
25572104Sjjj DoorFileName);
25580Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, "
25596358Snakanon "errno=%d\n", mythreadno, line,
25606358Snakanon err);
25610Sstevel@tonic-gate errno = err;
25620Sstevel@tonic-gate logerror(line);
25630Sstevel@tonic-gate delete_doorfiles();
25640Sstevel@tonic-gate exit(1);
25650Sstevel@tonic-gate }
25660Sstevel@tonic-gate
25670Sstevel@tonic-gate (void) fchmod(door,
25686358Snakanon S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
25690Sstevel@tonic-gate
25700Sstevel@tonic-gate DPRINT2(5, "open_door(%u): creat() of %s "
25716358Snakanon "succeeded\n", mythreadno,
25726358Snakanon DoorFileName);
25730Sstevel@tonic-gate
25740Sstevel@tonic-gate (void) close(door);
25750Sstevel@tonic-gate }
25760Sstevel@tonic-gate }
25770Sstevel@tonic-gate
25780Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) {
25790Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &buf) == 0) {
25800Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s "
25816358Snakanon "succeeded\n", mythreadno,
25826358Snakanon OLD_DOORFILE);
25830Sstevel@tonic-gate
25840Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) {
25852104Sjjj (void) snprintf(line, sizeof (line),
25862104Sjjj "%s is a directory - fatal",
25872104Sjjj OLD_DOORFILE);
25880Sstevel@tonic-gate DPRINT2(1, "open_door(%u): error: "
25896358Snakanon "%s\n", mythreadno, line);
25900Sstevel@tonic-gate errno = 0;
25910Sstevel@tonic-gate logerror(line);
25920Sstevel@tonic-gate delete_doorfiles();
25930Sstevel@tonic-gate exit(1);
25940Sstevel@tonic-gate }
25950Sstevel@tonic-gate
25960Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s is not a "
25976358Snakanon "directory\n",
25986358Snakanon mythreadno, OLD_DOORFILE);
25990Sstevel@tonic-gate
26000Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) {
26010Sstevel@tonic-gate err = errno;
26022104Sjjj (void) snprintf(line, sizeof (line),
26032104Sjjj "unlink() of %s failed",
26042104Sjjj OLD_DOORFILE);
26050Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n",
26066358Snakanon mythreadno, line);
26070Sstevel@tonic-gate
26080Sstevel@tonic-gate if (err != EROFS) {
26090Sstevel@tonic-gate DPRINT3(1, "open_door(%u): "
26106358Snakanon "error: %s, "
26116358Snakanon "errno=%d\n",
26126358Snakanon mythreadno, line, err);
26130Sstevel@tonic-gate (void) strcat(line, " - fatal");
26140Sstevel@tonic-gate errno = err;
26150Sstevel@tonic-gate logerror(line);
26160Sstevel@tonic-gate delete_doorfiles();
26170Sstevel@tonic-gate exit(1);
26180Sstevel@tonic-gate }
26190Sstevel@tonic-gate
26200Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink "
26216358Snakanon "failure OK on RO file "
26226358Snakanon "system\n", mythreadno);
26230Sstevel@tonic-gate }
26240Sstevel@tonic-gate } else {
26250Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't "
26266358Snakanon "exist\n", mythreadno, OLD_DOORFILE);
26270Sstevel@tonic-gate }
26280Sstevel@tonic-gate
26290Sstevel@tonic-gate if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) {
26300Sstevel@tonic-gate err = errno;
26312104Sjjj (void) snprintf(line, sizeof (line),
26322104Sjjj "symlink %s -> %s failed", OLD_DOORFILE,
26332104Sjjj RELATIVE_DOORFILE);
26340Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno,
26356358Snakanon line);
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate if (err != EROFS) {
26380Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, "
26396358Snakanon "errno=%d\n", mythreadno, line,
26406358Snakanon err);
26410Sstevel@tonic-gate errno = err;
26420Sstevel@tonic-gate (void) strcat(line, " - fatal");
26430Sstevel@tonic-gate logerror(line);
26440Sstevel@tonic-gate delete_doorfiles();
26450Sstevel@tonic-gate exit(1);
26460Sstevel@tonic-gate }
26470Sstevel@tonic-gate
26480Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK "
26496358Snakanon "on RO file system\n", mythreadno);
26500Sstevel@tonic-gate } else {
26510Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s "
26526358Snakanon "succeeded\n", mythreadno,
26536358Snakanon OLD_DOORFILE, RELATIVE_DOORFILE);
26540Sstevel@tonic-gate }
26550Sstevel@tonic-gate }
26560Sstevel@tonic-gate
26570Sstevel@tonic-gate if ((DoorFd = door_create(server, 0,
26580Sstevel@tonic-gate DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
26590Sstevel@tonic-gate err = errno;
26600Sstevel@tonic-gate (void) sprintf(line, "door_create() failed - fatal");
26610Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n",
26626358Snakanon mythreadno, line, err);
26630Sstevel@tonic-gate errno = err;
26640Sstevel@tonic-gate logerror(line);
26650Sstevel@tonic-gate delete_doorfiles();
26660Sstevel@tonic-gate exit(1);
26670Sstevel@tonic-gate }
26680Sstevel@tonic-gate (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
26690Sstevel@tonic-gate DPRINT2(5, "open_door(%u): door_create() succeeded, "
26706358Snakanon "DoorFd=%d\n", mythreadno, DoorFd);
26710Sstevel@tonic-gate
26720Sstevel@tonic-gate DoorCreated = 1;
26730Sstevel@tonic-gate }
26740Sstevel@tonic-gate
26750Sstevel@tonic-gate (void) fdetach(DoorFileName); /* just in case... */
26760Sstevel@tonic-gate
26776358Snakanon (void) door_server_create(door_server_pool);
26786358Snakanon
26790Sstevel@tonic-gate if (fattach(DoorFd, DoorFileName) < 0) {
26800Sstevel@tonic-gate err = errno;
26812104Sjjj (void) snprintf(line, sizeof (line), "fattach() of fd"
26826358Snakanon " %d to %s failed - fatal", DoorFd, DoorFileName);
26830Sstevel@tonic-gate DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", mythreadno,
26846358Snakanon line, err);
26850Sstevel@tonic-gate errno = err;
26860Sstevel@tonic-gate logerror(line);
26870Sstevel@tonic-gate delete_doorfiles();
26880Sstevel@tonic-gate exit(1);
26890Sstevel@tonic-gate }
26900Sstevel@tonic-gate
26910Sstevel@tonic-gate DPRINT2(5, "open_door(%u): attached server() to %s\n", mythreadno,
26926358Snakanon DoorFileName);
26930Sstevel@tonic-gate
26940Sstevel@tonic-gate /*
26950Sstevel@tonic-gate * create pidfile anyway, so those using it to control
26960Sstevel@tonic-gate * syslogd (with kill `cat /etc/syslog.pid` perhaps)
26970Sstevel@tonic-gate * don't get broken.
26980Sstevel@tonic-gate */
26990Sstevel@tonic-gate
27000Sstevel@tonic-gate if (!PidfileCreated) {
27010Sstevel@tonic-gate int pidfd;
27020Sstevel@tonic-gate
27030Sstevel@tonic-gate PidfileCreated = 1;
27040Sstevel@tonic-gate
27050Sstevel@tonic-gate if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644))
27060Sstevel@tonic-gate < 0) {
27070Sstevel@tonic-gate err = errno;
27082104Sjjj (void) snprintf(line, sizeof (line),
27092104Sjjj "open() of %s failed", PidFileName);
27100Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
27116358Snakanon mythreadno, line, err);
27120Sstevel@tonic-gate errno = err;
27130Sstevel@tonic-gate logerror(line);
27140Sstevel@tonic-gate return;
27150Sstevel@tonic-gate }
27160Sstevel@tonic-gate
27170Sstevel@tonic-gate (void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
27180Sstevel@tonic-gate (void) sprintf(line, "%ld\n", getpid());
27190Sstevel@tonic-gate
27200Sstevel@tonic-gate if (write(pidfd, line, strlen(line)) < 0) {
27210Sstevel@tonic-gate err = errno;
27222104Sjjj (void) snprintf(line, sizeof (line),
27232104Sjjj "write to %s on fd %d failed", PidFileName, pidfd);
27240Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
27256358Snakanon mythreadno, line, err);
27260Sstevel@tonic-gate errno = err;
27270Sstevel@tonic-gate logerror(line);
27280Sstevel@tonic-gate return;
27290Sstevel@tonic-gate }
27300Sstevel@tonic-gate
27310Sstevel@tonic-gate (void) close(pidfd);
27320Sstevel@tonic-gate
27330Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s created\n",
27346358Snakanon mythreadno, PidFileName);
27350Sstevel@tonic-gate
27360Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) {
27370Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &buf) == 0) {
27380Sstevel@tonic-gate DPRINT2(5, "open_door(%u): lstat() of %s "
27396358Snakanon "succeded\n", mythreadno, OLD_PIDFILE);
27400Sstevel@tonic-gate
27410Sstevel@tonic-gate if (S_ISDIR(buf.st_mode)) {
27422104Sjjj (void) snprintf(line, sizeof (line),
27432104Sjjj "file %s is a directory",
27442104Sjjj OLD_PIDFILE);
27450Sstevel@tonic-gate DPRINT2(1, "open_door(%u): warning: "
27466358Snakanon "%s\n", mythreadno, line);
27470Sstevel@tonic-gate errno = 0;
27480Sstevel@tonic-gate logerror(line);
27490Sstevel@tonic-gate return;
27500Sstevel@tonic-gate }
27510Sstevel@tonic-gate
27520Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) {
27530Sstevel@tonic-gate err = errno;
27542104Sjjj (void) snprintf(line, sizeof (line),
27552104Sjjj "unlink() of %s failed",
27562104Sjjj OLD_PIDFILE);
27570Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n",
27586358Snakanon mythreadno, line);
27590Sstevel@tonic-gate
27600Sstevel@tonic-gate if (err != EROFS) {
27610Sstevel@tonic-gate DPRINT3(1, "open_door (%u): "
27626358Snakanon "warning: %s, "
27636358Snakanon "errno=%d\n",
27646358Snakanon mythreadno, line, err);
27650Sstevel@tonic-gate errno = err;
27660Sstevel@tonic-gate logerror(line);
27670Sstevel@tonic-gate return;
27680Sstevel@tonic-gate }
27690Sstevel@tonic-gate
27700Sstevel@tonic-gate DPRINT1(5, "open_door(%u): unlink "
27716358Snakanon "failure OK on RO file "
27726358Snakanon "system\n", mythreadno);
27730Sstevel@tonic-gate }
27740Sstevel@tonic-gate } else {
27750Sstevel@tonic-gate DPRINT2(5, "open_door(%u): file %s doesn't "
27766358Snakanon "exist\n", mythreadno, OLD_PIDFILE);
27770Sstevel@tonic-gate }
27780Sstevel@tonic-gate
27790Sstevel@tonic-gate if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) {
27800Sstevel@tonic-gate err = errno;
27812104Sjjj (void) snprintf(line, sizeof (line),
27822104Sjjj "symlink %s -> %s failed", OLD_PIDFILE,
27836358Snakanon RELATIVE_PIDFILE);
27840Sstevel@tonic-gate DPRINT2(5, "open_door(%u): %s\n", mythreadno,
27856358Snakanon line);
27860Sstevel@tonic-gate
27870Sstevel@tonic-gate if (err != EROFS) {
27880Sstevel@tonic-gate DPRINT3(1, "open_door(%u): warning: "
27896358Snakanon "%s, errno=%d\n", mythreadno,
27906358Snakanon line, err);
27910Sstevel@tonic-gate errno = err;
27920Sstevel@tonic-gate logerror(line);
27930Sstevel@tonic-gate return;
27940Sstevel@tonic-gate }
27950Sstevel@tonic-gate
27960Sstevel@tonic-gate DPRINT1(5, "open_door(%u): symlink failure OK "
27976358Snakanon "on RO file system\n", mythreadno);
27980Sstevel@tonic-gate return;
27990Sstevel@tonic-gate }
28000Sstevel@tonic-gate
28010Sstevel@tonic-gate DPRINT3(5, "open_door(%u): symlink %s -> %s "
28026358Snakanon "succeeded\n", mythreadno, OLD_PIDFILE,
28036358Snakanon RELATIVE_PIDFILE);
28040Sstevel@tonic-gate }
28050Sstevel@tonic-gate }
28060Sstevel@tonic-gate }
28070Sstevel@tonic-gate
28080Sstevel@tonic-gate /*
28090Sstevel@tonic-gate * the 'server' function that we export via the door. It does
28100Sstevel@tonic-gate * nothing but return.
28110Sstevel@tonic-gate */
28120Sstevel@tonic-gate /*ARGSUSED*/
28130Sstevel@tonic-gate static void
server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n)28140Sstevel@tonic-gate server(void *cookie, char *argp, size_t arg_size,
28150Sstevel@tonic-gate door_desc_t *dp, uint_t n)
28160Sstevel@tonic-gate {
28170Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0);
28180Sstevel@tonic-gate /* NOTREACHED */
28190Sstevel@tonic-gate }
28200Sstevel@tonic-gate
28216358Snakanon /*ARGSUSED*/
28226358Snakanon static void *
create_door_thr(void * arg)28236358Snakanon create_door_thr(void *arg)
28246358Snakanon {
28256358Snakanon (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
28266358Snakanon (void) door_return(NULL, 0, NULL, 0);
28276358Snakanon
28286358Snakanon /*
28296358Snakanon * If there is an error in door_return(), it will return here and
28306358Snakanon * the thread will exit. Hence we need to decrement door_server_cnt.
28316358Snakanon */
28326358Snakanon (void) pthread_mutex_lock(&door_server_cnt_lock);
28336358Snakanon door_server_cnt--;
28346358Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock);
28356358Snakanon return (NULL);
28366358Snakanon }
28376358Snakanon
28386358Snakanon /*
28396358Snakanon * Max number of door server threads for syslogd. Since door is used
28406358Snakanon * to check the health of syslogd, we don't need large number of
28416358Snakanon * server threads.
28426358Snakanon */
28436358Snakanon #define MAX_DOOR_SERVER_THR 3
28446358Snakanon
28456358Snakanon /*
28466358Snakanon * Manage door server thread pool.
28476358Snakanon */
28486358Snakanon /*ARGSUSED*/
28496358Snakanon static void
door_server_pool(door_info_t * dip)28506358Snakanon door_server_pool(door_info_t *dip)
28516358Snakanon {
28526358Snakanon (void) pthread_mutex_lock(&door_server_cnt_lock);
28536358Snakanon if (door_server_cnt <= MAX_DOOR_SERVER_THR &&
28546358Snakanon pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) {
28556358Snakanon door_server_cnt++;
28566358Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock);
28576358Snakanon return;
28586358Snakanon }
28596358Snakanon
28606358Snakanon (void) pthread_mutex_unlock(&door_server_cnt_lock);
28616358Snakanon }
28626358Snakanon
28630Sstevel@tonic-gate /*
28640Sstevel@tonic-gate * checkm4 - used to verify that the external utilities that
28650Sstevel@tonic-gate * syslogd depends on are where we expect them to be.
28660Sstevel@tonic-gate * Returns 0 if all utilities are found, > 0 if any are missing.
28670Sstevel@tonic-gate * Also logs errors so user knows what's missing
28680Sstevel@tonic-gate */
28690Sstevel@tonic-gate static int
checkm4(void)28700Sstevel@tonic-gate checkm4(void)
28710Sstevel@tonic-gate {
28720Sstevel@tonic-gate int notfound = 0;
28730Sstevel@tonic-gate int saverrno;
28740Sstevel@tonic-gate pthread_t mythreadno;
28750Sstevel@tonic-gate
28760Sstevel@tonic-gate if (Debug) {
28770Sstevel@tonic-gate mythreadno = pthread_self();
28780Sstevel@tonic-gate }
28790Sstevel@tonic-gate
28800Sstevel@tonic-gate if (access("/usr/ccs/bin/m4", X_OK) < 0) {
28810Sstevel@tonic-gate saverrno = errno;
28820Sstevel@tonic-gate logerror("/usr/ccs/bin/m4");
28830Sstevel@tonic-gate DPRINT2(1, "checkm4(%u): /usr/ccs/bin/m4 - access "
28846358Snakanon "returned %d\n", mythreadno, saverrno);
28850Sstevel@tonic-gate notfound++;
28860Sstevel@tonic-gate }
28870Sstevel@tonic-gate
28880Sstevel@tonic-gate return (notfound);
28890Sstevel@tonic-gate }
28900Sstevel@tonic-gate
28910Sstevel@tonic-gate /*
28920Sstevel@tonic-gate * INIT -- Initialize syslogd from configuration table, start up
28930Sstevel@tonic-gate * input and logger threads. This routine is called only once.
28940Sstevel@tonic-gate */
28950Sstevel@tonic-gate static void
init(void)28960Sstevel@tonic-gate init(void)
28970Sstevel@tonic-gate {
28980Sstevel@tonic-gate struct utsname *up;
28990Sstevel@tonic-gate pthread_attr_t sys_attr, net_attr, log_attr, hnl_attr;
29000Sstevel@tonic-gate int nthread;
29010Sstevel@tonic-gate pthread_t mythreadno;
29020Sstevel@tonic-gate
29030Sstevel@tonic-gate if (Debug) {
29040Sstevel@tonic-gate mythreadno = pthread_self();
29050Sstevel@tonic-gate }
29060Sstevel@tonic-gate
29070Sstevel@tonic-gate DPRINT1(2, "init(%u): initializing\n", mythreadno);
29080Sstevel@tonic-gate
29090Sstevel@tonic-gate /* hand-craft a host_list_t entry for our local host name */
29100Sstevel@tonic-gate if ((up = malloc(sizeof (struct utsname))) == NULL) {
29110Sstevel@tonic-gate MALLOC_FAIL_EXIT;
29120Sstevel@tonic-gate }
29130Sstevel@tonic-gate (void) uname(up);
29140Sstevel@tonic-gate LocalHostName.hl_cnt = 1;
29150Sstevel@tonic-gate if ((LocalHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
29160Sstevel@tonic-gate MALLOC_FAIL_EXIT;
29170Sstevel@tonic-gate }
29180Sstevel@tonic-gate if ((LocalHostName.hl_hosts[0] = strdup(up->nodename)) == NULL) {
29190Sstevel@tonic-gate free(LocalHostName.hl_hosts);
29200Sstevel@tonic-gate MALLOC_FAIL_EXIT;
29210Sstevel@tonic-gate }
29220Sstevel@tonic-gate free(up);
29230Sstevel@tonic-gate /* also hand craft one for use if name resolution fails */
29240Sstevel@tonic-gate NullHostName.hl_cnt = 1;
29250Sstevel@tonic-gate if ((NullHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
29260Sstevel@tonic-gate MALLOC_FAIL_EXIT;
29270Sstevel@tonic-gate }
29280Sstevel@tonic-gate if ((NullHostName.hl_hosts[0] = strdup("name lookup failed")) == NULL) {
29290Sstevel@tonic-gate MALLOC_FAIL_EXIT;
29300Sstevel@tonic-gate }
29310Sstevel@tonic-gate
29320Sstevel@tonic-gate hnc_init(0);
29330Sstevel@tonic-gate
29340Sstevel@tonic-gate /*
29350Sstevel@tonic-gate * Note that getnets will allocate network resources, but won't be
29360Sstevel@tonic-gate * binding UDP port. This is because, there could be a race
29370Sstevel@tonic-gate * condition between door. If we bind here, one syslogd could grab
29380Sstevel@tonic-gate * UDP port first, but later another syslogd could take over without
29390Sstevel@tonic-gate * getting UDP port but grab the door file. The 2nd syslogd could
29400Sstevel@tonic-gate * continue to run without listening network.
29410Sstevel@tonic-gate * bindnet() will be called after door was successfully opened.
29420Sstevel@tonic-gate */
29430Sstevel@tonic-gate getnets();
29440Sstevel@tonic-gate
29450Sstevel@tonic-gate /*
29460Sstevel@tonic-gate * Start up configured theads
29470Sstevel@tonic-gate */
29480Sstevel@tonic-gate conf_init();
29490Sstevel@tonic-gate
29500Sstevel@tonic-gate /*
29510Sstevel@tonic-gate * allocate thread stacks for the persistant threads
29520Sstevel@tonic-gate */
29530Sstevel@tonic-gate nthread = (turnoff == 0) ? 4 : 2;
29540Sstevel@tonic-gate
29550Sstevel@tonic-gate if ((stack_ptr = alloc_stacks(nthread)) == NULL) {
29560Sstevel@tonic-gate logerror("alloc_stacks failed - fatal");
29570Sstevel@tonic-gate exit(1);
29580Sstevel@tonic-gate }
29590Sstevel@tonic-gate
29600Sstevel@tonic-gate if (Debug) {
29610Sstevel@tonic-gate dumpstats(STDOUT_FILENO);
29620Sstevel@tonic-gate }
29630Sstevel@tonic-gate
29640Sstevel@tonic-gate (void) dataq_init(&inputq); /* init the input queue */
29650Sstevel@tonic-gate
29660Sstevel@tonic-gate if (pthread_attr_init(&sys_attr) != 0 ||
29670Sstevel@tonic-gate pthread_attr_init(&log_attr) != 0 ||
29680Sstevel@tonic-gate pthread_attr_init(&net_attr) != 0 ||
29696358Snakanon pthread_attr_init(&hnl_attr) != 0 ||
29706358Snakanon pthread_attr_init(&door_thr_attr) != 0) {
29710Sstevel@tonic-gate logerror("pthread_attr_init failed - fatal");
29720Sstevel@tonic-gate exit(1);
29730Sstevel@tonic-gate }
29740Sstevel@tonic-gate
29750Sstevel@tonic-gate (void) pthread_attr_setscope(&sys_attr, PTHREAD_SCOPE_PROCESS);
29760Sstevel@tonic-gate (void) pthread_attr_setscope(&log_attr, PTHREAD_SCOPE_PROCESS);
29770Sstevel@tonic-gate (void) pthread_attr_setscope(&net_attr, PTHREAD_SCOPE_PROCESS);
29780Sstevel@tonic-gate (void) pthread_attr_setscope(&hnl_attr, PTHREAD_SCOPE_PROCESS);
29796358Snakanon (void) pthread_attr_setscope(&door_thr_attr, PTHREAD_SCOPE_SYSTEM);
29806358Snakanon (void) pthread_attr_setdetachstate(&door_thr_attr,
29816358Snakanon PTHREAD_CREATE_DETACHED);
29820Sstevel@tonic-gate
29830Sstevel@tonic-gate /* 1: logmsg thread */
29840Sstevel@tonic-gate (void) pthread_attr_setstacksize(&log_attr, stacksize);
29850Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&log_attr, stack_ptr);
29860Sstevel@tonic-gate stack_ptr += stacksize + redzonesize;
29870Sstevel@tonic-gate if (pthread_create(&log_thread, &log_attr, logmsg, NULL) != 0) {
29880Sstevel@tonic-gate logerror("pthread_create failed - fatal");
29890Sstevel@tonic-gate exit(1);
29900Sstevel@tonic-gate }
29910Sstevel@tonic-gate
29920Sstevel@tonic-gate /*
29930Sstevel@tonic-gate * open the log device, and pull up all pending message
29940Sstevel@tonic-gate * from the log driver.
29950Sstevel@tonic-gate */
29960Sstevel@tonic-gate prepare_sys_poll();
29970Sstevel@tonic-gate
29980Sstevel@tonic-gate /*
29990Sstevel@tonic-gate * Now we can deliver the pending internal error messages.
30000Sstevel@tonic-gate */
30010Sstevel@tonic-gate enable_errorlog();
30020Sstevel@tonic-gate
30030Sstevel@tonic-gate /* 2: sys_poll thread */
30040Sstevel@tonic-gate (void) pthread_attr_setstacksize(&sys_attr, stacksize);
30050Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&sys_attr, stack_ptr);
30060Sstevel@tonic-gate stack_ptr += stacksize + redzonesize;
30070Sstevel@tonic-gate if (pthread_create(&sys_thread, &sys_attr, sys_poll, NULL) != 0) {
30080Sstevel@tonic-gate logerror("pthread_create failed - fatal");
30090Sstevel@tonic-gate exit(1);
30100Sstevel@tonic-gate }
30110Sstevel@tonic-gate
30120Sstevel@tonic-gate /*
30130Sstevel@tonic-gate * We've started the sys_poll() and logmsg() threads. Now we are ready
30140Sstevel@tonic-gate * to open the door. This cannot happen before spawning sys_poll(),
30150Sstevel@tonic-gate * because after opening the door, syslog() will no longer take care of
30160Sstevel@tonic-gate * LOG_CONS. Therefor, we should pull up all pending log messages and
30170Sstevel@tonic-gate * activate sys_poll() before opening the door, so that log driver
30180Sstevel@tonic-gate * won't drop messages.
30190Sstevel@tonic-gate */
30200Sstevel@tonic-gate open_door();
30210Sstevel@tonic-gate
30220Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from local system\n",
30236358Snakanon mythreadno);
30240Sstevel@tonic-gate
30250Sstevel@tonic-gate if (turnoff == 0) {
30260Sstevel@tonic-gate /* init the hostname lookup queue */
30270Sstevel@tonic-gate (void) dataq_init(&hnlq);
30280Sstevel@tonic-gate
30290Sstevel@tonic-gate /* 3: hostname lookup thread */
30300Sstevel@tonic-gate (void) pthread_attr_setstacksize(&hnl_attr, stacksize);
30310Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&hnl_attr, stack_ptr);
30320Sstevel@tonic-gate stack_ptr += stacksize + redzonesize;
30330Sstevel@tonic-gate if (pthread_create(&hnl_thread, &hnl_attr,
30346358Snakanon hostname_lookup, NULL) != 0) {
30350Sstevel@tonic-gate logerror("pthread_create failed - fatal");
30360Sstevel@tonic-gate exit(1);
30370Sstevel@tonic-gate }
30380Sstevel@tonic-gate
30390Sstevel@tonic-gate /* 4: net_poll thread */
30400Sstevel@tonic-gate (void) pthread_attr_setstacksize(&net_attr, stacksize);
30410Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&net_attr, stack_ptr);
30420Sstevel@tonic-gate stack_ptr += stacksize + redzonesize;
30430Sstevel@tonic-gate
30440Sstevel@tonic-gate /* grab UDP port */
30450Sstevel@tonic-gate bindnet();
30460Sstevel@tonic-gate
30470Sstevel@tonic-gate if (pthread_create(&net_thread, &net_attr, net_poll,
30486358Snakanon NULL) != 0) {
30490Sstevel@tonic-gate logerror("pthread_create failed - fatal");
30500Sstevel@tonic-gate exit(1);
30510Sstevel@tonic-gate }
30520Sstevel@tonic-gate DPRINT1(1, "init(%u): accepting messages from remote\n",
30536358Snakanon mythreadno);
30540Sstevel@tonic-gate }
30550Sstevel@tonic-gate
30560Sstevel@tonic-gate (void) pthread_attr_destroy(&sys_attr);
30570Sstevel@tonic-gate (void) pthread_attr_destroy(&net_attr);
30580Sstevel@tonic-gate (void) pthread_attr_destroy(&log_attr);
30590Sstevel@tonic-gate (void) pthread_attr_destroy(&hnl_attr);
30600Sstevel@tonic-gate
30610Sstevel@tonic-gate curalarm = MarkInterval * 60 / MARKCOUNT;
30620Sstevel@tonic-gate (void) alarm((unsigned)curalarm);
30630Sstevel@tonic-gate DPRINT2(2, "init(%u): Next alarm in %d seconds\n",
30646358Snakanon mythreadno, curalarm);
30650Sstevel@tonic-gate DPRINT1(1, "init(%u): syslogd: started\n", mythreadno);
30660Sstevel@tonic-gate }
30670Sstevel@tonic-gate
30680Sstevel@tonic-gate /*
30690Sstevel@tonic-gate * will print a bunch of debugging stats on 'fd'
30700Sstevel@tonic-gate */
30710Sstevel@tonic-gate static void
dumpstats(int fd)30720Sstevel@tonic-gate dumpstats(int fd)
30730Sstevel@tonic-gate {
30740Sstevel@tonic-gate FILE *out;
30750Sstevel@tonic-gate struct filed *f;
30760Sstevel@tonic-gate int i;
30770Sstevel@tonic-gate char users[1024];
30780Sstevel@tonic-gate char cbuf[30];
30790Sstevel@tonic-gate char *dashes = "------------------------";
30800Sstevel@tonic-gate static int conversion_printed;
30810Sstevel@tonic-gate
30820Sstevel@tonic-gate if ((out = fdopen(fd, "w+")) == NULL)
30830Sstevel@tonic-gate return;
30840Sstevel@tonic-gate
3085*8094SVladimir.Marek@Sun.COM (void) fprintf(out, "\nSyslogd started: %s",
3086*8094SVladimir.Marek@Sun.COM ctime_r(&start_time, cbuf));
30870Sstevel@tonic-gate (void) fprintf(out, "Input message count: system %d, network %d\n",
30886358Snakanon sys_msg_count, net_msg_count);
30890Sstevel@tonic-gate (void) fprintf(out, "# Outputs: %d\n\n", nlogs);
30900Sstevel@tonic-gate
30910Sstevel@tonic-gate (void) fprintf(out, "%s priority = [file, facility] %s\n\n",
30926358Snakanon dashes, dashes);
30930Sstevel@tonic-gate
30940Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30950Sstevel@tonic-gate (void) fprintf(out, "%d ", i / 10);
30960Sstevel@tonic-gate }
30970Sstevel@tonic-gate (void) fprintf(out, "\n");
30980Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30990Sstevel@tonic-gate (void) fprintf(out, "%d ", i % 10);
31000Sstevel@tonic-gate }
31010Sstevel@tonic-gate (void) fprintf(out, "\n");
31020Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) {
31030Sstevel@tonic-gate (void) fprintf(out, "--");
31040Sstevel@tonic-gate }
31050Sstevel@tonic-gate (void) fprintf(out, "\n");
31060Sstevel@tonic-gate
31070Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
31080Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES + 1; i++) {
31090Sstevel@tonic-gate if (f->f_pmask[i] == NOPRI)
31100Sstevel@tonic-gate (void) fprintf(out, "X ");
31110Sstevel@tonic-gate else
31120Sstevel@tonic-gate (void) fprintf(out, "%d ",
31136358Snakanon f->f_pmask[i]);
31140Sstevel@tonic-gate }
31150Sstevel@tonic-gate (void) fprintf(out, "%s: ", TypeNames[f->f_type]);
31160Sstevel@tonic-gate switch (f->f_type) {
31170Sstevel@tonic-gate case F_FILE:
31180Sstevel@tonic-gate case F_TTY:
31190Sstevel@tonic-gate case F_CONSOLE:
31200Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_fname);
31210Sstevel@tonic-gate break;
31220Sstevel@tonic-gate case F_FORW:
31230Sstevel@tonic-gate (void) fprintf(out, "%s", f->f_un.f_forw.f_hname);
31240Sstevel@tonic-gate break;
31250Sstevel@tonic-gate case F_USERS:
31260Sstevel@tonic-gate for (i = 0; i < MAXUNAMES &&
31276358Snakanon *f->f_un.f_uname[i]; i++) {
31280Sstevel@tonic-gate if (!i)
31290Sstevel@tonic-gate (void) fprintf(out, "%s",
31306358Snakanon f->f_un.f_uname[i]);
31310Sstevel@tonic-gate else
31320Sstevel@tonic-gate (void) fprintf(out, ", %s",
31336358Snakanon f->f_un.f_uname[i]);
31340Sstevel@tonic-gate }
31350Sstevel@tonic-gate break;
31360Sstevel@tonic-gate }
31370Sstevel@tonic-gate (void) fprintf(out, "\n");
31380Sstevel@tonic-gate }
31390Sstevel@tonic-gate
31400Sstevel@tonic-gate if (!conversion_printed) {
31412104Sjjj (void) fprintf(out, "\nFacilities:\n");
31420Sstevel@tonic-gate
31430Sstevel@tonic-gate for (i = 0; FacNames[i].c_val != -1; i++) {
31442104Sjjj (void) fprintf(out, " [%02d] %s: %3d\n", i,
31456358Snakanon FacNames[i].c_name, FacNames[i].c_val);
31460Sstevel@tonic-gate }
31470Sstevel@tonic-gate
31482104Sjjj (void) fprintf(out, "\nPriorities:\n");
31490Sstevel@tonic-gate
31500Sstevel@tonic-gate for (i = 0; PriNames[i].c_val != -1; i++) {
31512104Sjjj (void) fprintf(out, " [%02d] %s: %3d\n", i,
31526358Snakanon PriNames[i].c_name, PriNames[i].c_val);
31530Sstevel@tonic-gate }
31540Sstevel@tonic-gate
31550Sstevel@tonic-gate conversion_printed = 1;
31560Sstevel@tonic-gate }
31570Sstevel@tonic-gate
31580Sstevel@tonic-gate (void) fprintf(out, "\n\n\n\t\tPer File Statistics\n");
31590Sstevel@tonic-gate (void) fprintf(out, "%-24s\tTot\tDups\tNofwd\tErrs\n", "File");
31600Sstevel@tonic-gate (void) fprintf(out, "%-24s\t---\t----\t-----\t----\n", "----");
31610Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
31620Sstevel@tonic-gate switch (f->f_type) {
31630Sstevel@tonic-gate case F_FILE:
31640Sstevel@tonic-gate case F_TTY:
31650Sstevel@tonic-gate case F_CONSOLE:
31660Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_fname);
31670Sstevel@tonic-gate break;
31680Sstevel@tonic-gate case F_WALL:
31690Sstevel@tonic-gate (void) fprintf(out, "%-24s", TypeNames[f->f_type]);
31700Sstevel@tonic-gate break;
31710Sstevel@tonic-gate case F_FORW:
31720Sstevel@tonic-gate (void) fprintf(out, "%-24s", f->f_un.f_forw.f_hname);
31730Sstevel@tonic-gate break;
31740Sstevel@tonic-gate case F_USERS:
31750Sstevel@tonic-gate for (i = 0; i < MAXUNAMES &&
31766358Snakanon *f->f_un.f_uname[i]; i++) {
31770Sstevel@tonic-gate if (!i)
31780Sstevel@tonic-gate (void) strcpy(users,
31796358Snakanon f->f_un.f_uname[i]);
31800Sstevel@tonic-gate else {
31810Sstevel@tonic-gate (void) strcat(users, ",");
31820Sstevel@tonic-gate (void) strcat(users,
31836358Snakanon f->f_un.f_uname[i]);
31840Sstevel@tonic-gate }
31850Sstevel@tonic-gate }
31860Sstevel@tonic-gate (void) fprintf(out, "%-24s", users);
31870Sstevel@tonic-gate break;
31880Sstevel@tonic-gate }
31890Sstevel@tonic-gate (void) fprintf(out, "\t%d\t%d\t%d\t%d\n",
31906358Snakanon f->f_stat.total, f->f_stat.dups,
31916358Snakanon f->f_stat.cantfwd, f->f_stat.errs);
31920Sstevel@tonic-gate }
31930Sstevel@tonic-gate (void) fprintf(out, "\n\n");
31940Sstevel@tonic-gate if (Debug && fd == 1)
31950Sstevel@tonic-gate return;
31960Sstevel@tonic-gate (void) fclose(out);
31970Sstevel@tonic-gate }
31980Sstevel@tonic-gate
31990Sstevel@tonic-gate /*
32000Sstevel@tonic-gate * conf_init - This routine is code seperated from the
32010Sstevel@tonic-gate * init routine in order to be re-callable when we get
32020Sstevel@tonic-gate * a SIGHUP signal.
32030Sstevel@tonic-gate */
32040Sstevel@tonic-gate static void
conf_init(void)32050Sstevel@tonic-gate conf_init(void)
32060Sstevel@tonic-gate {
32070Sstevel@tonic-gate char *p;
32080Sstevel@tonic-gate int i;
32090Sstevel@tonic-gate struct filed *f;
32100Sstevel@tonic-gate char *m4argv[4];
32110Sstevel@tonic-gate int m4argc = 0;
32120Sstevel@tonic-gate conf_t cf;
32130Sstevel@tonic-gate pthread_t mythreadno;
32140Sstevel@tonic-gate
32150Sstevel@tonic-gate if (Debug) {
32160Sstevel@tonic-gate mythreadno = pthread_self();
32170Sstevel@tonic-gate }
32180Sstevel@tonic-gate
32190Sstevel@tonic-gate DPRINT1(2, "conf_init(%u): starting logger threads\n",
32206358Snakanon mythreadno);
32210Sstevel@tonic-gate
32220Sstevel@tonic-gate m4argv[m4argc++] = "m4";
32230Sstevel@tonic-gate
32240Sstevel@tonic-gate if (amiloghost() == 1) {
32250Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): I am loghost\n", mythreadno);
32260Sstevel@tonic-gate m4argv[m4argc++] = "-DLOGHOST=1";
32270Sstevel@tonic-gate }
32280Sstevel@tonic-gate
32290Sstevel@tonic-gate m4argv[m4argc++] = ConfFile;
32300Sstevel@tonic-gate m4argv[m4argc] = NULL;
32310Sstevel@tonic-gate
32320Sstevel@tonic-gate /*
32330Sstevel@tonic-gate * Make sure the configuration file and m4 exist, and then parse
32340Sstevel@tonic-gate * the configuration file with m4. If any of these fail, resort
32350Sstevel@tonic-gate * to our hardcoded fallback configuration.
32360Sstevel@tonic-gate */
32370Sstevel@tonic-gate
32380Sstevel@tonic-gate if (access(ConfFile, R_OK) == -1) {
32390Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): %s does not exist\n", mythreadno,
32406358Snakanon ConfFile);
32410Sstevel@tonic-gate logerror("can't open configuration file");
32420Sstevel@tonic-gate /* CSTYLED */
32430Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */
32440Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
32450Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]);
32460Sstevel@tonic-gate nlogs = 2;
32470Sstevel@tonic-gate goto nofile;
32480Sstevel@tonic-gate }
32490Sstevel@tonic-gate
32500Sstevel@tonic-gate if (checkm4() != 0 || conf_open(&cf, "/usr/ccs/bin/m4", m4argv) == -1) {
32510Sstevel@tonic-gate DPRINT2(1, "conf_init(%u): cannot open %s\n", mythreadno,
32526358Snakanon ConfFile);
32530Sstevel@tonic-gate /* CSTYLED */
32540Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */
32550Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
32560Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]);
32570Sstevel@tonic-gate nlogs = 2;
32580Sstevel@tonic-gate goto nofile;
32590Sstevel@tonic-gate }
32600Sstevel@tonic-gate
32610Sstevel@tonic-gate /* Count the number of lines which are not blanks or comments */
32620Sstevel@tonic-gate nlogs = 0;
32630Sstevel@tonic-gate while ((p = conf_read(&cf)) != NULL) {
32640Sstevel@tonic-gate if (p[0] != '\0' && p[0] != '#')
32650Sstevel@tonic-gate nlogs++;
32660Sstevel@tonic-gate }
32670Sstevel@tonic-gate
32680Sstevel@tonic-gate Files = (struct filed *)malloc(sizeof (struct filed) * nlogs);
32690Sstevel@tonic-gate
32700Sstevel@tonic-gate if (!Files) {
32710Sstevel@tonic-gate DPRINT1(1, "conf_init(%u): malloc failed - can't "
32726358Snakanon "allocate 'Files' array\n", mythreadno);
32730Sstevel@tonic-gate MALLOC_FAIL("loading minimum configuration");
32740Sstevel@tonic-gate /* CSTYLED */
32750Sstevel@tonic-gate Files = (struct filed *) &fallback; /*lint !e545 */
32760Sstevel@tonic-gate cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
32770Sstevel@tonic-gate cfline("*.PANIC\t*", 0, &Files[1]);
32780Sstevel@tonic-gate nlogs = 2;
32790Sstevel@tonic-gate conf_close(&cf);
32800Sstevel@tonic-gate goto nofile;
32810Sstevel@tonic-gate }
32820Sstevel@tonic-gate
32830Sstevel@tonic-gate /*
32840Sstevel@tonic-gate * Foreach line in the conf table, open that file.
32850Sstevel@tonic-gate */
32860Sstevel@tonic-gate conf_rewind(&cf);
32870Sstevel@tonic-gate f = Files;
32880Sstevel@tonic-gate i = 0;
32890Sstevel@tonic-gate while (((p = conf_read(&cf)) != NULL) && (f < &Files[nlogs])) {
32900Sstevel@tonic-gate i++;
32910Sstevel@tonic-gate /* check for end-of-section */
32920Sstevel@tonic-gate if (p[0] == '\0' || p[0] == '#')
32930Sstevel@tonic-gate continue;
32940Sstevel@tonic-gate
32950Sstevel@tonic-gate cfline(p, i, f);
32960Sstevel@tonic-gate if (f->f_type == F_UNUSED)
32970Sstevel@tonic-gate nlogs--;
32980Sstevel@tonic-gate else
32990Sstevel@tonic-gate f++;
33000Sstevel@tonic-gate }
33010Sstevel@tonic-gate
33020Sstevel@tonic-gate conf_close(&cf);
33030Sstevel@tonic-gate
33040Sstevel@tonic-gate /*
33050Sstevel@tonic-gate * See if marks are to be written to any files. If so, set up a
33060Sstevel@tonic-gate * timeout for marks.
33070Sstevel@tonic-gate */
33080Sstevel@tonic-gate nofile:
33090Sstevel@tonic-gate Marking = 0;
33100Sstevel@tonic-gate
33110Sstevel@tonic-gate /*
33120Sstevel@tonic-gate * allocate thread stacks - one for each logger thread.
33130Sstevel@tonic-gate */
33140Sstevel@tonic-gate if ((cstack_ptr = alloc_stacks(nlogs)) == NULL) {
33150Sstevel@tonic-gate logerror("alloc_stacks failed - fatal");
33160Sstevel@tonic-gate exit(1);
33170Sstevel@tonic-gate }
33180Sstevel@tonic-gate
33190Sstevel@tonic-gate /* And now one thread for each configured file */
33200Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
33210Sstevel@tonic-gate if (filed_init(f) != 0) {
33220Sstevel@tonic-gate logerror("pthread_create failed - fatal");
33230Sstevel@tonic-gate exit(1);
33240Sstevel@tonic-gate }
33250Sstevel@tonic-gate
33262104Sjjj (void) pthread_mutex_lock(&cft);
33270Sstevel@tonic-gate ++conf_threads;
33282104Sjjj (void) pthread_mutex_unlock(&cft);
33290Sstevel@tonic-gate
33300Sstevel@tonic-gate if (f->f_type != F_UNUSED &&
33316358Snakanon f->f_pmask[LOG_NFACILITIES] != NOPRI)
33320Sstevel@tonic-gate Marking = 1;
33330Sstevel@tonic-gate }
33340Sstevel@tonic-gate }
33350Sstevel@tonic-gate
33360Sstevel@tonic-gate /*
33370Sstevel@tonic-gate * filed init - initialize fields in a file descriptor struct
33380Sstevel@tonic-gate * this is called before multiple threads are running, so no mutex
33390Sstevel@tonic-gate * needs to be held at this time.
33400Sstevel@tonic-gate */
3341236Schin static int
filed_init(struct filed * f)33420Sstevel@tonic-gate filed_init(struct filed *f)
33430Sstevel@tonic-gate {
33440Sstevel@tonic-gate pthread_attr_t stack_attr;
33450Sstevel@tonic-gate pthread_t mythreadno;
33460Sstevel@tonic-gate
33470Sstevel@tonic-gate if (Debug) {
33480Sstevel@tonic-gate mythreadno = pthread_self();
33490Sstevel@tonic-gate }
33500Sstevel@tonic-gate
33510Sstevel@tonic-gate if (pthread_mutex_init(&f->filed_mutex, NULL) != 0) {
33520Sstevel@tonic-gate logerror("pthread_mutex_init failed");
33530Sstevel@tonic-gate return (-1);
33540Sstevel@tonic-gate }
33550Sstevel@tonic-gate
33560Sstevel@tonic-gate DPRINT2(5, "filed_init(%u): dataq_init for queue %p\n",
33576358Snakanon mythreadno, (void *)&f->f_queue);
33580Sstevel@tonic-gate (void) dataq_init(&f->f_queue);
33590Sstevel@tonic-gate
33600Sstevel@tonic-gate if (pthread_attr_init(&stack_attr) != 0) {
33610Sstevel@tonic-gate logerror("pthread_attr_init failed");
33620Sstevel@tonic-gate return (-1);
33630Sstevel@tonic-gate }
33640Sstevel@tonic-gate
33650Sstevel@tonic-gate (void) pthread_attr_setstacksize(&stack_attr, stacksize);
33660Sstevel@tonic-gate (void) pthread_attr_setstackaddr(&stack_attr, cstack_ptr);
33670Sstevel@tonic-gate cstack_ptr += stacksize + redzonesize;
33680Sstevel@tonic-gate
33690Sstevel@tonic-gate f->f_msgflag = 0;
33700Sstevel@tonic-gate f->f_prevmsg.msg[0] = '\0';
33710Sstevel@tonic-gate f->f_prevmsg.flags = 0;
33720Sstevel@tonic-gate f->f_prevmsg.pri = 0;
33730Sstevel@tonic-gate f->f_prevmsg.host[0] = '\0';
33740Sstevel@tonic-gate
33750Sstevel@tonic-gate f->f_current.msg[0] = '\0';
33760Sstevel@tonic-gate f->f_current.flags = 0;
33770Sstevel@tonic-gate f->f_current.pri = 0;
33780Sstevel@tonic-gate f->f_current.host[0] = '\0';
33790Sstevel@tonic-gate
33800Sstevel@tonic-gate f->f_prevcount = 0;
33810Sstevel@tonic-gate
33820Sstevel@tonic-gate f->f_stat.flag = 0;
33830Sstevel@tonic-gate f->f_stat.total = 0;
33840Sstevel@tonic-gate f->f_stat.dups = 0;
33850Sstevel@tonic-gate f->f_stat.cantfwd = 0;
33860Sstevel@tonic-gate f->f_stat.errs = 0;
33870Sstevel@tonic-gate
33880Sstevel@tonic-gate if (pthread_create(&f->f_thread, NULL, logit, (void *)f) != 0) {
33890Sstevel@tonic-gate logerror("pthread_create failed");
33902104Sjjj (void) pthread_attr_destroy(&stack_attr);
33910Sstevel@tonic-gate return (-1);
33920Sstevel@tonic-gate }
33930Sstevel@tonic-gate
33942104Sjjj (void) pthread_attr_destroy(&stack_attr);
33950Sstevel@tonic-gate return (0);
33960Sstevel@tonic-gate }
33970Sstevel@tonic-gate
33980Sstevel@tonic-gate
33990Sstevel@tonic-gate /*
34000Sstevel@tonic-gate * Crack a configuration file line
34010Sstevel@tonic-gate */
34020Sstevel@tonic-gate static void
cfline(char * line,int lineno,struct filed * f)34030Sstevel@tonic-gate cfline(char *line, int lineno, struct filed *f)
34040Sstevel@tonic-gate {
34050Sstevel@tonic-gate char *p;
34060Sstevel@tonic-gate char *q;
34070Sstevel@tonic-gate int i;
34080Sstevel@tonic-gate char *bp;
34090Sstevel@tonic-gate int pri;
34100Sstevel@tonic-gate char buf[MAXLINE];
34110Sstevel@tonic-gate char ebuf[SYS_NMLN+1+40];
34120Sstevel@tonic-gate mode_t fmode, omode = O_WRONLY|O_APPEND|O_NOCTTY;
34130Sstevel@tonic-gate struct stat64 sbuf;
34140Sstevel@tonic-gate pthread_t mythreadno;
34150Sstevel@tonic-gate
34160Sstevel@tonic-gate if (Debug) {
34170Sstevel@tonic-gate mythreadno = pthread_self();
34180Sstevel@tonic-gate }
34190Sstevel@tonic-gate
34200Sstevel@tonic-gate DPRINT2(1, "cfline(%u): (%s)\n", mythreadno, line);
34210Sstevel@tonic-gate
3422634Sdp errno = 0; /* keep errno related stuff out of logerror messages */
34230Sstevel@tonic-gate
34240Sstevel@tonic-gate /* clear out file entry */
34250Sstevel@tonic-gate bzero((char *)f, sizeof (*f));
34260Sstevel@tonic-gate for (i = 0; i <= LOG_NFACILITIES; i++)
34270Sstevel@tonic-gate f->f_pmask[i] = NOPRI;
34280Sstevel@tonic-gate
34290Sstevel@tonic-gate /* scan through the list of selectors */
34300Sstevel@tonic-gate for (p = line; *p && *p != '\t'; ) {
34310Sstevel@tonic-gate
34320Sstevel@tonic-gate /* find the end of this facility name list */
34330Sstevel@tonic-gate for (q = p; *q && *q != '\t' && *q++ != '.'; )
34340Sstevel@tonic-gate continue;
34350Sstevel@tonic-gate
34360Sstevel@tonic-gate /* collect priority name */
34370Sstevel@tonic-gate for (bp = buf; *q && !strchr("\t,;", *q); )
34380Sstevel@tonic-gate *bp++ = *q++;
34390Sstevel@tonic-gate *bp = '\0';
34400Sstevel@tonic-gate
34410Sstevel@tonic-gate /* skip cruft */
34420Sstevel@tonic-gate while (strchr(", ;", *q))
34430Sstevel@tonic-gate q++;
34440Sstevel@tonic-gate
34450Sstevel@tonic-gate /* decode priority name */
34460Sstevel@tonic-gate pri = decode(buf, PriNames);
34470Sstevel@tonic-gate if (pri < 0) {
34480Sstevel@tonic-gate logerror("line %d: unknown priority name \"%s\"",
34496358Snakanon lineno, buf);
34500Sstevel@tonic-gate return;
34510Sstevel@tonic-gate }
34520Sstevel@tonic-gate
34530Sstevel@tonic-gate /* scan facilities */
34540Sstevel@tonic-gate while (*p && !strchr("\t.;", *p)) {
34550Sstevel@tonic-gate for (bp = buf; *p && !strchr("\t,;.", *p); )
34560Sstevel@tonic-gate *bp++ = *p++;
34570Sstevel@tonic-gate *bp = '\0';
34580Sstevel@tonic-gate if (*buf == '*')
34590Sstevel@tonic-gate for (i = 0; i < LOG_NFACILITIES; i++)
34600Sstevel@tonic-gate f->f_pmask[i] = (uchar_t)pri;
34610Sstevel@tonic-gate else {
34620Sstevel@tonic-gate i = decode(buf, FacNames);
34630Sstevel@tonic-gate if (i < 0) {
34640Sstevel@tonic-gate logerror("line %d: unknown facility"
34656358Snakanon " name \"%s\"", lineno, buf);
34660Sstevel@tonic-gate return;
34670Sstevel@tonic-gate }
34680Sstevel@tonic-gate f->f_pmask[i >> 3] = (uchar_t)pri;
34690Sstevel@tonic-gate }
34700Sstevel@tonic-gate while (*p == ',' || *p == ' ')
34710Sstevel@tonic-gate p++;
34720Sstevel@tonic-gate }
34730Sstevel@tonic-gate
34740Sstevel@tonic-gate p = q;
34750Sstevel@tonic-gate }
34760Sstevel@tonic-gate
34770Sstevel@tonic-gate /* skip to action part */
34780Sstevel@tonic-gate while (*p == '\t' || *p == ' ')
34790Sstevel@tonic-gate p++;
34800Sstevel@tonic-gate
34810Sstevel@tonic-gate switch (*p) {
34820Sstevel@tonic-gate case '\0':
34830Sstevel@tonic-gate errno = 0;
34840Sstevel@tonic-gate logerror("line %d: no action part", lineno);
34850Sstevel@tonic-gate break;
34860Sstevel@tonic-gate
34870Sstevel@tonic-gate case '@':
34880Sstevel@tonic-gate (void) strlcpy(f->f_un.f_forw.f_hname, ++p, SYS_NMLN);
34892104Sjjj if (logforward(f, ebuf, sizeof (ebuf)) != 0) {
34900Sstevel@tonic-gate logerror("line %d: %s", lineno, ebuf);
34910Sstevel@tonic-gate break;
34920Sstevel@tonic-gate }
34930Sstevel@tonic-gate f->f_type = F_FORW;
34940Sstevel@tonic-gate break;
34950Sstevel@tonic-gate
34960Sstevel@tonic-gate case '/':
34970Sstevel@tonic-gate (void) strlcpy(f->f_un.f_fname, p, MAXPATHLEN);
34980Sstevel@tonic-gate if (stat64(p, &sbuf) < 0) {
34990Sstevel@tonic-gate logerror(p);
35000Sstevel@tonic-gate break;
35010Sstevel@tonic-gate }
35020Sstevel@tonic-gate /*
35030Sstevel@tonic-gate * don't block trying to open a pipe
35040Sstevel@tonic-gate * with no reader on the other end
35050Sstevel@tonic-gate */
35060Sstevel@tonic-gate fmode = 0; /* reset each pass */
35070Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode))
35080Sstevel@tonic-gate fmode = O_NONBLOCK;
35090Sstevel@tonic-gate
35100Sstevel@tonic-gate f->f_file = open64(p, omode|fmode);
35110Sstevel@tonic-gate if (f->f_file < 0) {
35120Sstevel@tonic-gate if (fmode && errno == ENXIO) {
35130Sstevel@tonic-gate errno = 0;
35140Sstevel@tonic-gate logerror("%s - no reader", p);
35150Sstevel@tonic-gate } else
35160Sstevel@tonic-gate logerror(p);
35170Sstevel@tonic-gate break;
35180Sstevel@tonic-gate }
35190Sstevel@tonic-gate
35200Sstevel@tonic-gate /*
35210Sstevel@tonic-gate * Fifos are initially opened NONBLOCK
35220Sstevel@tonic-gate * to insure we don't hang, but once
35230Sstevel@tonic-gate * we are open, we need to change the
35240Sstevel@tonic-gate * behavior back to blocking, otherwise
35250Sstevel@tonic-gate * we may get write errors, and the log
35260Sstevel@tonic-gate * will get closed down the line.
35270Sstevel@tonic-gate */
35280Sstevel@tonic-gate if (S_ISFIFO(sbuf.st_mode))
35290Sstevel@tonic-gate (void) fcntl(f->f_file, F_SETFL, omode);
35300Sstevel@tonic-gate
35310Sstevel@tonic-gate if (isatty(f->f_file)) {
35320Sstevel@tonic-gate f->f_type = F_TTY;
35330Sstevel@tonic-gate untty();
35340Sstevel@tonic-gate } else
35350Sstevel@tonic-gate f->f_type = F_FILE;
35360Sstevel@tonic-gate
35370Sstevel@tonic-gate if ((strcmp(p, ctty) == 0) || (strcmp(p, sysmsg) == 0))
35380Sstevel@tonic-gate f->f_type = F_CONSOLE;
35390Sstevel@tonic-gate break;
35400Sstevel@tonic-gate
35410Sstevel@tonic-gate case '*':
35420Sstevel@tonic-gate f->f_type = F_WALL;
35430Sstevel@tonic-gate break;
35440Sstevel@tonic-gate
35450Sstevel@tonic-gate default:
35460Sstevel@tonic-gate for (i = 0; i < MAXUNAMES && *p; i++) {
35470Sstevel@tonic-gate for (q = p; *q && *q != ','; )
35480Sstevel@tonic-gate q++;
35490Sstevel@tonic-gate (void) strlcpy(f->f_un.f_uname[i], p, UNAMESZ);
35500Sstevel@tonic-gate if ((q - p) > UNAMESZ)
35510Sstevel@tonic-gate f->f_un.f_uname[i][UNAMESZ] = '\0';
35520Sstevel@tonic-gate else
35530Sstevel@tonic-gate f->f_un.f_uname[i][q - p] = '\0';
35540Sstevel@tonic-gate while (*q == ',' || *q == ' ')
35550Sstevel@tonic-gate q++;
35560Sstevel@tonic-gate p = q;
35570Sstevel@tonic-gate }
35580Sstevel@tonic-gate f->f_type = F_USERS;
35590Sstevel@tonic-gate break;
35600Sstevel@tonic-gate }
35610Sstevel@tonic-gate f->f_orig_type = f->f_type;
35620Sstevel@tonic-gate }
35630Sstevel@tonic-gate
35640Sstevel@tonic-gate
35650Sstevel@tonic-gate /*
35660Sstevel@tonic-gate * Decode a symbolic name to a numeric value
35670Sstevel@tonic-gate */
35680Sstevel@tonic-gate static int
decode(char * name,struct code * codetab)35690Sstevel@tonic-gate decode(char *name, struct code *codetab)
35700Sstevel@tonic-gate {
35710Sstevel@tonic-gate struct code *c;
35720Sstevel@tonic-gate char *p;
35730Sstevel@tonic-gate char buf[40];
35740Sstevel@tonic-gate
35750Sstevel@tonic-gate if (isdigit(*name))
35760Sstevel@tonic-gate return (atoi(name));
35770Sstevel@tonic-gate
35780Sstevel@tonic-gate (void) strncpy(buf, name, sizeof (buf) - 1);
35790Sstevel@tonic-gate for (p = buf; *p; p++)
35800Sstevel@tonic-gate if (isupper(*p))
35810Sstevel@tonic-gate *p = tolower(*p);
35820Sstevel@tonic-gate for (c = codetab; c->c_name; c++)
35830Sstevel@tonic-gate if (!(strcmp(buf, c->c_name)))
35840Sstevel@tonic-gate return (c->c_val);
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate return (-1);
35870Sstevel@tonic-gate }
35880Sstevel@tonic-gate
35890Sstevel@tonic-gate static int
ismyaddr(struct netbuf * nbp)35900Sstevel@tonic-gate ismyaddr(struct netbuf *nbp)
35910Sstevel@tonic-gate {
35920Sstevel@tonic-gate int i;
35930Sstevel@tonic-gate
35940Sstevel@tonic-gate if (nbp == NULL)
35950Sstevel@tonic-gate return (0);
35960Sstevel@tonic-gate
35970Sstevel@tonic-gate for (i = 1; i < Ninputs; i++) {
35980Sstevel@tonic-gate if (same_addr(nbp, Myaddrs[i]))
35990Sstevel@tonic-gate return (1);
36000Sstevel@tonic-gate }
36010Sstevel@tonic-gate return (0);
36020Sstevel@tonic-gate }
36030Sstevel@tonic-gate
36040Sstevel@tonic-gate static void
getnets(void)36050Sstevel@tonic-gate getnets(void)
36060Sstevel@tonic-gate {
36070Sstevel@tonic-gate struct nd_hostserv hs;
36080Sstevel@tonic-gate struct netconfig *ncp;
36090Sstevel@tonic-gate struct nd_addrlist *nap;
36100Sstevel@tonic-gate struct netbuf *nbp;
36110Sstevel@tonic-gate int i, inputs;
36120Sstevel@tonic-gate void *handle;
36130Sstevel@tonic-gate char *uap;
36140Sstevel@tonic-gate pthread_t mythreadno;
36150Sstevel@tonic-gate
36160Sstevel@tonic-gate if (Debug) {
36170Sstevel@tonic-gate mythreadno = pthread_self();
36180Sstevel@tonic-gate }
36190Sstevel@tonic-gate
36200Sstevel@tonic-gate if (turnoff) {
36210Sstevel@tonic-gate DPRINT1(1, "getnets(%u): network is being turned off\n",
36226358Snakanon mythreadno);
36230Sstevel@tonic-gate return;
36240Sstevel@tonic-gate }
36250Sstevel@tonic-gate
36260Sstevel@tonic-gate hs.h_host = HOST_SELF;
36270Sstevel@tonic-gate hs.h_serv = "syslog";
36280Sstevel@tonic-gate
36290Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) {
36300Sstevel@tonic-gate return;
36310Sstevel@tonic-gate }
36320Sstevel@tonic-gate
36330Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) {
36340Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) {
36350Sstevel@tonic-gate continue;
36360Sstevel@tonic-gate }
36370Sstevel@tonic-gate
36380Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) {
36390Sstevel@tonic-gate continue;
36400Sstevel@tonic-gate }
36410Sstevel@tonic-gate
36420Sstevel@tonic-gate if (nap == NULL || nap->n_cnt <= 0) {
36430Sstevel@tonic-gate DPRINT1(1, "getnets(%u): found no address\n",
36446358Snakanon mythreadno);
36450Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
36460Sstevel@tonic-gate continue;
36470Sstevel@tonic-gate }
36480Sstevel@tonic-gate
36490Sstevel@tonic-gate if (Debug) {
36500Sstevel@tonic-gate DPRINT2(1, "getnets(%u): found %d addresses",
36516358Snakanon mythreadno, nap->n_cnt);
36520Sstevel@tonic-gate DPRINT0(1, ", they are: ");
36530Sstevel@tonic-gate nbp = nap->n_addrs;
36540Sstevel@tonic-gate
36550Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) {
36560Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
36570Sstevel@tonic-gate DPRINT1(1, "%s ", uap);
36580Sstevel@tonic-gate free(uap);
36590Sstevel@tonic-gate }
36600Sstevel@tonic-gate nbp++;
36610Sstevel@tonic-gate }
36620Sstevel@tonic-gate
36630Sstevel@tonic-gate DPRINT0(1, "\n");
36640Sstevel@tonic-gate }
36650Sstevel@tonic-gate
36660Sstevel@tonic-gate inputs = Ninputs + nap->n_cnt;
36670Sstevel@tonic-gate
36680Sstevel@tonic-gate Nfd = realloc(Nfd, inputs * sizeof (struct pollfd));
36690Sstevel@tonic-gate Ncf = realloc(Ncf, inputs * sizeof (struct netconfig));
36700Sstevel@tonic-gate Myaddrs = realloc(Myaddrs, inputs * sizeof (struct netbuf *));
36710Sstevel@tonic-gate Udp = realloc(Udp, inputs * sizeof (struct t_unitdata *));
36720Sstevel@tonic-gate Errp = realloc(Errp, inputs * sizeof (struct t_uderr *));
36730Sstevel@tonic-gate
36740Sstevel@tonic-gate /*
36750Sstevel@tonic-gate * all malloc failures here are fatal
36760Sstevel@tonic-gate */
36770Sstevel@tonic-gate if (Nfd == NULL || Ncf == NULL || Myaddrs == NULL ||
36786358Snakanon Udp == NULL || Errp == NULL) {
36790Sstevel@tonic-gate MALLOC_FAIL_EXIT;
36800Sstevel@tonic-gate }
36810Sstevel@tonic-gate
36820Sstevel@tonic-gate nbp = nap->n_addrs;
36830Sstevel@tonic-gate
36840Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++, nbp++) {
36850Sstevel@tonic-gate char ebuf[128];
36860Sstevel@tonic-gate
36870Sstevel@tonic-gate if (addnet(ncp, nbp) == 0) {
36880Sstevel@tonic-gate /* no error */
36890Sstevel@tonic-gate continue;
36900Sstevel@tonic-gate }
36910Sstevel@tonic-gate
36920Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to configure syslog port");
36930Sstevel@tonic-gate
36940Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
36950Sstevel@tonic-gate size_t l = strlen(ebuf);
36960Sstevel@tonic-gate (void) snprintf(ebuf + l, sizeof (ebuf) - l,
36976358Snakanon " for %s", uap);
36980Sstevel@tonic-gate }
36990Sstevel@tonic-gate
37000Sstevel@tonic-gate DPRINT2(1, "getnets(%u): %s",
37016358Snakanon mythreadno, ebuf);
37020Sstevel@tonic-gate
37030Sstevel@tonic-gate if (uap) {
37040Sstevel@tonic-gate free(uap);
37050Sstevel@tonic-gate }
37060Sstevel@tonic-gate
37070Sstevel@tonic-gate logerror(ebuf);
37080Sstevel@tonic-gate /*
37090Sstevel@tonic-gate * Here maybe syslogd can quit. However, syslogd
37100Sstevel@tonic-gate * has been ignoring this error and keep running.
37110Sstevel@tonic-gate * So we won't break it.
37120Sstevel@tonic-gate */
37130Sstevel@tonic-gate }
37140Sstevel@tonic-gate
37150Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
37160Sstevel@tonic-gate }
37170Sstevel@tonic-gate
37180Sstevel@tonic-gate (void) endnetconfig(handle);
37190Sstevel@tonic-gate }
37200Sstevel@tonic-gate
37210Sstevel@tonic-gate /*
37220Sstevel@tonic-gate * Open the network device, and allocate necessary resources.
37230Sstevel@tonic-gate * Myaddrs will also be filled, so that we can call ismyaddr() before
37240Sstevel@tonic-gate * being bound to the network.
37250Sstevel@tonic-gate */
37260Sstevel@tonic-gate static int
addnet(struct netconfig * ncp,struct netbuf * nbp)37270Sstevel@tonic-gate addnet(struct netconfig *ncp, struct netbuf *nbp)
37280Sstevel@tonic-gate {
37290Sstevel@tonic-gate int fd;
37300Sstevel@tonic-gate struct netbuf *bp;
37310Sstevel@tonic-gate
37320Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL);
37330Sstevel@tonic-gate
37340Sstevel@tonic-gate if (fd < 0) {
37350Sstevel@tonic-gate return (1);
37360Sstevel@tonic-gate }
37370Sstevel@tonic-gate
37380Sstevel@tonic-gate (void) memcpy(&Ncf[Ninputs], ncp, sizeof (struct netconfig));
37390Sstevel@tonic-gate
37400Sstevel@tonic-gate /*LINTED*/
37410Sstevel@tonic-gate Udp[Ninputs] = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR);
37420Sstevel@tonic-gate
37430Sstevel@tonic-gate if (Udp[Ninputs] == NULL) {
37442104Sjjj (void) t_close(fd);
37450Sstevel@tonic-gate return (1);
37460Sstevel@tonic-gate }
37470Sstevel@tonic-gate
37480Sstevel@tonic-gate /*LINTED*/
37490Sstevel@tonic-gate Errp[Ninputs] = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ADDR);
37500Sstevel@tonic-gate
37510Sstevel@tonic-gate if (Errp[Ninputs] == NULL) {
37522104Sjjj (void) t_close(fd);
37532104Sjjj (void) t_free((char *)Udp[Ninputs], T_UNITDATA);
37540Sstevel@tonic-gate return (1);
37550Sstevel@tonic-gate }
37560Sstevel@tonic-gate
37570Sstevel@tonic-gate if ((bp = malloc(sizeof (struct netbuf))) == NULL ||
37586358Snakanon (bp->buf = malloc(nbp->len)) == NULL) {
37590Sstevel@tonic-gate MALLOC_FAIL("allocating address buffer");
37602104Sjjj (void) t_close(fd);
37612104Sjjj (void) t_free((char *)Udp[Ninputs], T_UNITDATA);
37622104Sjjj (void) t_free((char *)Errp[Ninputs], T_UDERROR);
37630Sstevel@tonic-gate
37640Sstevel@tonic-gate if (bp) {
37650Sstevel@tonic-gate free(bp);
37660Sstevel@tonic-gate }
37670Sstevel@tonic-gate
37680Sstevel@tonic-gate return (1);
37690Sstevel@tonic-gate }
37700Sstevel@tonic-gate
37710Sstevel@tonic-gate bp->len = nbp->len;
37720Sstevel@tonic-gate (void) memcpy(bp->buf, nbp->buf, nbp->len);
37730Sstevel@tonic-gate Myaddrs[Ninputs] = bp;
37740Sstevel@tonic-gate
37750Sstevel@tonic-gate Nfd[Ninputs].fd = fd;
37760Sstevel@tonic-gate Nfd[Ninputs].events = POLLIN;
37770Sstevel@tonic-gate Ninputs++;
37780Sstevel@tonic-gate return (0);
37790Sstevel@tonic-gate }
37800Sstevel@tonic-gate
37810Sstevel@tonic-gate /*
37820Sstevel@tonic-gate * Allocate UDP buffer to minimize packet loss.
37830Sstevel@tonic-gate */
37840Sstevel@tonic-gate static void
set_udp_buffer(int fd)37850Sstevel@tonic-gate set_udp_buffer(int fd)
37860Sstevel@tonic-gate {
37870Sstevel@tonic-gate struct t_optmgmt req, resp;
37880Sstevel@tonic-gate struct opthdr *opt;
37890Sstevel@tonic-gate size_t optsize, bsize = 256 * 1024;
37900Sstevel@tonic-gate pthread_t mythreadno;
37910Sstevel@tonic-gate
37920Sstevel@tonic-gate if (Debug) {
37930Sstevel@tonic-gate mythreadno = pthread_self();
37940Sstevel@tonic-gate }
37950Sstevel@tonic-gate
37960Sstevel@tonic-gate optsize = sizeof (struct opthdr) + sizeof (int);
37970Sstevel@tonic-gate if ((opt = malloc(optsize)) == NULL) {
37980Sstevel@tonic-gate MALLOC_FAIL("will have no udp buffer");
37990Sstevel@tonic-gate return;
38000Sstevel@tonic-gate }
38010Sstevel@tonic-gate opt->level = SOL_SOCKET;
38020Sstevel@tonic-gate opt->name = SO_RCVBUF;
38030Sstevel@tonic-gate opt->len = sizeof (int);
38040Sstevel@tonic-gate *(int *)(opt + 1) = bsize;
38050Sstevel@tonic-gate
38060Sstevel@tonic-gate req.flags = T_NEGOTIATE;
38070Sstevel@tonic-gate req.opt.len = optsize;
38080Sstevel@tonic-gate req.opt.buf = (char *)opt;
38090Sstevel@tonic-gate
38100Sstevel@tonic-gate resp.flags = 0;
38110Sstevel@tonic-gate resp.opt.maxlen = optsize;
38120Sstevel@tonic-gate resp.opt.buf = (char *)opt;
38130Sstevel@tonic-gate
38140Sstevel@tonic-gate while (t_optmgmt(fd, &req, &resp) == -1 || resp.flags != T_SUCCESS) {
38150Sstevel@tonic-gate if (t_errno != TSYSERR || errno != ENOBUFS) {
38160Sstevel@tonic-gate bsize = 0;
38170Sstevel@tonic-gate break;
38180Sstevel@tonic-gate }
38190Sstevel@tonic-gate bsize >>= 1;
38200Sstevel@tonic-gate if (bsize < 8192) {
38210Sstevel@tonic-gate break;
38220Sstevel@tonic-gate }
38230Sstevel@tonic-gate *(int *)(opt + 1) = bsize;
38240Sstevel@tonic-gate }
38250Sstevel@tonic-gate if (bsize == 0) {
38260Sstevel@tonic-gate logerror("failed to allocate UDP buffer");
38270Sstevel@tonic-gate }
38280Sstevel@tonic-gate DPRINT3(1, "set_udp_buffer(%u): allocate %d for fd %d\n",
38296358Snakanon mythreadno, bsize, fd);
38300Sstevel@tonic-gate free(opt);
38310Sstevel@tonic-gate }
38320Sstevel@tonic-gate
38330Sstevel@tonic-gate /*
38340Sstevel@tonic-gate * Attach the network, and allocate UDP buffer for the interface.
38350Sstevel@tonic-gate */
38360Sstevel@tonic-gate static void
bindnet(void)38370Sstevel@tonic-gate bindnet(void)
38380Sstevel@tonic-gate {
38390Sstevel@tonic-gate struct t_bind bind, *bound;
38400Sstevel@tonic-gate int cnt, i;
38410Sstevel@tonic-gate char *uap;
38420Sstevel@tonic-gate pthread_t mythreadno;
38430Sstevel@tonic-gate
38440Sstevel@tonic-gate if (Debug) {
38450Sstevel@tonic-gate mythreadno = pthread_self();
38460Sstevel@tonic-gate }
38470Sstevel@tonic-gate
38480Sstevel@tonic-gate cnt = 0;
38490Sstevel@tonic-gate
38500Sstevel@tonic-gate while (cnt < Ninputs) {
38510Sstevel@tonic-gate char ebuf[128];
38520Sstevel@tonic-gate
38530Sstevel@tonic-gate /*LINTED*/
38540Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(Nfd[cnt].fd, T_BIND, T_ADDR);
38550Sstevel@tonic-gate bind.addr = *Myaddrs[cnt];
38560Sstevel@tonic-gate bind.qlen = 0;
38570Sstevel@tonic-gate
38580Sstevel@tonic-gate if (t_bind(Nfd[cnt].fd, &bind, bound) == 0) {
38590Sstevel@tonic-gate if (same_addr(&bind.addr, &bound->addr)) {
38602104Sjjj (void) t_free((char *)bound, T_BIND);
38610Sstevel@tonic-gate set_udp_buffer(Nfd[cnt].fd);
38620Sstevel@tonic-gate cnt++;
38630Sstevel@tonic-gate continue;
38640Sstevel@tonic-gate }
38650Sstevel@tonic-gate }
38660Sstevel@tonic-gate
38670Sstevel@tonic-gate /* failed to bind port */
38682104Sjjj (void) t_free((char *)bound, T_BIND);
38690Sstevel@tonic-gate
38700Sstevel@tonic-gate (void) strcpy(ebuf, "Unable to bind syslog port");
38710Sstevel@tonic-gate
38720Sstevel@tonic-gate uap = taddr2uaddr(&Ncf[cnt], Myaddrs[cnt]);
38730Sstevel@tonic-gate if (uap) {
38740Sstevel@tonic-gate i = strlen(ebuf);
38750Sstevel@tonic-gate (void) snprintf(ebuf + i, sizeof (ebuf) - i,
38766358Snakanon " for %s", uap);
38770Sstevel@tonic-gate }
38780Sstevel@tonic-gate
38790Sstevel@tonic-gate DPRINT2(1, "bindnet(%u): failed to bind port (%s)\n",
38806358Snakanon mythreadno, uap ? uap : "<unknown>");
38810Sstevel@tonic-gate
38820Sstevel@tonic-gate if (uap) {
38830Sstevel@tonic-gate free(uap);
38840Sstevel@tonic-gate }
38850Sstevel@tonic-gate
38860Sstevel@tonic-gate errno = 0;
38870Sstevel@tonic-gate logerror(ebuf);
38880Sstevel@tonic-gate
38892104Sjjj (void) t_close(Nfd[cnt].fd);
38900Sstevel@tonic-gate free(Myaddrs[cnt]->buf);
38910Sstevel@tonic-gate free(Myaddrs[cnt]);
38922104Sjjj (void) t_free((char *)Udp[cnt], T_UNITDATA);
38932104Sjjj (void) t_free((char *)Errp[cnt], T_UDERROR);
38940Sstevel@tonic-gate
38950Sstevel@tonic-gate for (i = cnt; i < (Ninputs-1); i++) {
38960Sstevel@tonic-gate Nfd[i] = Nfd[i + 1];
38970Sstevel@tonic-gate Ncf[i] = Ncf[i + 1];
38980Sstevel@tonic-gate Myaddrs[i] = Myaddrs[i + 1];
38990Sstevel@tonic-gate Udp[i] = Udp[i + 1];
39000Sstevel@tonic-gate Errp[i] = Errp[i + 1];
39010Sstevel@tonic-gate }
39020Sstevel@tonic-gate
39030Sstevel@tonic-gate Ninputs--;
39040Sstevel@tonic-gate }
39050Sstevel@tonic-gate }
39060Sstevel@tonic-gate
39070Sstevel@tonic-gate static int
logforward(struct filed * f,char * ebuf,size_t elen)39082104Sjjj logforward(struct filed *f, char *ebuf, size_t elen)
39090Sstevel@tonic-gate {
39100Sstevel@tonic-gate struct nd_hostserv hs;
39110Sstevel@tonic-gate struct netbuf *nbp;
39120Sstevel@tonic-gate struct netconfig *ncp;
39130Sstevel@tonic-gate struct nd_addrlist *nap;
39140Sstevel@tonic-gate void *handle;
39150Sstevel@tonic-gate char *hp;
39160Sstevel@tonic-gate
39170Sstevel@tonic-gate hp = f->f_un.f_forw.f_hname;
39180Sstevel@tonic-gate hs.h_host = hp;
39190Sstevel@tonic-gate hs.h_serv = "syslog";
39200Sstevel@tonic-gate
39210Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) {
39222104Sjjj (void) strlcpy(ebuf,
39236358Snakanon "unable to rewind the netconfig database", elen);
39240Sstevel@tonic-gate errno = 0;
39250Sstevel@tonic-gate return (-1);
39260Sstevel@tonic-gate }
39270Sstevel@tonic-gate nap = (struct nd_addrlist *)NULL;
39280Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) {
39290Sstevel@tonic-gate if (ncp->nc_semantics == NC_TPI_CLTS) {
39300Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) == 0) {
39310Sstevel@tonic-gate if (!nap)
39320Sstevel@tonic-gate continue;
39330Sstevel@tonic-gate nbp = nap->n_addrs;
39340Sstevel@tonic-gate break;
39350Sstevel@tonic-gate }
39360Sstevel@tonic-gate }
39370Sstevel@tonic-gate }
39380Sstevel@tonic-gate if (ncp == NULL) {
39392104Sjjj (void) endnetconfig(handle);
39402104Sjjj (void) snprintf(ebuf, elen,
39412104Sjjj "WARNING: %s could not be resolved", hp);
39420Sstevel@tonic-gate errno = 0;
39430Sstevel@tonic-gate return (-1);
39440Sstevel@tonic-gate }
39450Sstevel@tonic-gate if (nap == (struct nd_addrlist *)NULL) {
39462104Sjjj (void) endnetconfig(handle);
39472104Sjjj (void) snprintf(ebuf, elen, "unknown host %s", hp);
39480Sstevel@tonic-gate errno = 0;
39490Sstevel@tonic-gate return (-1);
39500Sstevel@tonic-gate }
39510Sstevel@tonic-gate /* CSTYLED */
39520Sstevel@tonic-gate if (ismyaddr(nbp)) { /*lint !e644 */
39530Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
39542104Sjjj (void) endnetconfig(handle);
39552104Sjjj (void) snprintf(ebuf, elen,
39562104Sjjj "host %s is this host - logging loop", hp);
39570Sstevel@tonic-gate errno = 0;
39580Sstevel@tonic-gate return (-1);
39590Sstevel@tonic-gate }
39600Sstevel@tonic-gate f->f_un.f_forw.f_addr.buf = malloc(nbp->len);
39610Sstevel@tonic-gate if (f->f_un.f_forw.f_addr.buf == NULL) {
39620Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
39632104Sjjj (void) endnetconfig(handle);
39642104Sjjj (void) strlcpy(ebuf, "malloc failed", elen);
39650Sstevel@tonic-gate return (-1);
39660Sstevel@tonic-gate }
39670Sstevel@tonic-gate bcopy(nbp->buf, f->f_un.f_forw.f_addr.buf, nbp->len);
39680Sstevel@tonic-gate f->f_un.f_forw.f_addr.len = nbp->len;
39690Sstevel@tonic-gate f->f_file = t_open(ncp->nc_device, O_RDWR, NULL);
39700Sstevel@tonic-gate if (f->f_file < 0) {
39710Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
39722104Sjjj (void) endnetconfig(handle);
39730Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf);
39742104Sjjj (void) strlcpy(ebuf, "t_open", elen);
39750Sstevel@tonic-gate return (-1);
39760Sstevel@tonic-gate }
39770Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
39782104Sjjj (void) endnetconfig(handle);
39790Sstevel@tonic-gate if (t_bind(f->f_file, NULL, NULL) < 0) {
39802104Sjjj (void) strlcpy(ebuf, "t_bind", elen);
39810Sstevel@tonic-gate free(f->f_un.f_forw.f_addr.buf);
39822104Sjjj (void) t_close(f->f_file);
39830Sstevel@tonic-gate return (-1);
39840Sstevel@tonic-gate }
39850Sstevel@tonic-gate return (0);
39860Sstevel@tonic-gate }
39870Sstevel@tonic-gate
39880Sstevel@tonic-gate static int
amiloghost(void)39890Sstevel@tonic-gate amiloghost(void)
39900Sstevel@tonic-gate {
39910Sstevel@tonic-gate struct nd_hostserv hs;
39920Sstevel@tonic-gate struct netconfig *ncp;
39930Sstevel@tonic-gate struct nd_addrlist *nap;
39940Sstevel@tonic-gate struct netbuf *nbp;
39950Sstevel@tonic-gate int i, fd;
39960Sstevel@tonic-gate void *handle;
39970Sstevel@tonic-gate char *uap;
39980Sstevel@tonic-gate struct t_bind bind, *bound;
39990Sstevel@tonic-gate pthread_t mythreadno;
40000Sstevel@tonic-gate
40010Sstevel@tonic-gate if (Debug) {
40020Sstevel@tonic-gate mythreadno = pthread_self();
40030Sstevel@tonic-gate }
40040Sstevel@tonic-gate
40050Sstevel@tonic-gate /*
40060Sstevel@tonic-gate * we need to know if we are running on the loghost. This is
40070Sstevel@tonic-gate * checked by binding to the address associated with "loghost"
40080Sstevel@tonic-gate * and "syslogd" service over the connectionless transport
40090Sstevel@tonic-gate */
40100Sstevel@tonic-gate hs.h_host = "loghost";
40110Sstevel@tonic-gate hs.h_serv = "syslog";
40120Sstevel@tonic-gate
40130Sstevel@tonic-gate if ((handle = setnetconfig()) == NULL) {
40140Sstevel@tonic-gate return (0);
40150Sstevel@tonic-gate }
40160Sstevel@tonic-gate
40170Sstevel@tonic-gate while ((ncp = getnetconfig(handle)) != NULL) {
40180Sstevel@tonic-gate if (ncp->nc_semantics != NC_TPI_CLTS) {
40190Sstevel@tonic-gate continue;
40200Sstevel@tonic-gate }
40210Sstevel@tonic-gate
40220Sstevel@tonic-gate if (netdir_getbyname(ncp, &hs, &nap) != 0) {
40230Sstevel@tonic-gate continue;
40240Sstevel@tonic-gate }
40250Sstevel@tonic-gate
40260Sstevel@tonic-gate if (nap == NULL) {
40270Sstevel@tonic-gate continue;
40280Sstevel@tonic-gate }
40290Sstevel@tonic-gate
40300Sstevel@tonic-gate nbp = nap->n_addrs;
40310Sstevel@tonic-gate
40320Sstevel@tonic-gate for (i = 0; i < nap->n_cnt; i++) {
40330Sstevel@tonic-gate if ((uap = taddr2uaddr(ncp, nbp)) != (char *)NULL) {
40340Sstevel@tonic-gate DPRINT2(1, "amiloghost(%u): testing %s\n",
40356358Snakanon mythreadno, uap);
40360Sstevel@tonic-gate }
40370Sstevel@tonic-gate
40380Sstevel@tonic-gate free(uap);
40390Sstevel@tonic-gate
40400Sstevel@tonic-gate fd = t_open(ncp->nc_device, O_RDWR, NULL);
40410Sstevel@tonic-gate
40420Sstevel@tonic-gate if (fd < 0) {
40430Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
40442104Sjjj (void) endnetconfig(handle);
40450Sstevel@tonic-gate return (0);
40460Sstevel@tonic-gate }
40470Sstevel@tonic-gate
40480Sstevel@tonic-gate /*LINTED*/
40490Sstevel@tonic-gate bound = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
40500Sstevel@tonic-gate bind.addr = *nbp;
40510Sstevel@tonic-gate bind.qlen = 0;
40520Sstevel@tonic-gate
40530Sstevel@tonic-gate if (t_bind(fd, &bind, bound) == 0) {
40542104Sjjj (void) t_close(fd);
40552104Sjjj (void) t_free((char *)bound, T_BIND);
40560Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
40572104Sjjj (void) endnetconfig(handle);
40580Sstevel@tonic-gate return (1);
40590Sstevel@tonic-gate } else {
40602104Sjjj (void) t_close(fd);
40612104Sjjj (void) t_free((char *)bound, T_BIND);
40620Sstevel@tonic-gate }
40630Sstevel@tonic-gate
40640Sstevel@tonic-gate nbp++;
40650Sstevel@tonic-gate }
40660Sstevel@tonic-gate
40670Sstevel@tonic-gate netdir_free((void *)nap, ND_ADDRLIST);
40680Sstevel@tonic-gate }
40690Sstevel@tonic-gate
40702104Sjjj (void) endnetconfig(handle);
40710Sstevel@tonic-gate return (0);
40720Sstevel@tonic-gate }
40730Sstevel@tonic-gate
40740Sstevel@tonic-gate int
same_addr(struct netbuf * na,struct netbuf * nb)40750Sstevel@tonic-gate same_addr(struct netbuf *na, struct netbuf *nb)
40760Sstevel@tonic-gate {
40770Sstevel@tonic-gate char *a, *b;
40780Sstevel@tonic-gate size_t n;
40790Sstevel@tonic-gate
40802104Sjjj assert(na->buf != NULL && nb->buf != NULL);
40810Sstevel@tonic-gate
40820Sstevel@tonic-gate if (na->len != nb->len) {
40830Sstevel@tonic-gate return (0);
40840Sstevel@tonic-gate }
40850Sstevel@tonic-gate
40860Sstevel@tonic-gate a = na->buf;
40870Sstevel@tonic-gate b = nb->buf;
40880Sstevel@tonic-gate n = nb->len;
40890Sstevel@tonic-gate
40900Sstevel@tonic-gate while (n-- > 0) {
40910Sstevel@tonic-gate if (*a++ != *b++) {
40920Sstevel@tonic-gate return (0);
40930Sstevel@tonic-gate }
40940Sstevel@tonic-gate }
40950Sstevel@tonic-gate
40960Sstevel@tonic-gate return (1);
40970Sstevel@tonic-gate }
40980Sstevel@tonic-gate
40990Sstevel@tonic-gate /*
41000Sstevel@tonic-gate * allocates a new message structure, initializes it
41010Sstevel@tonic-gate * and returns a pointer to it
41020Sstevel@tonic-gate */
41030Sstevel@tonic-gate static log_message_t *
new_msg(void)41040Sstevel@tonic-gate new_msg(void)
41050Sstevel@tonic-gate {
41060Sstevel@tonic-gate log_message_t *lm;
41070Sstevel@tonic-gate pthread_t mythreadno;
41080Sstevel@tonic-gate
41090Sstevel@tonic-gate if (Debug) {
41100Sstevel@tonic-gate mythreadno = pthread_self();
41110Sstevel@tonic-gate }
41120Sstevel@tonic-gate
41130Sstevel@tonic-gate if ((lm = malloc(sizeof (log_message_t))) == NULL)
41140Sstevel@tonic-gate return ((log_message_t *)NULL);
41150Sstevel@tonic-gate
41160Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lm))
41170Sstevel@tonic-gate
41180Sstevel@tonic-gate if (pthread_mutex_init(&lm->msg_mutex, NULL) != 0)
41190Sstevel@tonic-gate return ((log_message_t *)NULL);
41200Sstevel@tonic-gate lm->refcnt = 0;
41210Sstevel@tonic-gate lm->pri = 0;
41220Sstevel@tonic-gate lm->flags = 0;
41230Sstevel@tonic-gate lm->hlp = NULL;
41240Sstevel@tonic-gate lm->msg[0] = '\0';
41250Sstevel@tonic-gate lm->ptr = NULL;
41260Sstevel@tonic-gate
41272104Sjjj DPRINT2(3, "new_msg(%u): creating msg %p\n", mythreadno, (void *)lm);
41280Sstevel@tonic-gate return (lm);
41290Sstevel@tonic-gate }
41300Sstevel@tonic-gate
41310Sstevel@tonic-gate /*
41320Sstevel@tonic-gate * frees a message structure - should only be called if
41330Sstevel@tonic-gate * the refcount is 0
41340Sstevel@tonic-gate */
41350Sstevel@tonic-gate static void
free_msg(log_message_t * lm)41360Sstevel@tonic-gate free_msg(log_message_t *lm)
41370Sstevel@tonic-gate {
41380Sstevel@tonic-gate pthread_t mythreadno;
41390Sstevel@tonic-gate
41400Sstevel@tonic-gate if (Debug) {
41410Sstevel@tonic-gate mythreadno = pthread_self();
41420Sstevel@tonic-gate }
41430Sstevel@tonic-gate
41440Sstevel@tonic-gate assert(lm != NULL && lm->refcnt == 0);
41450Sstevel@tonic-gate if (lm->hlp != NULL)
41460Sstevel@tonic-gate freehl(lm->hlp);
41472104Sjjj DPRINT2(3, "free_msg(%u): freeing msg %p\n", mythreadno, (void *)lm);
41480Sstevel@tonic-gate free(lm);
41490Sstevel@tonic-gate }
41500Sstevel@tonic-gate
41510Sstevel@tonic-gate /*
41520Sstevel@tonic-gate * Make sure that the message makes sense in the current locale, and
41530Sstevel@tonic-gate * does not contain stray control characters.
41540Sstevel@tonic-gate */
41550Sstevel@tonic-gate static void
filter_string(char * mbstr,char * filtered,size_t max)41560Sstevel@tonic-gate filter_string(char *mbstr, char *filtered, size_t max)
41570Sstevel@tonic-gate {
41580Sstevel@tonic-gate size_t cs = 0;
41590Sstevel@tonic-gate size_t mb_cur_max;
41600Sstevel@tonic-gate unsigned char *p = (unsigned char *)mbstr;
41610Sstevel@tonic-gate pthread_t mythreadno = 0;
41620Sstevel@tonic-gate
41630Sstevel@tonic-gate if (Debug) {
41640Sstevel@tonic-gate mythreadno = pthread_self();
41650Sstevel@tonic-gate }
41660Sstevel@tonic-gate
41670Sstevel@tonic-gate assert(mbstr != NULL && filtered != NULL);
41680Sstevel@tonic-gate
41690Sstevel@tonic-gate /*
41700Sstevel@tonic-gate * Since the access to MB_CUR_MAX is expensive (because
41710Sstevel@tonic-gate * MB_CUR_MAX lives in a global area), it should be
41720Sstevel@tonic-gate * restrained for the better performance.
41730Sstevel@tonic-gate */
41740Sstevel@tonic-gate mb_cur_max = (size_t)MB_CUR_MAX;
41750Sstevel@tonic-gate if (mb_cur_max > 1) {
41760Sstevel@tonic-gate /* multibyte locale */
41770Sstevel@tonic-gate int mlen;
41780Sstevel@tonic-gate wchar_t wc;
41790Sstevel@tonic-gate
41800Sstevel@tonic-gate while (*p != '\0') {
41810Sstevel@tonic-gate if ((mlen = mbtowc(&wc, (char *)p,
41826358Snakanon mb_cur_max)) == -1) {
41830Sstevel@tonic-gate /*
41840Sstevel@tonic-gate * Invalid byte sequence found.
41850Sstevel@tonic-gate *
41860Sstevel@tonic-gate * try to print one byte
41870Sstevel@tonic-gate * in ASCII format.
41880Sstevel@tonic-gate */
41890Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): Invalid "
41906358Snakanon "MB sequence: %ld\n", mythreadno,
41916358Snakanon wc);
41920Sstevel@tonic-gate
41930Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) {
41940Sstevel@tonic-gate /* not enough buffer */
41950Sstevel@tonic-gate goto end;
41960Sstevel@tonic-gate } else {
41970Sstevel@tonic-gate continue;
41980Sstevel@tonic-gate }
41990Sstevel@tonic-gate } else {
42000Sstevel@tonic-gate /*
42010Sstevel@tonic-gate * Since *p is not a null byte here,
42020Sstevel@tonic-gate * mbtowc should have never returned 0.
42030Sstevel@tonic-gate *
42040Sstevel@tonic-gate * A valid wide character found.
42050Sstevel@tonic-gate */
42060Sstevel@tonic-gate
42070Sstevel@tonic-gate if (wc != L'\t' && iswcntrl(wc)) {
42080Sstevel@tonic-gate /*
42090Sstevel@tonic-gate * non-tab, non-newline, and
42100Sstevel@tonic-gate * control character found.
42110Sstevel@tonic-gate *
42120Sstevel@tonic-gate * try to print this wide character
42130Sstevel@tonic-gate * in ASCII-format.
42140Sstevel@tonic-gate */
42150Sstevel@tonic-gate char *q = filtered;
42160Sstevel@tonic-gate
42170Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): MB"
42186358Snakanon " control character: %ld\n",
42196358Snakanon mythreadno, wc);
42200Sstevel@tonic-gate
42210Sstevel@tonic-gate while (mlen--) {
42220Sstevel@tonic-gate if (!putctrlc(*p++, &filtered,
42236358Snakanon &cs, max)) {
42240Sstevel@tonic-gate /*
42250Sstevel@tonic-gate * not enough buffer in
42260Sstevel@tonic-gate * filtered
42270Sstevel@tonic-gate *
42280Sstevel@tonic-gate * cancel already
42290Sstevel@tonic-gate * stored bytes in
42300Sstevel@tonic-gate * filtered for this
42310Sstevel@tonic-gate * wide character.
42320Sstevel@tonic-gate */
42330Sstevel@tonic-gate filtered = q;
42340Sstevel@tonic-gate goto end;
42350Sstevel@tonic-gate }
42360Sstevel@tonic-gate }
42370Sstevel@tonic-gate continue;
42380Sstevel@tonic-gate } else {
42390Sstevel@tonic-gate /*
42400Sstevel@tonic-gate * tab, newline, or non-control
42410Sstevel@tonic-gate * character found.
42420Sstevel@tonic-gate */
42430Sstevel@tonic-gate if (cs + mlen < max) {
42440Sstevel@tonic-gate /* enough buffer */
42450Sstevel@tonic-gate cs += mlen;
42460Sstevel@tonic-gate while (mlen--) {
42470Sstevel@tonic-gate *filtered++ = *p++;
42480Sstevel@tonic-gate }
42490Sstevel@tonic-gate continue;
42500Sstevel@tonic-gate } else {
42510Sstevel@tonic-gate /* not enough buffer */
42520Sstevel@tonic-gate goto end;
42530Sstevel@tonic-gate }
42540Sstevel@tonic-gate }
42550Sstevel@tonic-gate }
42560Sstevel@tonic-gate }
42570Sstevel@tonic-gate } else {
42580Sstevel@tonic-gate /* singlebyte locale */
42590Sstevel@tonic-gate
42600Sstevel@tonic-gate while (*p != '\0') {
42610Sstevel@tonic-gate if (*p != '\t' && iscntrl(*p)) {
42620Sstevel@tonic-gate /*
42630Sstevel@tonic-gate * non-tab, non-newline,
42640Sstevel@tonic-gate * and control character found.
42650Sstevel@tonic-gate *
42660Sstevel@tonic-gate * try to print this singlebyte character
42670Sstevel@tonic-gate * in ASCII format.
42680Sstevel@tonic-gate */
42690Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): control "
42706358Snakanon "character: %d\n", mythreadno, *p);
42710Sstevel@tonic-gate
42720Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) {
42730Sstevel@tonic-gate /* not enough buffer */
42740Sstevel@tonic-gate goto end;
42750Sstevel@tonic-gate } else {
42760Sstevel@tonic-gate continue;
42770Sstevel@tonic-gate }
42780Sstevel@tonic-gate } else if (*p != '\t' && !isprint(*p)) {
42790Sstevel@tonic-gate /*
42800Sstevel@tonic-gate * non-tab and non printable character found
42810Sstevel@tonic-gate * this check is required for the C locale
42820Sstevel@tonic-gate */
42830Sstevel@tonic-gate DPRINT2(9, "filter_string(%u): non-printable "
42846358Snakanon "character: %d\n", mythreadno, *p);
42850Sstevel@tonic-gate if (!putctrlc(*p++, &filtered, &cs, max)) {
42860Sstevel@tonic-gate /* not enough buffer */
42870Sstevel@tonic-gate goto end;
42880Sstevel@tonic-gate } else {
42890Sstevel@tonic-gate continue;
42900Sstevel@tonic-gate }
42910Sstevel@tonic-gate } else {
42920Sstevel@tonic-gate /*
42930Sstevel@tonic-gate * tab, newline, non-control character, or
42940Sstevel@tonic-gate * printable found.
42950Sstevel@tonic-gate */
42960Sstevel@tonic-gate if (cs + 1 < max) {
42970Sstevel@tonic-gate *filtered++ = *p++;
42980Sstevel@tonic-gate cs++;
42990Sstevel@tonic-gate continue;
43000Sstevel@tonic-gate } else {
43010Sstevel@tonic-gate /* not enough buffer */
43020Sstevel@tonic-gate goto end;
43030Sstevel@tonic-gate }
43040Sstevel@tonic-gate }
43050Sstevel@tonic-gate }
43060Sstevel@tonic-gate }
43070Sstevel@tonic-gate
43080Sstevel@tonic-gate end:
43090Sstevel@tonic-gate *filtered = '\0';
43100Sstevel@tonic-gate
43110Sstevel@tonic-gate if (cs >= 2 &&
43126358Snakanon filtered[-2] == '\\' && filtered[-1] == 'n') {
43130Sstevel@tonic-gate filtered[-2] = '\0';
43140Sstevel@tonic-gate }
43150Sstevel@tonic-gate }
43160Sstevel@tonic-gate
43170Sstevel@tonic-gate static char *
alloc_stacks(int numstacks)43180Sstevel@tonic-gate alloc_stacks(int numstacks)
43190Sstevel@tonic-gate {
43200Sstevel@tonic-gate size_t pagesize, mapsize;
43210Sstevel@tonic-gate char *stack_top;
43220Sstevel@tonic-gate char *addr;
43230Sstevel@tonic-gate int i;
43240Sstevel@tonic-gate
43250Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE);
43260Sstevel@tonic-gate /*
43270Sstevel@tonic-gate * stacksize and redzonesize are global so threads
43280Sstevel@tonic-gate * can be created elsewhere and refer to the sizes
43290Sstevel@tonic-gate */
43300Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
43316358Snakanon DEFAULT_STACKSIZE, pagesize);
43320Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
43330Sstevel@tonic-gate
43340Sstevel@tonic-gate /*
43350Sstevel@tonic-gate * allocate an additional "redzonesize" chunk in addition
43360Sstevel@tonic-gate * to what we require, so we can create a redzone at the
43370Sstevel@tonic-gate * bottom of the last stack as well.
43380Sstevel@tonic-gate */
43390Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize);
43400Sstevel@tonic-gate stack_top = mmap(NULL, mapsize, PROT_READ|PROT_WRITE,
43416358Snakanon MAP_PRIVATE|MAP_ANON, -1, 0);
43420Sstevel@tonic-gate if (stack_top == MAP_FAILED)
43430Sstevel@tonic-gate return (NULL);
43440Sstevel@tonic-gate
43450Sstevel@tonic-gate addr = stack_top;
43460Sstevel@tonic-gate /*
43470Sstevel@tonic-gate * this loop is intentionally <= instead of <, so we can
43480Sstevel@tonic-gate * protect the redzone at the bottom of the last stack
43490Sstevel@tonic-gate */
43500Sstevel@tonic-gate for (i = 0; i <= numstacks; i++) {
43510Sstevel@tonic-gate (void) mprotect(addr, redzonesize, PROT_NONE);
43520Sstevel@tonic-gate addr += stacksize + redzonesize;
43530Sstevel@tonic-gate }
43540Sstevel@tonic-gate return ((char *)(stack_top + redzonesize));
43550Sstevel@tonic-gate }
43560Sstevel@tonic-gate
43570Sstevel@tonic-gate static void
dealloc_stacks(int numstacks)43580Sstevel@tonic-gate dealloc_stacks(int numstacks)
43590Sstevel@tonic-gate {
43600Sstevel@tonic-gate size_t pagesize, mapsize;
43610Sstevel@tonic-gate
43620Sstevel@tonic-gate pagesize = (size_t)sysconf(_SC_PAGESIZE);
43630Sstevel@tonic-gate
43640Sstevel@tonic-gate stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
43650Sstevel@tonic-gate DEFAULT_STACKSIZE, pagesize);
43660Sstevel@tonic-gate
43670Sstevel@tonic-gate redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
43680Sstevel@tonic-gate
43690Sstevel@tonic-gate mapsize = redzonesize + numstacks * (stacksize + redzonesize);
43700Sstevel@tonic-gate (void) munmap(cstack_ptr - mapsize, mapsize);
43710Sstevel@tonic-gate }
43720Sstevel@tonic-gate
43730Sstevel@tonic-gate static void
filed_destroy(struct filed * f)43740Sstevel@tonic-gate filed_destroy(struct filed *f)
43750Sstevel@tonic-gate {
43760Sstevel@tonic-gate (void) dataq_destroy(&f->f_queue);
43772104Sjjj (void) pthread_mutex_destroy(&f->filed_mutex);
43780Sstevel@tonic-gate }
43790Sstevel@tonic-gate
43800Sstevel@tonic-gate static void
close_door(void)43810Sstevel@tonic-gate close_door(void)
43820Sstevel@tonic-gate {
43830Sstevel@tonic-gate pthread_t mythreadno;
43840Sstevel@tonic-gate
43850Sstevel@tonic-gate if (Debug) {
43860Sstevel@tonic-gate mythreadno = pthread_self();
43870Sstevel@tonic-gate }
43880Sstevel@tonic-gate
43890Sstevel@tonic-gate (void) fdetach(DoorFileName);
43900Sstevel@tonic-gate
43910Sstevel@tonic-gate DPRINT2(5, "close_door(%u): detached server() from %s\n",
43926358Snakanon mythreadno, DoorFileName);
43930Sstevel@tonic-gate }
43940Sstevel@tonic-gate
43950Sstevel@tonic-gate static void
delete_doorfiles(void)43960Sstevel@tonic-gate delete_doorfiles(void)
43970Sstevel@tonic-gate {
43980Sstevel@tonic-gate pthread_t mythreadno;
43990Sstevel@tonic-gate struct stat sb;
44000Sstevel@tonic-gate int err;
44010Sstevel@tonic-gate char line[MAXLINE+1];
44020Sstevel@tonic-gate
44030Sstevel@tonic-gate if (Debug) {
44040Sstevel@tonic-gate mythreadno = pthread_self();
44050Sstevel@tonic-gate }
44060Sstevel@tonic-gate
44070Sstevel@tonic-gate
44080Sstevel@tonic-gate if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44090Sstevel@tonic-gate if (unlink(DoorFileName) < 0) {
44100Sstevel@tonic-gate err = errno;
44112104Sjjj (void) snprintf(line, sizeof (line),
44122104Sjjj "unlink() of %s failed - fatal", DoorFileName);
44130Sstevel@tonic-gate errno = err;
44140Sstevel@tonic-gate logerror(line);
44150Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, "
44166358Snakanon "errno=%d\n", mythreadno, line, err);
44170Sstevel@tonic-gate exit(1);
44180Sstevel@tonic-gate }
44190Sstevel@tonic-gate
44200Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
44216358Snakanon mythreadno, DoorFileName);
44220Sstevel@tonic-gate }
44230Sstevel@tonic-gate
44240Sstevel@tonic-gate if (strcmp(DoorFileName, DOORFILE) == 0) {
44250Sstevel@tonic-gate if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44260Sstevel@tonic-gate if (unlink(OLD_DOORFILE) < 0) {
44270Sstevel@tonic-gate err = errno;
44282104Sjjj (void) snprintf(line, sizeof (line),
44292104Sjjj "unlink() of %s failed", OLD_DOORFILE);
44300Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s\n",
44316358Snakanon mythreadno, line);
44320Sstevel@tonic-gate
44330Sstevel@tonic-gate if (err != EROFS) {
44340Sstevel@tonic-gate errno = err;
44352104Sjjj (void) strlcat(line, " - fatal",
44362104Sjjj sizeof (line));
44370Sstevel@tonic-gate logerror(line);
44380Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): "
44396358Snakanon "error: %s, errno=%d\n",
44406358Snakanon mythreadno, line, err);
44410Sstevel@tonic-gate exit(1);
44420Sstevel@tonic-gate }
44430Sstevel@tonic-gate
44440Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink() "
44456358Snakanon "failure OK on RO file system\n",
44466358Snakanon mythreadno);
44470Sstevel@tonic-gate }
44480Sstevel@tonic-gate
44490Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
44506358Snakanon mythreadno, OLD_DOORFILE);
44510Sstevel@tonic-gate }
44520Sstevel@tonic-gate }
44530Sstevel@tonic-gate
44540Sstevel@tonic-gate if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44550Sstevel@tonic-gate if (unlink(PidFileName) < 0) {
44560Sstevel@tonic-gate err = errno;
44572104Sjjj (void) snprintf(line, sizeof (line),
44582104Sjjj "unlink() of %s failed - fatal", PidFileName);
44590Sstevel@tonic-gate errno = err;
44600Sstevel@tonic-gate logerror(line);
44610Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): error: %s, "
44626358Snakanon "errno=%d\n", mythreadno, line, err);
44630Sstevel@tonic-gate exit(1);
44640Sstevel@tonic-gate }
44650Sstevel@tonic-gate
44660Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", mythreadno,
44676358Snakanon PidFileName);
44680Sstevel@tonic-gate }
44690Sstevel@tonic-gate
44700Sstevel@tonic-gate if (strcmp(PidFileName, PIDFILE) == 0) {
44710Sstevel@tonic-gate if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44720Sstevel@tonic-gate if (unlink(OLD_PIDFILE) < 0) {
44730Sstevel@tonic-gate err = errno;
44742104Sjjj (void) snprintf(line, sizeof (line),
44752104Sjjj "unlink() of %s failed", OLD_PIDFILE);
44760Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): %s, \n",
44776358Snakanon mythreadno, line);
44780Sstevel@tonic-gate
44790Sstevel@tonic-gate if (err != EROFS) {
44800Sstevel@tonic-gate errno = err;
44812104Sjjj (void) strlcat(line, " - fatal",
44822104Sjjj sizeof (line));
44830Sstevel@tonic-gate logerror(line);
44840Sstevel@tonic-gate DPRINT3(1, "delete_doorfiles(%u): "
44856358Snakanon "error: %s, errno=%d\n",
44866358Snakanon mythreadno, line, err);
44870Sstevel@tonic-gate exit(1);
44880Sstevel@tonic-gate }
44890Sstevel@tonic-gate
44900Sstevel@tonic-gate DPRINT1(5, "delete_doorfiles(%u): unlink "
44916358Snakanon "failure OK on RO file system\n",
44926358Snakanon mythreadno);
44930Sstevel@tonic-gate }
44940Sstevel@tonic-gate
44950Sstevel@tonic-gate DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
44966358Snakanon mythreadno, OLD_PIDFILE);
44970Sstevel@tonic-gate }
44980Sstevel@tonic-gate }
44990Sstevel@tonic-gate
45000Sstevel@tonic-gate if (DoorFd != -1) {
45010Sstevel@tonic-gate (void) door_revoke(DoorFd);
45020Sstevel@tonic-gate }
45030Sstevel@tonic-gate
45040Sstevel@tonic-gate DPRINT2(1, "delete_doorfiles(%u): revoked door: DoorFd=%d\n",
45056358Snakanon mythreadno, DoorFd);
45060Sstevel@tonic-gate }
45070Sstevel@tonic-gate
45080Sstevel@tonic-gate
45090Sstevel@tonic-gate /*ARGSUSED*/
45100Sstevel@tonic-gate static void
signull(int sig,siginfo_t * sip,void * utp)45110Sstevel@tonic-gate signull(int sig, siginfo_t *sip, void *utp)
45120Sstevel@tonic-gate {
45130Sstevel@tonic-gate DPRINT1(1, "signull(%u): THIS CALL SHOULD NEVER HAPPEN\n",
45146358Snakanon pthread_self());
45150Sstevel@tonic-gate /*
45160Sstevel@tonic-gate * Do nothing, as this is a place-holder used in conjunction with
45170Sstevel@tonic-gate * sigaction()/sigwait() to ensure that the proper disposition is
45180Sstevel@tonic-gate * given to the signals we handle in main().
45190Sstevel@tonic-gate */
45200Sstevel@tonic-gate }
45210Sstevel@tonic-gate
45220Sstevel@tonic-gate /*
45230Sstevel@tonic-gate * putctrlc returns zero, if failed due to not enough buffer.
45240Sstevel@tonic-gate * Otherwise, putctrlc returns non-zero.
45250Sstevel@tonic-gate *
45260Sstevel@tonic-gate * c: a byte to print in ASCII format
45270Sstevel@tonic-gate * **buf: a pointer to the pointer to the output buffer.
45280Sstevel@tonic-gate * *cl: current length of characters in the output buffer
45290Sstevel@tonic-gate * max: maximum length of the buffer
45300Sstevel@tonic-gate */
45310Sstevel@tonic-gate
45320Sstevel@tonic-gate static int
putctrlc(int c,char ** buf,size_t * cl,size_t max)45330Sstevel@tonic-gate putctrlc(int c, char **buf, size_t *cl, size_t max)
45340Sstevel@tonic-gate {
45350Sstevel@tonic-gate char *p = *buf;
45360Sstevel@tonic-gate
45370Sstevel@tonic-gate if (c == '\n') {
45380Sstevel@tonic-gate if (*cl + 2 < max) {
45390Sstevel@tonic-gate *p++ = '\\';
45400Sstevel@tonic-gate *p++ = 'n';
45410Sstevel@tonic-gate *cl += 2;
45420Sstevel@tonic-gate *buf = p;
45430Sstevel@tonic-gate return (2);
45440Sstevel@tonic-gate } else {
45450Sstevel@tonic-gate return (0);
45460Sstevel@tonic-gate }
45470Sstevel@tonic-gate } else if (c < 0200) {
45480Sstevel@tonic-gate /* ascii control character */
45490Sstevel@tonic-gate if (*cl + 2 < max) {
45500Sstevel@tonic-gate *p++ = '^';
45510Sstevel@tonic-gate *p++ = c ^ 0100;
45520Sstevel@tonic-gate *cl += 2;
45530Sstevel@tonic-gate *buf = p;
45540Sstevel@tonic-gate return (2);
45550Sstevel@tonic-gate } else {
45560Sstevel@tonic-gate return (0);
45570Sstevel@tonic-gate }
45580Sstevel@tonic-gate } else {
45590Sstevel@tonic-gate if (*cl + 4 < max) {
45600Sstevel@tonic-gate *p++ = '\\';
45610Sstevel@tonic-gate *p++ = ((c >> 6) & 07) + '0';
45620Sstevel@tonic-gate *p++ = ((c >> 3) & 07) + '0';
45630Sstevel@tonic-gate *p++ = (c & 07) + '0';
45640Sstevel@tonic-gate *cl += 4;
45650Sstevel@tonic-gate *buf = p;
45660Sstevel@tonic-gate return (4);
45670Sstevel@tonic-gate } else {
45680Sstevel@tonic-gate return (0);
45690Sstevel@tonic-gate }
45700Sstevel@tonic-gate }
45710Sstevel@tonic-gate }
45720Sstevel@tonic-gate
45730Sstevel@tonic-gate /*
45740Sstevel@tonic-gate * findnl_bkwd:
45750Sstevel@tonic-gate * Scans each character in buf until it finds the last newline in buf,
45760Sstevel@tonic-gate * or the scanned character becomes the last COMPLETE character in buf.
45770Sstevel@tonic-gate * Returns the number of scanned bytes.
45780Sstevel@tonic-gate *
45790Sstevel@tonic-gate * buf - pointer to a buffer containing the message string
45800Sstevel@tonic-gate * len - the length of the buffer
45810Sstevel@tonic-gate */
45820Sstevel@tonic-gate size_t
findnl_bkwd(const char * buf,const size_t len)45830Sstevel@tonic-gate findnl_bkwd(const char *buf, const size_t len)
45840Sstevel@tonic-gate {
45850Sstevel@tonic-gate const char *p;
45860Sstevel@tonic-gate size_t mb_cur_max;
45870Sstevel@tonic-gate pthread_t mythreadno;
45880Sstevel@tonic-gate
45890Sstevel@tonic-gate if (Debug) {
45900Sstevel@tonic-gate mythreadno = pthread_self();
45910Sstevel@tonic-gate }
45920Sstevel@tonic-gate
45930Sstevel@tonic-gate if (len == 0) {
45940Sstevel@tonic-gate return (0);
45950Sstevel@tonic-gate }
45960Sstevel@tonic-gate
45970Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX;
45980Sstevel@tonic-gate
45990Sstevel@tonic-gate if (mb_cur_max == 1) {
46000Sstevel@tonic-gate /* single-byte locale */
46010Sstevel@tonic-gate for (p = buf + len - 1; p != buf; p--) {
46020Sstevel@tonic-gate if (*p == '\n') {
46030Sstevel@tonic-gate return ((size_t)(p - buf));
46040Sstevel@tonic-gate }
46050Sstevel@tonic-gate }
46060Sstevel@tonic-gate return ((size_t)len);
46070Sstevel@tonic-gate } else {
46080Sstevel@tonic-gate /* multi-byte locale */
46090Sstevel@tonic-gate int mlen;
46100Sstevel@tonic-gate const char *nl;
46110Sstevel@tonic-gate size_t rem;
46120Sstevel@tonic-gate
46130Sstevel@tonic-gate p = buf;
46140Sstevel@tonic-gate nl = NULL;
46150Sstevel@tonic-gate for (rem = len; rem >= mb_cur_max; ) {
46160Sstevel@tonic-gate mlen = mblen(p, mb_cur_max);
46170Sstevel@tonic-gate if (mlen == -1) {
46180Sstevel@tonic-gate /*
46190Sstevel@tonic-gate * Invalid character found.
46200Sstevel@tonic-gate */
46210Sstevel@tonic-gate DPRINT1(9, "findnl_bkwd(%u): Invalid MB "
46226358Snakanon "sequence\n", mythreadno);
46230Sstevel@tonic-gate /*
46240Sstevel@tonic-gate * handle as a single byte character.
46250Sstevel@tonic-gate */
46260Sstevel@tonic-gate p++;
46270Sstevel@tonic-gate rem--;
46280Sstevel@tonic-gate } else {
46290Sstevel@tonic-gate /*
46300Sstevel@tonic-gate * It's guaranteed that *p points to
46310Sstevel@tonic-gate * the 1st byte of a multibyte character.
46320Sstevel@tonic-gate */
46330Sstevel@tonic-gate if (*p == '\n') {
46340Sstevel@tonic-gate nl = p;
46350Sstevel@tonic-gate }
46360Sstevel@tonic-gate p += mlen;
46370Sstevel@tonic-gate rem -= mlen;
46380Sstevel@tonic-gate }
46390Sstevel@tonic-gate }
46400Sstevel@tonic-gate if (nl) {
46410Sstevel@tonic-gate return ((size_t)(nl - buf));
46420Sstevel@tonic-gate }
46430Sstevel@tonic-gate /*
46440Sstevel@tonic-gate * no newline nor null byte found.
46450Sstevel@tonic-gate * Also it's guaranteed that *p points to
46460Sstevel@tonic-gate * the 1st byte of a (multibyte) character
46470Sstevel@tonic-gate * at this point.
46480Sstevel@tonic-gate */
46490Sstevel@tonic-gate return (len - rem);
46500Sstevel@tonic-gate }
46510Sstevel@tonic-gate }
46520Sstevel@tonic-gate
46530Sstevel@tonic-gate /*
46540Sstevel@tonic-gate * copynl_frwd:
46550Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf
46560Sstevel@tonic-gate * until it finds a null byte or a newline, or
46570Sstevel@tonic-gate * the number of the remaining bytes in obuf gets to exceed obuflen
46580Sstevel@tonic-gate * if copying the scanned character to obuf.
46590Sstevel@tonic-gate * Returns the number of scanned bytes.
46600Sstevel@tonic-gate *
46610Sstevel@tonic-gate * obuf - buffer to be copied the scanned character
46620Sstevel@tonic-gate * obuflen - the size of obuf
46630Sstevel@tonic-gate * buf - pointer to a buffer containing the message string
46640Sstevel@tonic-gate * len - the length of the buffer
46650Sstevel@tonic-gate */
46660Sstevel@tonic-gate size_t
copynl_frwd(char * obuf,const size_t obuflen,const char * buf,const size_t len)46670Sstevel@tonic-gate copynl_frwd(char *obuf, const size_t obuflen,
46680Sstevel@tonic-gate const char *buf, const size_t len)
46690Sstevel@tonic-gate {
46700Sstevel@tonic-gate const char *p;
46710Sstevel@tonic-gate char *q = obuf;
46720Sstevel@tonic-gate size_t olen = 0;
46730Sstevel@tonic-gate size_t mb_cur_max;
46740Sstevel@tonic-gate pthread_t mythreadno;
46750Sstevel@tonic-gate
46760Sstevel@tonic-gate if (Debug) {
46770Sstevel@tonic-gate mythreadno = pthread_self();
46780Sstevel@tonic-gate }
46790Sstevel@tonic-gate
46800Sstevel@tonic-gate if (len == 0) {
46810Sstevel@tonic-gate return (0);
46820Sstevel@tonic-gate }
46830Sstevel@tonic-gate
46840Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX;
46850Sstevel@tonic-gate
46860Sstevel@tonic-gate if (mb_cur_max == 1) {
46870Sstevel@tonic-gate /* single-byte locale */
46880Sstevel@tonic-gate for (p = buf; *p; ) {
46890Sstevel@tonic-gate if (obuflen > olen + 1) {
46900Sstevel@tonic-gate if (*p != '\n') {
46910Sstevel@tonic-gate *q++ = *p++;
46920Sstevel@tonic-gate olen++;
46930Sstevel@tonic-gate } else {
46940Sstevel@tonic-gate *q = '\0';
46950Sstevel@tonic-gate return ((size_t)(p - buf));
46960Sstevel@tonic-gate }
46970Sstevel@tonic-gate } else {
46980Sstevel@tonic-gate *q = '\0';
46990Sstevel@tonic-gate return ((size_t)(p - buf));
47000Sstevel@tonic-gate }
47010Sstevel@tonic-gate }
47020Sstevel@tonic-gate *q = '\0';
47030Sstevel@tonic-gate return ((size_t)(p - buf));
47040Sstevel@tonic-gate } else {
47050Sstevel@tonic-gate /* multi-byte locale */
47060Sstevel@tonic-gate int mlen;
47070Sstevel@tonic-gate
47080Sstevel@tonic-gate for (p = buf; *p; ) {
47090Sstevel@tonic-gate mlen = mblen(p, mb_cur_max);
47100Sstevel@tonic-gate if (mlen == -1) {
47110Sstevel@tonic-gate /*
47120Sstevel@tonic-gate * Invalid character found.
47130Sstevel@tonic-gate */
47140Sstevel@tonic-gate DPRINT1(9, "copynl_frwd(%u): Invalid MB "
47156358Snakanon "sequence\n", mythreadno);
47160Sstevel@tonic-gate /*
47170Sstevel@tonic-gate * handle as a single byte character.
47180Sstevel@tonic-gate */
47190Sstevel@tonic-gate if (obuflen > olen + 1) {
47200Sstevel@tonic-gate *q++ = *p++;
47210Sstevel@tonic-gate olen++;
47220Sstevel@tonic-gate } else {
47230Sstevel@tonic-gate *q = '\0';
47240Sstevel@tonic-gate return ((size_t)(p - buf));
47250Sstevel@tonic-gate }
47260Sstevel@tonic-gate } else {
47270Sstevel@tonic-gate /*
47280Sstevel@tonic-gate * It's guaranteed that *p points to
47290Sstevel@tonic-gate * the 1st byte of a multibyte character.
47300Sstevel@tonic-gate */
47310Sstevel@tonic-gate if (*p == '\n') {
47320Sstevel@tonic-gate *q = '\0';
47330Sstevel@tonic-gate return ((size_t)(p - buf));
47340Sstevel@tonic-gate }
47350Sstevel@tonic-gate if (obuflen > olen + mlen) {
47360Sstevel@tonic-gate int n;
47370Sstevel@tonic-gate for (n = 0; n < mlen; n++) {
47380Sstevel@tonic-gate *q++ = *p++;
47390Sstevel@tonic-gate }
47400Sstevel@tonic-gate olen += mlen;
47410Sstevel@tonic-gate } else {
47420Sstevel@tonic-gate *q = '\0';
47430Sstevel@tonic-gate return ((size_t)(p - buf));
47440Sstevel@tonic-gate }
47450Sstevel@tonic-gate }
47460Sstevel@tonic-gate }
47470Sstevel@tonic-gate /*
47480Sstevel@tonic-gate * no newline nor null byte found.
47490Sstevel@tonic-gate * Also it's guaranteed that *p points to
47500Sstevel@tonic-gate * the 1st byte of a (multibyte) character
47510Sstevel@tonic-gate * at this point.
47520Sstevel@tonic-gate */
47530Sstevel@tonic-gate *q = '\0';
47540Sstevel@tonic-gate return ((size_t)(p - buf));
47550Sstevel@tonic-gate }
47560Sstevel@tonic-gate }
47570Sstevel@tonic-gate
47580Sstevel@tonic-gate /*
47590Sstevel@tonic-gate * copy_frwd:
47600Sstevel@tonic-gate * Scans each character in buf and copies the scanned character to obuf
47610Sstevel@tonic-gate * until the number of the remaining bytes in obuf gets to exceed obuflen
47620Sstevel@tonic-gate * if copying the scanned character to obuf.
47630Sstevel@tonic-gate * Returns the number of scanned (copied) bytes.
47640Sstevel@tonic-gate *
47650Sstevel@tonic-gate * obuf - buffer to be copied the scanned character
47660Sstevel@tonic-gate * obuflen - the size of obuf
47670Sstevel@tonic-gate * buf - pointer to a buffer containing the message string
47680Sstevel@tonic-gate * len - the length of the buffer
47690Sstevel@tonic-gate */
47700Sstevel@tonic-gate size_t
copy_frwd(char * obuf,const size_t obuflen,const char * buf,const size_t len)47710Sstevel@tonic-gate copy_frwd(char *obuf, const size_t obuflen,
47720Sstevel@tonic-gate const char *buf, const size_t len)
47730Sstevel@tonic-gate {
47740Sstevel@tonic-gate const char *p;
47750Sstevel@tonic-gate char *q = obuf;
47760Sstevel@tonic-gate size_t olen = 0;
47770Sstevel@tonic-gate size_t mb_cur_max;
47780Sstevel@tonic-gate pthread_t mythreadno;
47790Sstevel@tonic-gate
47800Sstevel@tonic-gate if (Debug) {
47810Sstevel@tonic-gate mythreadno = pthread_self();
47820Sstevel@tonic-gate }
47830Sstevel@tonic-gate
47840Sstevel@tonic-gate if (len == 0) {
47850Sstevel@tonic-gate return (0);
47860Sstevel@tonic-gate }
47870Sstevel@tonic-gate
47880Sstevel@tonic-gate mb_cur_max = MB_CUR_MAX;
47890Sstevel@tonic-gate
47900Sstevel@tonic-gate if (mb_cur_max == 1) {
47910Sstevel@tonic-gate /* single-byte locale */
47920Sstevel@tonic-gate if (obuflen > len) {
47930Sstevel@tonic-gate (void) memcpy(obuf, buf, len);
47940Sstevel@tonic-gate obuf[len] = '\0';
47950Sstevel@tonic-gate return ((size_t)len);
47960Sstevel@tonic-gate } else {
47970Sstevel@tonic-gate (void) memcpy(obuf, buf, obuflen - 1);
47980Sstevel@tonic-gate obuf[obuflen - 1] = '\0';
47990Sstevel@tonic-gate return (obuflen - 1);
48000Sstevel@tonic-gate }
48010Sstevel@tonic-gate } else {
48020Sstevel@tonic-gate /* multi-byte locale */
48030Sstevel@tonic-gate int mlen;
48040Sstevel@tonic-gate
48050Sstevel@tonic-gate for (p = buf; *p; ) {
48060Sstevel@tonic-gate mlen = mblen(p, mb_cur_max);
48070Sstevel@tonic-gate if (mlen == -1) {
48080Sstevel@tonic-gate /*
48090Sstevel@tonic-gate * Invalid character found.
48100Sstevel@tonic-gate */
48110Sstevel@tonic-gate DPRINT1(9, "copy_frwd(%u): Invalid MB "
48126358Snakanon "sequence\n", mythreadno);
48130Sstevel@tonic-gate /*
48140Sstevel@tonic-gate * handle as a single byte character.
48150Sstevel@tonic-gate */
48160Sstevel@tonic-gate if (obuflen > olen + 1) {
48170Sstevel@tonic-gate *q++ = *p++;
48180Sstevel@tonic-gate olen++;
48190Sstevel@tonic-gate } else {
48200Sstevel@tonic-gate *q = '\0';
48210Sstevel@tonic-gate return ((size_t)(p - buf));
48220Sstevel@tonic-gate }
48230Sstevel@tonic-gate } else {
48240Sstevel@tonic-gate if (obuflen > olen + mlen) {
48250Sstevel@tonic-gate int n;
48260Sstevel@tonic-gate for (n = 0; n < mlen; n++) {
48270Sstevel@tonic-gate *q++ = *p++;
48280Sstevel@tonic-gate }
48290Sstevel@tonic-gate olen += mlen;
48300Sstevel@tonic-gate } else {
48310Sstevel@tonic-gate *q = '\0';
48320Sstevel@tonic-gate return ((size_t)(p - buf));
48330Sstevel@tonic-gate }
48340Sstevel@tonic-gate }
48350Sstevel@tonic-gate }
48360Sstevel@tonic-gate *q = '\0';
48370Sstevel@tonic-gate return ((size_t)(p - buf));
48380Sstevel@tonic-gate }
48390Sstevel@tonic-gate }
48400Sstevel@tonic-gate
48410Sstevel@tonic-gate /*
48422104Sjjj * properties:
48432104Sjjj * Get properties from SMF framework.
48440Sstevel@tonic-gate */
48450Sstevel@tonic-gate static void
properties(void)48462104Sjjj properties(void)
48470Sstevel@tonic-gate {
48482104Sjjj scf_simple_prop_t *prop;
48492104Sjjj uint8_t *bool;
48502104Sjjj
48512104Sjjj if ((prop = scf_simple_prop_get(NULL, NULL, "config",
48522104Sjjj "log_from_remote")) != NULL) {
48532104Sjjj if ((bool = scf_simple_prop_next_boolean(prop)) != NULL) {
48542104Sjjj if (*bool == 0)
48552104Sjjj turnoff = 1; /* log_from_remote = false */
48562104Sjjj else
48572104Sjjj turnoff = 0; /* log_from_remote = true */
48580Sstevel@tonic-gate }
48592104Sjjj scf_simple_prop_free(prop);
48602104Sjjj DPRINT1(1, "properties: setting turnoff to %s\n",
48612104Sjjj turnoff ? "true" : "false");
48620Sstevel@tonic-gate }
48630Sstevel@tonic-gate }
48640Sstevel@tonic-gate
48650Sstevel@tonic-gate /*
48660Sstevel@tonic-gate * close all the input devices.
48670Sstevel@tonic-gate */
48680Sstevel@tonic-gate static void
shutdown_input(void)48690Sstevel@tonic-gate shutdown_input(void)
48700Sstevel@tonic-gate {
48710Sstevel@tonic-gate int cnt;
48720Sstevel@tonic-gate
48730Sstevel@tonic-gate shutting_down = 1;
48740Sstevel@tonic-gate
48750Sstevel@tonic-gate for (cnt = 0; cnt < Ninputs; cnt++) {
48760Sstevel@tonic-gate (void) t_close(Nfd[cnt].fd);
48770Sstevel@tonic-gate }
48780Sstevel@tonic-gate
48790Sstevel@tonic-gate (void) close(Pfd.fd);
48800Sstevel@tonic-gate }
48810Sstevel@tonic-gate
48820Sstevel@tonic-gate /*
48830Sstevel@tonic-gate * This is for the one thread that dedicates to resolve the
48840Sstevel@tonic-gate * hostname. This will get the messages from net_poll() through
48850Sstevel@tonic-gate * hnlq, and resolve the hostname, and push the messages back
48860Sstevel@tonic-gate * into the inputq.
48870Sstevel@tonic-gate */
48880Sstevel@tonic-gate /*ARGSUSED*/
48890Sstevel@tonic-gate static void *
hostname_lookup(void * ap)48900Sstevel@tonic-gate hostname_lookup(void *ap)
48910Sstevel@tonic-gate {
48920Sstevel@tonic-gate char *uap;
48930Sstevel@tonic-gate log_message_t *mp;
48940Sstevel@tonic-gate host_info_t *hip;
48950Sstevel@tonic-gate char failsafe_addr[SYS_NMLN + 1];
48960Sstevel@tonic-gate pthread_t mythreadno;
48970Sstevel@tonic-gate
48980Sstevel@tonic-gate if (Debug) {
48990Sstevel@tonic-gate mythreadno = pthread_self();
49000Sstevel@tonic-gate }
49010Sstevel@tonic-gate
49020Sstevel@tonic-gate DPRINT1(1, "hostname_lookup(%u): hostname_lookup started\n",
49036358Snakanon mythreadno);
49040Sstevel@tonic-gate
49050Sstevel@tonic-gate for (;;) {
49060Sstevel@tonic-gate (void) dataq_dequeue(&hnlq, (void **)&mp, 0);
49070Sstevel@tonic-gate
49080Sstevel@tonic-gate DPRINT3(5, "hostname_lookup(%u): dequeued msg %p"
49096358Snakanon " from queue %p\n", mythreadno, (void *)mp,
49106358Snakanon (void *)&hnlq);
49110Sstevel@tonic-gate
49120Sstevel@tonic-gate hip = (host_info_t *)mp->ptr;
49130Sstevel@tonic-gate if ((uap = taddr2uaddr(hip->ncp, &hip->addr)) != NULL) {
49140Sstevel@tonic-gate (void) strlcpy(failsafe_addr, uap, SYS_NMLN);
49150Sstevel@tonic-gate free(uap);
49160Sstevel@tonic-gate } else {
49170Sstevel@tonic-gate (void) strlcpy(failsafe_addr, "<unknown>", SYS_NMLN);
49180Sstevel@tonic-gate }
49190Sstevel@tonic-gate
49200Sstevel@tonic-gate mp->hlp = cvthname(&hip->addr, hip->ncp, failsafe_addr);
49210Sstevel@tonic-gate
49220Sstevel@tonic-gate if (mp->hlp == NULL) {
49230Sstevel@tonic-gate mp->hlp = &NullHostName;
49240Sstevel@tonic-gate }
49250Sstevel@tonic-gate
49260Sstevel@tonic-gate free(hip->addr.buf);
49270Sstevel@tonic-gate free(hip);
49280Sstevel@tonic-gate mp->ptr = NULL;
49290Sstevel@tonic-gate
49300Sstevel@tonic-gate if (dataq_enqueue(&inputq, (void *)mp) == -1) {
49310Sstevel@tonic-gate MALLOC_FAIL("dropping message from remote");
49320Sstevel@tonic-gate free_msg(mp);
49330Sstevel@tonic-gate continue;
49340Sstevel@tonic-gate }
49350Sstevel@tonic-gate
49362104Sjjj DPRINT3(5, "hostname_lookup(%u): enqueued msg %p on queue "
49376358Snakanon "%p\n", mythreadno, (void *)mp, (void *)&inputq);
49380Sstevel@tonic-gate }
49390Sstevel@tonic-gate
49400Sstevel@tonic-gate /*NOTREACHED*/
49410Sstevel@tonic-gate return (NULL);
49420Sstevel@tonic-gate }
49430Sstevel@tonic-gate
49440Sstevel@tonic-gate /*
49450Sstevel@tonic-gate * Does all HUP(re-configuration) process.
49460Sstevel@tonic-gate */
49470Sstevel@tonic-gate static void
reconfigure()49480Sstevel@tonic-gate reconfigure()
49490Sstevel@tonic-gate {
49500Sstevel@tonic-gate int cnt, loop, drops;
49510Sstevel@tonic-gate int really_stuck;
49520Sstevel@tonic-gate int console_stuck = 0;
49530Sstevel@tonic-gate struct filed *f;
49540Sstevel@tonic-gate char buf[LINE_MAX];
49550Sstevel@tonic-gate struct utsname up;
49560Sstevel@tonic-gate char cbuf[30];
49570Sstevel@tonic-gate time_t tim;
49580Sstevel@tonic-gate pthread_t mythreadno;
49590Sstevel@tonic-gate
49600Sstevel@tonic-gate if (Debug) {
49610Sstevel@tonic-gate mythreadno = pthread_self();
49620Sstevel@tonic-gate }
49630Sstevel@tonic-gate
49640Sstevel@tonic-gate /* If we get here then we must need to regen */
49650Sstevel@tonic-gate flushmsg(0);
49660Sstevel@tonic-gate
49670Sstevel@tonic-gate if (logmymsg(LOG_SYSLOG|LOG_INFO, "syslogd: configuration restart",
49686358Snakanon ADDDATE, 0) == -1) {
49690Sstevel@tonic-gate MALLOC_FAIL("dropping message");
49700Sstevel@tonic-gate }
49710Sstevel@tonic-gate
49720Sstevel@tonic-gate /*
49730Sstevel@tonic-gate * make sure the logmsg thread is not in the waiting state.
49740Sstevel@tonic-gate * Otherwise, changing hup_state will prevent the logmsg thread
49750Sstevel@tonic-gate * getting out from the waiting loop.
49760Sstevel@tonic-gate */
49770Sstevel@tonic-gate
49780Sstevel@tonic-gate if (Debug) {
49790Sstevel@tonic-gate tim = time(NULL);
49800Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logmsg()"
49816358Snakanon " moving to the safe place\n",
49826358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
49830Sstevel@tonic-gate }
49840Sstevel@tonic-gate
49850Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) {
49860Sstevel@tonic-gate /* we don't need the mutex to read */
49870Sstevel@tonic-gate if (hup_state == HUP_ACCEPTABLE)
49880Sstevel@tonic-gate break;
49890Sstevel@tonic-gate (void) sleep(1);
49900Sstevel@tonic-gate }
49910Sstevel@tonic-gate if (hup_state != HUP_ACCEPTABLE) {
49920Sstevel@tonic-gate goto thread_stuck;
49930Sstevel@tonic-gate }
49940Sstevel@tonic-gate
49950Sstevel@tonic-gate if (Debug) {
49960Sstevel@tonic-gate tim = time(NULL);
49970Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() will accept HUP\n",
49986358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
49990Sstevel@tonic-gate }
50000Sstevel@tonic-gate
50010Sstevel@tonic-gate /*
50020Sstevel@tonic-gate * Prevent logging until we are truly done processing the HUP
50030Sstevel@tonic-gate */
50040Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock);
50050Sstevel@tonic-gate hup_state = HUP_INPROGRESS;
50060Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock);
50070Sstevel@tonic-gate
50080Sstevel@tonic-gate /*
50090Sstevel@tonic-gate * We will be going into a critical state. Any error message
50100Sstevel@tonic-gate * from syslogd needs to be dumped to the console by default
50110Sstevel@tonic-gate * immediately. Also, those error messages are quened in a temporary
50120Sstevel@tonic-gate * queue to be able to post into the regular stream later.
50130Sstevel@tonic-gate */
50140Sstevel@tonic-gate disable_errorlog();
50150Sstevel@tonic-gate
50160Sstevel@tonic-gate if (Debug) {
50170Sstevel@tonic-gate tim = time(NULL);
50180Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: sending SHUTDOWN\n",
50196358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
50200Sstevel@tonic-gate }
50210Sstevel@tonic-gate
50220Sstevel@tonic-gate /* stop configured threads */
50230Sstevel@tonic-gate if (shutdown_msg() == -1) {
50240Sstevel@tonic-gate /*
50250Sstevel@tonic-gate * No memory, message will be dumped to the console.
50260Sstevel@tonic-gate */
50270Sstevel@tonic-gate MALLOC_FAIL("unable to restart syslogd");
50280Sstevel@tonic-gate goto out;
50290Sstevel@tonic-gate }
50300Sstevel@tonic-gate
50310Sstevel@tonic-gate /* make sure logmsg() is in suspended state */
50320Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) {
50330Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED)
50340Sstevel@tonic-gate break;
50350Sstevel@tonic-gate (void) sleep(1);
50360Sstevel@tonic-gate }
50370Sstevel@tonic-gate
50380Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
50390Sstevel@tonic-gate if (Debug) {
50400Sstevel@tonic-gate tim = time(NULL);
50410Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() does not "
50426358Snakanon "stop. enforcing\n",
50436358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
50440Sstevel@tonic-gate }
50450Sstevel@tonic-gate
50460Sstevel@tonic-gate /* probably we have too long input queue, or really stuck */
50470Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock);
50480Sstevel@tonic-gate hup_state |= HUP_SUSP_LOGMSG_REQD;
50490Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock);
50500Sstevel@tonic-gate
50510Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) {
50520Sstevel@tonic-gate if (hup_state & HUP_LOGMSG_SUSPENDED)
50530Sstevel@tonic-gate break;
50540Sstevel@tonic-gate (void) sleep(1);
50550Sstevel@tonic-gate }
50560Sstevel@tonic-gate if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
50570Sstevel@tonic-gate if (Debug) {
50580Sstevel@tonic-gate tim = time(NULL);
50590Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg()"
50606358Snakanon " does not stop. give up\n",
50616358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
50620Sstevel@tonic-gate }
50630Sstevel@tonic-gate logerror("could not suspend logmsg - fatal");
50640Sstevel@tonic-gate goto thread_stuck;
50650Sstevel@tonic-gate }
50660Sstevel@tonic-gate }
50670Sstevel@tonic-gate
50680Sstevel@tonic-gate if (Debug) {
50690Sstevel@tonic-gate tim = time(NULL);
50700Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: logmsg() suspended\n",
50716358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
50720Sstevel@tonic-gate }
50730Sstevel@tonic-gate
50740Sstevel@tonic-gate /*
50750Sstevel@tonic-gate * Will wait for LOOP_MAX secs with watching queue lengths for the
50760Sstevel@tonic-gate * each logger threads. If they have backlogs, and no change in the
50770Sstevel@tonic-gate * length of queue found in 30 seconds, those will be counted as
50780Sstevel@tonic-gate * "really stuck".
50790Sstevel@tonic-gate * If all running logger threads become "really stuck" state, there
50800Sstevel@tonic-gate * should be no worth waiting for them to quit.
50810Sstevel@tonic-gate * In that case, we will go ahead and close out file descriptors to
50820Sstevel@tonic-gate * have them pull out from hanging system call, and give them a last
50830Sstevel@tonic-gate * chance(LOOP_INTERVAL sec) to quit.
50840Sstevel@tonic-gate */
50850Sstevel@tonic-gate
50860Sstevel@tonic-gate if (Debug) {
50870Sstevel@tonic-gate tim = time(NULL);
50880Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: awaiting logit() to be"
50896358Snakanon " shutdown\n", mythreadno, ctime_r(&tim, cbuf)+4);
50900Sstevel@tonic-gate }
50910Sstevel@tonic-gate
50920Sstevel@tonic-gate cnt = 0;
50930Sstevel@tonic-gate really_stuck = 0;
50940Sstevel@tonic-gate while (cnt < (LOOP_MAX/LOOP_INTERVAL) &&
50956358Snakanon conf_threads > really_stuck) {
50960Sstevel@tonic-gate
50970Sstevel@tonic-gate /* save initial queue count */
50980Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
50990Sstevel@tonic-gate f->f_prev_queue_count = (f->f_type == F_UNUSED) ?
51006358Snakanon -1 : f->f_queue_count;
51010Sstevel@tonic-gate }
51020Sstevel@tonic-gate
51030Sstevel@tonic-gate for (loop = 0; loop < LOOP_INTERVAL; loop++) {
51040Sstevel@tonic-gate if (conf_threads == 0)
51050Sstevel@tonic-gate break;
51060Sstevel@tonic-gate (void) sleep(1);
51070Sstevel@tonic-gate }
51080Sstevel@tonic-gate
51090Sstevel@tonic-gate if (conf_threads == 0)
51100Sstevel@tonic-gate break;
51110Sstevel@tonic-gate
51120Sstevel@tonic-gate if (Debug) {
51130Sstevel@tonic-gate tim = time(NULL);
51140Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: "
51156358Snakanon "%d threads are still alive.\n",
51166358Snakanon mythreadno, ctime_r(&tim, cbuf)+4,
51176358Snakanon conf_threads);
51180Sstevel@tonic-gate }
51190Sstevel@tonic-gate
51200Sstevel@tonic-gate really_stuck = 0;
51210Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
51220Sstevel@tonic-gate if (f->f_type == F_UNUSED) {
51230Sstevel@tonic-gate f->f_prev_queue_count = -1;
51240Sstevel@tonic-gate continue;
51250Sstevel@tonic-gate }
51260Sstevel@tonic-gate if (f->f_prev_queue_count == f->f_queue_count) {
51270Sstevel@tonic-gate really_stuck++;
51280Sstevel@tonic-gate f->f_prev_queue_count = 1;
51290Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): "
51306358Snakanon "tid=%d is really stuck.\n",
51316358Snakanon mythreadno, f->f_thread);
51320Sstevel@tonic-gate } else {
51330Sstevel@tonic-gate f->f_prev_queue_count = 0;
51340Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): "
51356358Snakanon "tid=%d is still active.\n",
51366358Snakanon mythreadno, f->f_thread);
51370Sstevel@tonic-gate }
51380Sstevel@tonic-gate }
51390Sstevel@tonic-gate /*
51400Sstevel@tonic-gate * Here we have one of following values in the
51410Sstevel@tonic-gate * f_prev_queue_count:
51420Sstevel@tonic-gate * 0: logger thread is still actively working.
51430Sstevel@tonic-gate * 1: logger thread is really stuck.
51440Sstevel@tonic-gate * -1: logger thread has already died.
51450Sstevel@tonic-gate */
51460Sstevel@tonic-gate
51470Sstevel@tonic-gate cnt++;
51480Sstevel@tonic-gate }
51490Sstevel@tonic-gate
51500Sstevel@tonic-gate if (Debug) {
51510Sstevel@tonic-gate tim = time(NULL);
51520Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s:"
51536358Snakanon " complete awaiting logit()\n",
51546358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
51550Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %d threads alive."
51566358Snakanon " %d threads stuck\n",
51576358Snakanon mythreadno, conf_threads, really_stuck);
51580Sstevel@tonic-gate }
51590Sstevel@tonic-gate
51600Sstevel@tonic-gate /*
51610Sstevel@tonic-gate * Still running? If so, mark it as UNUSED, and close
51620Sstevel@tonic-gate * the fd so that logger threads can bail out from the loop.
51630Sstevel@tonic-gate */
51640Sstevel@tonic-gate drops = 0;
51650Sstevel@tonic-gate if (conf_threads) {
51660Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
51670Sstevel@tonic-gate if (f->f_type == F_CONSOLE &&
51686358Snakanon f->f_prev_queue_count == 1) {
51690Sstevel@tonic-gate /* console is really stuck */
51700Sstevel@tonic-gate console_stuck = 1;
51710Sstevel@tonic-gate }
51720Sstevel@tonic-gate if (f->f_type == F_USERS || f->f_type == F_WALL ||
51736358Snakanon f->f_type == F_UNUSED)
51740Sstevel@tonic-gate continue;
51750Sstevel@tonic-gate cnt = f->f_queue_count;
51760Sstevel@tonic-gate drops += (cnt > 0) ? cnt - 1: 0;
51770Sstevel@tonic-gate f->f_type = F_UNUSED;
51780Sstevel@tonic-gate
51790Sstevel@tonic-gate if (f->f_orig_type == F_FORW)
51802104Sjjj (void) t_close(f->f_file);
51810Sstevel@tonic-gate else
51822104Sjjj (void) close(f->f_file);
51830Sstevel@tonic-gate }
51840Sstevel@tonic-gate
51850Sstevel@tonic-gate if (Debug) {
51860Sstevel@tonic-gate tim = time(NULL);
51870Sstevel@tonic-gate DPRINT1(3, "reconfigure(%u): terminating logit()\n",
51886358Snakanon mythreadno);
51890Sstevel@tonic-gate }
51900Sstevel@tonic-gate
51910Sstevel@tonic-gate /* last chance to exit */
51920Sstevel@tonic-gate for (loop = 0; loop < LOOP_MAX; loop++) {
51930Sstevel@tonic-gate if (conf_threads == 0)
51940Sstevel@tonic-gate break;
51950Sstevel@tonic-gate (void) sleep(1);
51960Sstevel@tonic-gate }
51970Sstevel@tonic-gate
51980Sstevel@tonic-gate if (Debug) {
51990Sstevel@tonic-gate tim = time(NULL);
52000Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: %d alive\n",
52016358Snakanon mythreadno, ctime_r(&tim, cbuf)+4,
52026358Snakanon conf_threads);
52030Sstevel@tonic-gate }
52040Sstevel@tonic-gate }
52050Sstevel@tonic-gate
52060Sstevel@tonic-gate if (conf_threads == 0 && drops) {
52070Sstevel@tonic-gate errno = 0;
52080Sstevel@tonic-gate logerror("Could not completely output pending messages"
52096358Snakanon " while preparing re-configuration");
52100Sstevel@tonic-gate logerror("discarded %d messages and restart configuration.",
52116358Snakanon drops);
52120Sstevel@tonic-gate if (Debug) {
52130Sstevel@tonic-gate tim = time(NULL);
52140Sstevel@tonic-gate DPRINT3(3, "reconfigure(%u): %.15s: "
52156358Snakanon "discarded %d messages\n",
52166358Snakanon mythreadno, ctime_r(&tim, cbuf)+4, drops);
52170Sstevel@tonic-gate }
52180Sstevel@tonic-gate }
52190Sstevel@tonic-gate
52200Sstevel@tonic-gate /*
52210Sstevel@tonic-gate * If all threads still haven't exited
52220Sstevel@tonic-gate * something is stuck or hosed. We just
52230Sstevel@tonic-gate * have no option but to exit.
52240Sstevel@tonic-gate */
52250Sstevel@tonic-gate if (conf_threads) {
52260Sstevel@tonic-gate thread_stuck:
52270Sstevel@tonic-gate if (Debug) {
52280Sstevel@tonic-gate tim = time(NULL);
52290Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: really stuck\n",
52306358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
52310Sstevel@tonic-gate }
52320Sstevel@tonic-gate
52330Sstevel@tonic-gate shutdown_input();
52340Sstevel@tonic-gate delete_doorfiles();
52352104Sjjj (void) uname(&up);
52362104Sjjj
52372104Sjjj (void) snprintf(buf, sizeof (buf),
52386358Snakanon "syslogd(%s): some logger thread(s) "
52396358Snakanon "are stuck%s; syslogd is shutting down.",
52406358Snakanon up.nodename,
52416358Snakanon console_stuck ? " (including the console)" : "");
52420Sstevel@tonic-gate
52430Sstevel@tonic-gate if (console_stuck) {
52440Sstevel@tonic-gate FILE *m = popen(MAILCMD, "w");
52450Sstevel@tonic-gate
52460Sstevel@tonic-gate if (m != NULL) {
52472104Sjjj (void) fprintf(m, "%s\n", buf);
52482104Sjjj (void) pclose(m);
52490Sstevel@tonic-gate }
52500Sstevel@tonic-gate }
52510Sstevel@tonic-gate
52520Sstevel@tonic-gate disable_errorlog();
52530Sstevel@tonic-gate logerror(buf);
52540Sstevel@tonic-gate exit(1);
52550Sstevel@tonic-gate }
52560Sstevel@tonic-gate
52570Sstevel@tonic-gate /* Free up some resources */
52580Sstevel@tonic-gate if (Files != (struct filed *)&fallback) {
52590Sstevel@tonic-gate for (f = Files; f < &Files[nlogs]; f++) {
52600Sstevel@tonic-gate (void) pthread_join(f->f_thread, NULL);
52610Sstevel@tonic-gate filed_destroy(f);
52620Sstevel@tonic-gate }
52630Sstevel@tonic-gate free(Files);
52640Sstevel@tonic-gate }
52650Sstevel@tonic-gate
52660Sstevel@tonic-gate dealloc_stacks(nlogs);
52670Sstevel@tonic-gate
52680Sstevel@tonic-gate if (Debug) {
52690Sstevel@tonic-gate tim = time(NULL);
52700Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: cleanup complete\n",
52716358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
52720Sstevel@tonic-gate }
52730Sstevel@tonic-gate
52740Sstevel@tonic-gate hnc_init(1); /* purge hostname cache */
52750Sstevel@tonic-gate conf_init(); /* start reconfigure */
52760Sstevel@tonic-gate
52770Sstevel@tonic-gate out:;
52780Sstevel@tonic-gate /* Now should be ready to dispatch error messages from syslogd. */
52790Sstevel@tonic-gate enable_errorlog();
52800Sstevel@tonic-gate
52810Sstevel@tonic-gate /* Wake up the log thread */
52820Sstevel@tonic-gate
52830Sstevel@tonic-gate if (Debug) {
52840Sstevel@tonic-gate tim = time(NULL);
52850Sstevel@tonic-gate DPRINT2(3, "reconfigure(%u): %.15s: resuming logmsg()\n",
52866358Snakanon mythreadno, ctime_r(&tim, cbuf)+4);
52870Sstevel@tonic-gate }
52880Sstevel@tonic-gate
52890Sstevel@tonic-gate (void) pthread_mutex_lock(&hup_lock);
52900Sstevel@tonic-gate hup_state = HUP_COMPLETED;
52910Sstevel@tonic-gate (void) pthread_cond_signal(&hup_done);
52920Sstevel@tonic-gate (void) pthread_mutex_unlock(&hup_lock);
52930Sstevel@tonic-gate }
52940Sstevel@tonic-gate
52950Sstevel@tonic-gate /*
52960Sstevel@tonic-gate * The following function implements simple hostname cache mechanism.
5297955Spd155743 * Host name cache is implemented through hash table bucket chaining method.
5298955Spd155743 * Collisions are handled by bucket chaining.
52990Sstevel@tonic-gate *
53000Sstevel@tonic-gate * hnc_init():
53010Sstevel@tonic-gate * allocate and initialize the cache. If reinit is set,
53020Sstevel@tonic-gate * invalidate all cache entries.
53030Sstevel@tonic-gate * hnc_look():
5304955Spd155743 * It hashes the ipaddress gets the index and walks thru the
5305955Spd155743 * single linked list. if cached entry was found, it will
5306955Spd155743 * put in the head of the list, and return.While going through
53070Sstevel@tonic-gate * the entries, an entry which has already expired will be invalidated.
53080Sstevel@tonic-gate * hnc_register():
5309955Spd155743 * Hashes the ipaddress finds the index and puts current entry to the list.
53100Sstevel@tonic-gate * hnc_unreg():
5311955Spd155743 * invalidate the cachep.
53120Sstevel@tonic-gate */
53130Sstevel@tonic-gate
53140Sstevel@tonic-gate static void
hnc_init(int reinit)53150Sstevel@tonic-gate hnc_init(int reinit)
53160Sstevel@tonic-gate {
53170Sstevel@tonic-gate struct hostname_cache **hpp;
53180Sstevel@tonic-gate pthread_t mythreadno;
5319955Spd155743 int i;
53200Sstevel@tonic-gate
53210Sstevel@tonic-gate if (Debug) {
53220Sstevel@tonic-gate mythreadno = pthread_self();
53230Sstevel@tonic-gate }
53240Sstevel@tonic-gate
53250Sstevel@tonic-gate if (reinit) {
53262104Sjjj (void) pthread_mutex_lock(&hnc_mutex);
53270Sstevel@tonic-gate
5328955Spd155743 for (i = 0; i < hnc_size; i++) {
5329955Spd155743 for (hpp = &hnc_cache[i]; *hpp != NULL; ) {
5330955Spd155743 hnc_unreg(hpp);
5331955Spd155743 }
53320Sstevel@tonic-gate }
53330Sstevel@tonic-gate
53342104Sjjj (void) pthread_mutex_unlock(&hnc_mutex);
53350Sstevel@tonic-gate DPRINT1(2, "hnc_init(%u): hostname cache re-configured\n",
53366358Snakanon mythreadno);
53370Sstevel@tonic-gate } else {
5338955Spd155743
5339955Spd155743 hnc_cache = calloc(hnc_size, sizeof (struct hostname_cache *));
53400Sstevel@tonic-gate
53410Sstevel@tonic-gate if (hnc_cache == NULL) {
53420Sstevel@tonic-gate MALLOC_FAIL("hostname cache");
53430Sstevel@tonic-gate logerror("hostname cache disabled");
53440Sstevel@tonic-gate return;
53450Sstevel@tonic-gate }
53460Sstevel@tonic-gate
53470Sstevel@tonic-gate DPRINT3(1, "hnc_init(%u): hostname cache configured %d entry"
53486358Snakanon " ttl:%d\n", mythreadno, hnc_size, hnc_ttl);
53490Sstevel@tonic-gate }
53500Sstevel@tonic-gate }
53510Sstevel@tonic-gate
53520Sstevel@tonic-gate static host_list_t *
hnc_lookup(struct netbuf * nbp,struct netconfig * ncp,int * hindex)5353955Spd155743 hnc_lookup(struct netbuf *nbp, struct netconfig *ncp, int *hindex)
53540Sstevel@tonic-gate {
53550Sstevel@tonic-gate struct hostname_cache **hpp, *hp;
53560Sstevel@tonic-gate time_t now;
53570Sstevel@tonic-gate pthread_t mythreadno;
5358955Spd155743 int index;
53590Sstevel@tonic-gate
53600Sstevel@tonic-gate if (Debug) {
53610Sstevel@tonic-gate mythreadno = pthread_self();
53620Sstevel@tonic-gate }
53630Sstevel@tonic-gate
53640Sstevel@tonic-gate if (hnc_cache == NULL) {
53650Sstevel@tonic-gate return (NULL);
53660Sstevel@tonic-gate }
53670Sstevel@tonic-gate
53682104Sjjj (void) pthread_mutex_lock(&hnc_mutex);
53690Sstevel@tonic-gate now = time(0);
53700Sstevel@tonic-gate
5371955Spd155743 *hindex = index = addr_hash(nbp);
5372955Spd155743
5373955Spd155743 for (hpp = &hnc_cache[index]; (hp = *hpp) != NULL; ) {
53740Sstevel@tonic-gate DPRINT4(10, "hnc_lookup(%u): check %p on %p for %s\n",
53756358Snakanon mythreadno, (void *)hp->h, (void *)hp,
53766358Snakanon hp->h->hl_hosts[0]);
53770Sstevel@tonic-gate
53780Sstevel@tonic-gate if (hp->expire < now) {
53790Sstevel@tonic-gate DPRINT2(9, "hnc_lookup(%u): purge %p\n",
53806358Snakanon mythreadno, (void *)hp);
53810Sstevel@tonic-gate hnc_unreg(hpp);
53820Sstevel@tonic-gate continue;
53830Sstevel@tonic-gate }
53840Sstevel@tonic-gate
53850Sstevel@tonic-gate if (ncp == hp->ncp && same_addr(&hp->addr, nbp)) {
53860Sstevel@tonic-gate /*
53870Sstevel@tonic-gate * found!
53880Sstevel@tonic-gate * Put the entry at the top.
53890Sstevel@tonic-gate */
53900Sstevel@tonic-gate
5391955Spd155743 if (hp != hnc_cache[index]) {
53920Sstevel@tonic-gate /* unlink from active list */
53930Sstevel@tonic-gate *hpp = (*hpp)->next;
53940Sstevel@tonic-gate /* push it onto the top */
5395955Spd155743 hp->next = hnc_cache[index];
5396955Spd155743 hnc_cache[index] = hp;
53970Sstevel@tonic-gate }
53980Sstevel@tonic-gate
53992104Sjjj (void) pthread_mutex_lock(&hp->h->hl_mutex);
54000Sstevel@tonic-gate hp->h->hl_refcnt++;
54012104Sjjj (void) pthread_mutex_unlock(&hp->h->hl_mutex);
54020Sstevel@tonic-gate
54030Sstevel@tonic-gate DPRINT4(9, "hnc_lookup(%u): found %p on %p for %s\n",
54046358Snakanon mythreadno, (void *)hp->h, (void *)hp,
54056358Snakanon hp->h->hl_hosts[0]);
54062104Sjjj
54072104Sjjj (void) pthread_mutex_unlock(&hnc_mutex);
54080Sstevel@tonic-gate return (hp->h);
54090Sstevel@tonic-gate }
54100Sstevel@tonic-gate
54110Sstevel@tonic-gate hpp = &hp->next;
54120Sstevel@tonic-gate }
54130Sstevel@tonic-gate
54142104Sjjj (void) pthread_mutex_unlock(&hnc_mutex);
54150Sstevel@tonic-gate return (NULL);
54160Sstevel@tonic-gate }
54170Sstevel@tonic-gate
54180Sstevel@tonic-gate static void
hnc_register(struct netbuf * nbp,struct netconfig * ncp,host_list_t * h,int hindex)5419955Spd155743 hnc_register(struct netbuf *nbp, struct netconfig *ncp,
5420955Spd155743 host_list_t *h, int hindex)
54210Sstevel@tonic-gate {
5422955Spd155743 struct hostname_cache **hpp, **tailp, *hp, *entry;
54230Sstevel@tonic-gate void *addrbuf;
54240Sstevel@tonic-gate time_t now;
54250Sstevel@tonic-gate pthread_t mythreadno;
5426955Spd155743 int i;
54270Sstevel@tonic-gate
54280Sstevel@tonic-gate if (Debug) {
54290Sstevel@tonic-gate mythreadno = pthread_self();
54300Sstevel@tonic-gate }
54310Sstevel@tonic-gate
54320Sstevel@tonic-gate if (hnc_cache == NULL) {
54330Sstevel@tonic-gate return;
54340Sstevel@tonic-gate }
54350Sstevel@tonic-gate
54360Sstevel@tonic-gate if ((addrbuf = malloc(nbp->len)) == NULL) {
54370Sstevel@tonic-gate MALLOC_FAIL("pushing hostname cache");
54380Sstevel@tonic-gate return;
54390Sstevel@tonic-gate }
54400Sstevel@tonic-gate
5441955Spd155743 if ((entry = malloc(sizeof (struct hostname_cache))) == NULL) {
5442955Spd155743 MALLOC_FAIL("pushing hostname entry");
5443955Spd155743 free(addrbuf);
5444955Spd155743 return;
5445955Spd155743 }
5446955Spd155743
54472104Sjjj (void) pthread_mutex_lock(&hnc_mutex);
54480Sstevel@tonic-gate
5449955Spd155743 i = 0;
5450955Spd155743
5451955Spd155743 now = time(0);
5452955Spd155743 /*
5453955Spd155743 * first go through active list, and discard the
5454955Spd155743 * caches which has been invalid. Count number of
5455955Spd155743 * non-expired buckets.
5456955Spd155743 */
5457955Spd155743
5458955Spd155743 for (hpp = &hnc_cache[hindex]; (hp = *hpp) != NULL; ) {
5459955Spd155743 tailp = hpp;
5460955Spd155743
5461955Spd155743 if (hp->expire < now) {
5462955Spd155743 DPRINT2(9, "hnc_register(%u): discard %p\n",
54636358Snakanon mythreadno, (void *)hp);
5464955Spd155743 hnc_unreg(hpp);
5465955Spd155743 } else {
5466955Spd155743 i++;
5467955Spd155743 hpp = &hp->next;
54680Sstevel@tonic-gate }
5469955Spd155743 }
5470955Spd155743
5471955Spd155743 /*
5472955Spd155743 * If max limit of chained hash buckets has been used up
5473955Spd155743 * delete the least active element in the chain.
5474955Spd155743 */
5475955Spd155743 if (i == MAX_BUCKETS) {
5476955Spd155743 hnc_unreg(tailp);
5477955Spd155743 }
54780Sstevel@tonic-gate
54790Sstevel@tonic-gate (void) memcpy(addrbuf, nbp->buf, nbp->len);
5480955Spd155743 entry->addr.len = nbp->len;
5481955Spd155743 entry->addr.buf = addrbuf;
5482955Spd155743 entry->ncp = ncp;
5483955Spd155743 entry->h = h;
5484955Spd155743 entry->expire = time(NULL) + hnc_ttl;
5485955Spd155743
5486955Spd155743 /* insert it at the top */
5487955Spd155743 entry->next = hnc_cache[hindex];
5488955Spd155743 hnc_cache[hindex] = entry;
54890Sstevel@tonic-gate
54900Sstevel@tonic-gate /*
54910Sstevel@tonic-gate * As far as cache is valid, corresponding host_list must
54920Sstevel@tonic-gate * also be valid. Increments the refcnt to avoid freeing
54930Sstevel@tonic-gate * host_list.
54940Sstevel@tonic-gate */
54950Sstevel@tonic-gate h->hl_refcnt++;
54960Sstevel@tonic-gate DPRINT4(9, "hnc_register(%u): reg %p onto %p for %s\n",
5497*8094SVladimir.Marek@Sun.COM mythreadno, (void *)entry->h, (void *)entry, entry->h->hl_hosts[0]);
54982104Sjjj (void) pthread_mutex_unlock(&hnc_mutex);
54990Sstevel@tonic-gate }
55000Sstevel@tonic-gate
55010Sstevel@tonic-gate static void
hnc_unreg(struct hostname_cache ** hpp)55020Sstevel@tonic-gate hnc_unreg(struct hostname_cache **hpp)
55030Sstevel@tonic-gate {
55040Sstevel@tonic-gate struct hostname_cache *hp = *hpp;
55050Sstevel@tonic-gate pthread_t mythreadno;
55060Sstevel@tonic-gate
55070Sstevel@tonic-gate if (Debug) {
55080Sstevel@tonic-gate mythreadno = pthread_self();
55090Sstevel@tonic-gate }
55100Sstevel@tonic-gate
55110Sstevel@tonic-gate DPRINT4(9, "hnc_unreg(%u): unreg %p on %p for %s\n",
55126358Snakanon mythreadno, (void *)hp->h, (void *)hp, hp->h->hl_hosts[0]);
55130Sstevel@tonic-gate free(hp->addr.buf);
55140Sstevel@tonic-gate freehl(hp->h);
55150Sstevel@tonic-gate
55160Sstevel@tonic-gate /* unlink from active list */
55170Sstevel@tonic-gate *hpp = (*hpp)->next;
55180Sstevel@tonic-gate
5519955Spd155743 free(hp);
55200Sstevel@tonic-gate }
55210Sstevel@tonic-gate
55220Sstevel@tonic-gate /*
55230Sstevel@tonic-gate * Once this is called, error messages through logerror() will go to
55240Sstevel@tonic-gate * the console immediately. Also, messages are queued into the tmpq
55250Sstevel@tonic-gate * to be able to later put them into inputq.
55260Sstevel@tonic-gate */
55270Sstevel@tonic-gate static void
disable_errorlog()55280Sstevel@tonic-gate disable_errorlog()
55290Sstevel@tonic-gate {
55302104Sjjj (void) dataq_init(&tmpq);
55312104Sjjj
55322104Sjjj (void) pthread_mutex_lock(&logerror_lock);
55330Sstevel@tonic-gate interrorlog = 0;
55342104Sjjj (void) pthread_mutex_unlock(&logerror_lock);
55350Sstevel@tonic-gate }
55360Sstevel@tonic-gate
55370Sstevel@tonic-gate /*
55380Sstevel@tonic-gate * Turn internal error messages to regular input stream.
55390Sstevel@tonic-gate * All pending messages are pulled and pushed into the regular
55400Sstevel@tonic-gate * input queue.
55410Sstevel@tonic-gate */
55420Sstevel@tonic-gate static void
enable_errorlog()55430Sstevel@tonic-gate enable_errorlog()
55440Sstevel@tonic-gate {
55450Sstevel@tonic-gate log_message_t *mp;
55460Sstevel@tonic-gate
55472104Sjjj (void) pthread_mutex_lock(&logerror_lock);
55480Sstevel@tonic-gate interrorlog = 1;
55492104Sjjj (void) pthread_mutex_unlock(&logerror_lock);
55500Sstevel@tonic-gate
55510Sstevel@tonic-gate /*
55520Sstevel@tonic-gate * push all the pending messages into inputq.
55530Sstevel@tonic-gate */
55540Sstevel@tonic-gate while (dataq_dequeue(&tmpq, (void **)&mp, 1) == 0) {
55550Sstevel@tonic-gate (void) dataq_enqueue(&inputq, mp);
55560Sstevel@tonic-gate }
55572104Sjjj (void) dataq_destroy(&tmpq);
55580Sstevel@tonic-gate }
5559955Spd155743
5560955Spd155743 /*
5561955Spd155743 * Generate a hash value of the given address and derive
5562955Spd155743 * an index into the hnc_cache hashtable.
5563955Spd155743 * The hashing method is similar to what Java does for strings.
5564955Spd155743 */
5565955Spd155743 static int
addr_hash(struct netbuf * nbp)5566955Spd155743 addr_hash(struct netbuf *nbp)
5567955Spd155743 {
5568955Spd155743 char *uap;
5569955Spd155743 int i;
5570955Spd155743 unsigned long hcode = 0;
5571955Spd155743
5572955Spd155743 uap = nbp->buf;
5573955Spd155743
5574955Spd155743 if (uap == NULL) {
5575955Spd155743 return (0);
5576955Spd155743 }
5577955Spd155743
5578955Spd155743 /*
5579955Spd155743 * Compute a hashcode of the address string
5580955Spd155743 */
5581955Spd155743 for (i = 0; i < nbp->len; i++)
5582955Spd155743 hcode = (31 * hcode) + uap[i];
5583955Spd155743
5584955Spd155743 /*
5585955Spd155743 * Scramble the hashcode for better distribution
5586955Spd155743 */
5587955Spd155743 hcode += ~(hcode << 9);
5588955Spd155743 hcode ^= (hcode >> 14);
5589955Spd155743 hcode += (hcode << 4);
5590955Spd155743 hcode ^= (hcode >> 10);
5591955Spd155743
5592955Spd155743 return ((int)(hcode % hnc_size));
5593955Spd155743 }
5594