diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2010-04-15 17:59:38 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2010-04-15 17:59:38 +0200 |
commit | b00e7946e8dec90270f35c1060ac6d0abfe9df3e (patch) | |
tree | f28798d5f59b56e5843fbdc884343c07bc7d6d45 /plugins/imsolaris | |
parent | f0e1a6588f96820a785b6b1940efcfad7ff85625 (diff) | |
download | rsyslog-b00e7946e8dec90270f35c1060ac6d0abfe9df3e.tar.gz rsyslog-b00e7946e8dec90270f35c1060ac6d0abfe9df3e.tar.xz rsyslog-b00e7946e8dec90270f35c1060ac6d0abfe9df3e.zip |
first version of imsolaris created, cleanup for solaris done
more cleanup required, but things now basically work
Diffstat (limited to 'plugins/imsolaris')
-rw-r--r-- | plugins/imsolaris/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/imsolaris/imsolaris.c | 281 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.c | 532 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.h | 5 |
4 files changed, 824 insertions, 0 deletions
diff --git a/plugins/imsolaris/Makefile.am b/plugins/imsolaris/Makefile.am new file mode 100644 index 00000000..2980fc6f --- /dev/null +++ b/plugins/imsolaris/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = imsolaris.la + +imsolaris_la_SOURCES = imsolaris.c sun_cddl.c sun_cddl.h +imsolaris_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) +imsolaris_la_LDFLAGS = -module -avoid-version +imsolaris_la_LIBADD = -ldoor -lpthread diff --git a/plugins/imsolaris/imsolaris.c b/plugins/imsolaris/imsolaris.c new file mode 100644 index 00000000..a2238a29 --- /dev/null +++ b/plugins/imsolaris/imsolaris.c @@ -0,0 +1,281 @@ +/* imsolaris.c + * This input module is used to gather local log data under Solaris. This + * includes messages from local applications AS WELL AS the kernel log. + * I first considered to make all of this available via imklog, but that + * did not lock appropriately on second thought. So I created this module + * that does anything for local message recption. + * + * This module is not meant to be used on plaforms other than Solaris. As + * such, trying to compile it elswhere will probably fail with all sorts + * of errors. + * + * Some notes on the Solaris syslog mechanism: + * Both system (kernel) and application log messages are provided via + * a single message stream. + * + * Solaris checks if the syslogd is running. If so, syslog() emits messages + * to the log socket, only. Otherwise, it emits messages to the console. + * It is possible to gather these console messages as well. However, then + * we clutter the console. + * Solaris does this "syslogd alive check" in a somewhat unexpected way + * (at least unexpected for me): it uses the so-called "door" mechanism, a + * fast RPC facility. I first thought that the door API was used to submit + * the actual syslog messages. But this is not the case. Instead, a door + * call is done, and the server process inside rsyslog simply does NOTHING + * but return. All that Solaris sylsogd() is interested in is if the door + * server (we) responds and thus can be considered alive. The actual message + * is then submitted via the usual stream. I have to admit I do not + * understand why the message itself is not passed via this high-performance + * API. But anyhow, that's nothing I can change, so the most important thing + * is to note how Solaris does this thing ;) + * The syslog() library call checks syslogd state for *each* call (what a + * waste of time...) and decides each time if the message should go to the + * console or not. According to OpenSolaris sources, it looks like there is + * message loss potential when the door file is created before all data has + * been pulled from the stream. While I have to admit that I do not fully + * understand that problem, I will follow the original code advise and do + * one complete pull cycle on the log socket (until it has no further data + * available) and only thereafter create the door file and start the "regular" + * pull cycle. As of my understanding, there is a minimal race between the + * point where the intial pull cycle has ended and the door file is created, + * but that race is also present in OpenSolaris syslogd code, so it should + * not matter that much (plus, I do not know how to avoid it...) + * + * File begun on 2010-04-15 by RGerhards + * + * Copyright 2010 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include "rsyslog.h" +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <stropts.h> +#include <sys/strlog.h> +#include <errno.h> +#include "dirty.h" +#include "cfsysline.h" +#include "unicode-helper.h" +#include "module-template.h" +#include "srUtils.h" +#include "errmsg.h" +#include "net.h" +#include "glbl.h" +#include "msg.h" +#include "prop.h" +#include "sun_cddl.h" + +MODULE_TYPE_INPUT + +/* defines */ +#define PATH_LOG "/dev/log" + + +/* Module static data */ +DEF_IMOD_STATIC_DATA +DEFobjCurrIf(errmsg) +DEFobjCurrIf(glbl) +DEFobjCurrIf(prop) + + +static int logfd = -1; /* file descriptor to access the system log */ + + +/* config settings */ +static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */ +static char *LogName = NULL; /* the log socket name TODO: make configurable! */ + + + +/* This function receives data from a socket indicated to be ready + * to receive and submits the message received for processing. + * rgerhards, 2007-12-20 + * Interface changed so that this function is passed the array index + * of the socket which is to be processed. This eases access to the + * growing number of properties. -- rgerhards, 2008-08-01 + */ +rsRetVal +solaris_readLog(int fd) +{ + DEFiRet; + int iRcvd; + int iMaxLine; + struct strbuf data; + struct strbuf ctl; + struct log_ctl hdr; + int flags; + msg_t *pMsg; + int ret; + uchar bufRcv[4096+1]; + uchar *pRcv = NULL; /* receive buffer */ + char errStr[1024]; + uchar fmtBuf[10240]; // TODO: use better solution + + assert(logfd >= 0); + + iMaxLine = glbl.GetMaxLine(); + + /* we optimize performance: if iMaxLine is below 4K (which it is in almost all + * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory + * is used. We could use alloca() to achive a similar aspect, but there are so + * many issues with alloca() that I do not want to take that route. + * rgerhards, 2008-09-02 + */ + if((size_t) iMaxLine < sizeof(bufRcv) - 1) { + pRcv = bufRcv; + } else { + CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))); + } + + data.buf = (char*)pRcv; + data.maxlen = iMaxLine; + ctl.maxlen = sizeof (struct log_ctl); + ctl.buf = (caddr_t)&hdr; + flags = 0; + ret = getmsg(fd, &ctl, &data, &flags); + if(ret < 0) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + dbgprintf("imsolaris: getmsg() error on fd %d: %s.\n", fd, errStr); + } + dbgprintf("imsolaris: getmsg() returns %d\n", ret); + dbgprintf("imsolaris: message from log socket: #%d: %s\n", fd, pRcv); + if (1) {//iRcvd > 0) { + // TODO: use hdr info! This whole section is a work-around to get + // it going. +#if 0 + CHKiRet(msgConstruct(&pMsg)); + //MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); + MsgSetInputName(pMsg, pInputName); + MsgSetRawMsg(pMsg, (char*)pRcv, strlen((char*)pRcv)); + MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ + MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); + //MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag); + //pMsg->iFacility = LOG_FAC(pInfo->iFacility); + //pMsg->iSeverity = LOG_PRI(pInfo->iSeverity); + pMsg->bParseHOSTNAME = 0; + CHKiRet(submitMsg(pMsg)); +#else + iRcvd = snprintf((char*)fmtBuf, sizeof(fmtBuf), "<%d>%s", hdr.pri, (char*) pRcv); + parseAndSubmitMessage(glbl.GetLocalHostName(), + (uchar*)"127.0.0.1", fmtBuf, + iRcvd, 0, + 0, pInputName, NULL, 0); +#endif + } else if (iRcvd < 0 && errno != EINTR) { + int en = errno; + rs_strerror_r(en, errStr, sizeof(errStr)); + dbgprintf("imsolaris: stream error: %d = %s.\n", errno, errStr); + //errmsg.LogError(en, NO_ERRCODE, "imsolaris: socket error UNIX"); + } + +finalize_it: + if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1) + free(pRcv); + + RETiRet; +} + + +/* This function is called to gather input. */ +BEGINrunInput +CODESTARTrunInput + /* this is an endless loop - it is terminated when the thread is + * signalled to do so. This, however, is handled by the framework, + * right into the sleep below. + */ + + dbgprintf("imsolaris: prepare_sys_poll()\n"); + prepare_sys_poll(); + + /* note: sun's syslogd code claims that the door should only + * be opened when the log socket has been polled. So file header + * comment of this file for more details. + */ + sun_open_door(); + dbgprintf("imsolaris: starting regular poll loop\n"); + while(1) { + sun_sys_poll(); + } + + RETiRet; +ENDrunInput + + +BEGINwillRun +CODESTARTwillRun + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imsolaris"), sizeof("imsolaris") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + + iRet = sun_openklog((LogName == NULL) ? PATH_LOG : LogName, &logfd); + dbgprintf("imsolaris opened system log socket as fd %d\n", logfd); + if(iRet != RS_RET_OK) { + errmsg.LogError(0, iRet, "error opening system log socket"); + } +finalize_it: +ENDwillRun + + +BEGINafterRun +CODESTARTafterRun + /* do cleanup here */ + if(pInputName != NULL) + prop.Destruct(&pInputName); +ENDafterRun + + +BEGINmodExit +CODESTARTmodExit + sun_delete_doorfiles(); + objRelease(glbl, CORE_COMPONENT); + objRelease(errmsg, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_IMOD_QUERIES +ENDqueryEtryPt + +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +{ + return RS_RET_OK; +} + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(errmsg, CORE_COMPONENT)); + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); + + dbgprintf("imsolaris version %s initializing\n", PACKAGE_VERSION); + + /* register config file handlers */ + CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, + resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); +ENDmodInit +/* vim:set ai: + */ diff --git a/plugins/imsolaris/sun_cddl.c b/plugins/imsolaris/sun_cddl.c new file mode 100644 index 00000000..1de23660 --- /dev/null +++ b/plugins/imsolaris/sun_cddl.c @@ -0,0 +1,532 @@ +#define MAXLINE 4096 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Portions Copyright 2010 by Rainer Gerhards and Adiscon + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T + * All Rights Reserved + */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ +#include <unistd.h> +#include <note.h> +#include <errno.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <ctype.h> +#include <signal.h> +#include <string.h> +#include <strings.h> +#include <libscf.h> +#include <netconfig.h> +#include <netdir.h> +#include <pwd.h> +#include <sys/socket.h> +#include <tiuser.h> +#include <utmpx.h> +#include <limits.h> +#include <pthread.h> +#include <fcntl.h> +#include <stropts.h> +#include <assert.h> +#include <sys/statvfs.h> + +#include <sys/param.h> +#include <sys/sysmacros.h> +#include <sys/syslog.h> +#include <sys/strlog.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/utsname.h> +#include <sys/poll.h> +#include <sys/wait.h> +#include <sys/resource.h> +#include <sys/mman.h> +#include <sys/note.h> +#include <door.h> +#include <sys/door.h> + +#include "rsyslog.h" +#include "srUtils.h" +#include "debug.h" + +#define DOORFILE "/var/run/syslog_door" +#define RELATIVE_DOORFILE "../var/run/syslog_door" +#define OLD_DOORFILE "/etc/.syslog_door" + +static struct pollfd Pfd; /* Pollfd for local the log device */ + +static int DoorFd = -1; +static int DoorCreated = 0; +static char *DoorFileName = DOORFILE; + +/* for managing door server threads */ +static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER; +static uint_t door_server_cnt = 0; +static pthread_attr_t door_thr_attr; + +/* + * the 'server' function that we export via the door. It does + * nothing but return. + */ +/*ARGSUSED*/ +static void +server(void __attribute__((unused)) *cookie, char __attribute__((unused)) *argp, size_t __attribute__((unused)) arg_size, + door_desc_t __attribute__((unused)) *dp, __attribute__((unused)) uint_t n) +{ + (void) door_return(NULL, 0, NULL, 0); + /* NOTREACHED */ +} + +/*ARGSUSED*/ +static void * +create_door_thr(void __attribute__((unused)) *arg) +{ + (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + (void) door_return(NULL, 0, NULL, 0); + + /* + * If there is an error in door_return(), it will return here and + * the thread will exit. Hence we need to decrement door_server_cnt. + */ + (void) pthread_mutex_lock(&door_server_cnt_lock); + door_server_cnt--; + (void) pthread_mutex_unlock(&door_server_cnt_lock); + return (NULL); +} + +/* + * Max number of door server threads for syslogd. Since door is used + * to check the health of syslogd, we don't need large number of + * server threads. + */ +#define MAX_DOOR_SERVER_THR 3 + +/* + * Manage door server thread pool. + */ +/*ARGSUSED*/ +static void +door_server_pool(door_info_t __attribute__((unused)) *dip) +{ + (void) pthread_mutex_lock(&door_server_cnt_lock); + if (door_server_cnt <= MAX_DOOR_SERVER_THR && + pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) { + door_server_cnt++; + (void) pthread_mutex_unlock(&door_server_cnt_lock); + return; + } + + (void) pthread_mutex_unlock(&door_server_cnt_lock); +} + +void +sun_delete_doorfiles(void) +{ + pthread_t mythreadno; + struct stat sb; + int err; + char line[MAXLINE+1]; + + if (Debug) { + mythreadno = pthread_self(); + } + + + if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) { + if (unlink(DoorFileName) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed - fatal", DoorFileName); + errno = err; + DBGPRINTF("%s", line);//logerror(line); + DBGPRINTF("delete_doorfiles(%u): error: %s, " + "errno=%d\n", mythreadno, line, err); + exit(1); + } + + DBGPRINTF("delete_doorfiles(%u): deleted %s\n", + mythreadno, DoorFileName); + } + + if (strcmp(DoorFileName, DOORFILE) == 0) { + if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) { + if (unlink(OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed", OLD_DOORFILE); + DBGPRINTF("delete_doorfiles(%u): %s\n", + mythreadno, line); + + if (err != EROFS) { + errno = err; + (void) strlcat(line, " - fatal", + sizeof (line)); + //logerror(line); + DBGPRINTF("delete_doorfiles(%u): " + "error: %s, errno=%d\n", + mythreadno, line, err); + exit(1); + } + + DBGPRINTF("delete_doorfiles(%u): unlink() " + "failure OK on RO file system\n", + mythreadno); + } + + DBGPRINTF("delete_doorfiles(%u): deleted %s\n", + mythreadno, OLD_DOORFILE); + } + } + + if (DoorFd != -1) { + (void) door_revoke(DoorFd); + } + + DBGPRINTF("delete_doorfiles(%u): revoked door: DoorFd=%d\n", + mythreadno, DoorFd); +} + + +/* Create the door file. If the filesystem + * containing /etc is writable, create symlinks /etc/.syslog_door + * to them. On systems that do not support /var/run, create + * /etc/.syslog_door directly. + */ + +void +sun_open_door(void) +{ + struct stat buf; + door_info_t info; + char line[MAXLINE+1]; + pthread_t mythreadno; + int err; + + if (Debug) { + mythreadno = pthread_self(); + } + + /* + * first see if another syslogd is running by trying + * a door call - if it succeeds, there is already + * a syslogd process active + */ + + if (!DoorCreated) { + int door; + + if ((door = open(DoorFileName, O_RDONLY)) >= 0) { + DBGPRINTF("open_door(%u): %s opened " + "successfully\n", mythreadno, DoorFileName); + + if (door_info(door, &info) >= 0) { + DBGPRINTF("open_door(%u): " + "door_info:info.di_target = %ld\n", + mythreadno, info.di_target); + + if (info.di_target > 0) { + (void) sprintf(line, "syslogd pid %ld" + " already running. Cannot " + "start another syslogd pid %ld", + info.di_target, getpid()); + DBGPRINTF("open_door(%u): error: " + "%s\n", mythreadno, line); + errno = 0; + //logerror(line); + exit(1); + } + } + + (void) close(door); + } else { + if (lstat(DoorFileName, &buf) < 0) { + err = errno; + + DBGPRINTF("open_door(%u): lstat() of %s " + "failed, errno=%d\n", + mythreadno, DoorFileName, err); + + if ((door = creat(DoorFileName, 0644)) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "creat() of %s failed - fatal", + DoorFileName); + DBGPRINTF("open_door(%u): error: %s, " + "errno=%d\n", mythreadno, line, + err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + (void) fchmod(door, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + + DBGPRINTF("open_door(%u): creat() of %s " + "succeeded\n", mythreadno, + DoorFileName); + + (void) close(door); + } + } + + if (strcmp(DoorFileName, DOORFILE) == 0) { + if (lstat(OLD_DOORFILE, &buf) == 0) { + DBGPRINTF("open_door(%u): lstat() of %s " + "succeeded\n", mythreadno, + OLD_DOORFILE); + + if (S_ISDIR(buf.st_mode)) { + (void) snprintf(line, sizeof (line), + "%s is a directory - fatal", + OLD_DOORFILE); + DBGPRINTF("open_door(%u): error: " + "%s\n", mythreadno, line); + errno = 0; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door(%u): %s is not a " + "directory\n", + mythreadno, OLD_DOORFILE); + + if (unlink(OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "unlink() of %s failed", + OLD_DOORFILE); + DBGPRINTF("open_door(%u): %s\n", + mythreadno, line); + + if (err != EROFS) { + DBGPRINTF("open_door(%u): " + "error: %s, " + "errno=%d\n", + mythreadno, line, err); + (void) strcat(line, " - fatal"); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door(%u): unlink " + "failure OK on RO file " + "system\n", mythreadno); + } + } else { + DBGPRINTF("open_door(%u): file %s doesn't " + "exist\n", mythreadno, OLD_DOORFILE); + } + + if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), + "symlink %s -> %s failed", OLD_DOORFILE, + RELATIVE_DOORFILE); + DBGPRINTF("open_door(%u): %s\n", mythreadno, + line); + + if (err != EROFS) { + DBGPRINTF("open_door(%u): error: %s, " + "errno=%d\n", mythreadno, line, + err); + errno = err; + (void) strcat(line, " - fatal"); + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door(%u): symlink failure OK " + "on RO file system\n", mythreadno); + } else { + DBGPRINTF("open_door(%u): symlink %s -> %s " + "succeeded\n", mythreadno, + OLD_DOORFILE, RELATIVE_DOORFILE); + } + } + + if ((DoorFd = door_create(server, 0, + DOOR_REFUSE_DESC)) < 0) { + //???? DOOR_NO_CANEL requires newer libs??? DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { + err = errno; + (void) sprintf(line, "door_create() failed - fatal"); + DBGPRINTF("open_door(%u): error: %s, errno=%d\n", + mythreadno, line, err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0); + DBGPRINTF("open_door(%u): door_create() succeeded, " + "DoorFd=%d\n", mythreadno, DoorFd); + + DoorCreated = 1; + } + + (void) fdetach(DoorFileName); /* just in case... */ + + (void) door_server_create(door_server_pool); + + if (fattach(DoorFd, DoorFileName) < 0) { + err = errno; + (void) snprintf(line, sizeof (line), "fattach() of fd" + " %d to %s failed - fatal", DoorFd, DoorFileName); + DBGPRINTF("open_door(%u): error: %s, errno=%d\n", mythreadno, + line, err); + errno = err; + //logerror(line); + sun_delete_doorfiles(); + exit(1); + } + + DBGPRINTF("open_door(%u): attached server() to %s\n", mythreadno, + DoorFileName); + +} + + +/* Attempts to open the local log device + * and return a file descriptor. + */ +rsRetVal +sun_openklog(char *name, int *fd) +{ + DEFiRet; + struct strioctl str; + char errBuf[1024]; + + if((*fd = open(name, O_RDONLY)) < 0) { + rs_strerror_r(errno, errBuf, sizeof(errBuf)); + dbgprintf("imsolaris:openklog: cannot open %s: %s\n", + name, errBuf); + ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG); + } + str.ic_cmd = I_CONSLOG; + str.ic_timout = 0; + str.ic_len = 0; + str.ic_dp = NULL; + if (ioctl(*fd, I_STR, &str) < 0) { + rs_strerror_r(errno, errBuf, sizeof(errBuf)); + dbgprintf("imsolaris:openklog: cannot register to log " + "console messages: %s\n", errBuf); + ABORT_FINALIZE(RS_RET_ERR_AQ_CONLOG); + } + Pfd.fd = *fd; + Pfd.events = POLLIN; + dbgprintf("imsolaris/openklog: opened '%s' as fd %d.\n", name, *fd); + +finalize_it: + RETiRet; +} + + +/* this thread listens to the local stream log driver for log messages + * generated by this host, formats them, and queues them to the logger + * thread. + */ +/*ARGSUSED*/ +void +sun_sys_poll() +{ + int nfds; + + dbgprintf("imsolaris:sys_poll: sys_thread started\n"); + + for (;;) { + errno = 0; + + dbgprintf("imsolaris:sys_poll waiting for next message...\n"); + nfds = poll(&Pfd, 1, INFTIM); + + if (nfds == 0) + continue; + + if (nfds < 0) { + if (errno != EINTR) + dbgprintf("imsolaris:poll error"); + continue; + } + if (Pfd.revents & POLLIN) { + solaris_readLog(Pfd.fd); + } else { + /* TODO: shutdown, the rsyslog way (in v5!) -- check shutdown flag */ + if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { + // TODO: trigger retry logic +/* logerror("kernel log driver poll error"); + (void) close(Pfd.fd); + Pfd.fd = -1; + */ + } + } + + } + /*NOTREACHED*/ +} + + +/* Open the log device, and pull up all pending messages. + */ +void +prepare_sys_poll() +{ + int nfds; + + Pfd.events = POLLIN; + + for (;;) { + dbgprintf("imsolaris:prepare_sys_poll waiting for next message...\n"); + nfds = poll(&Pfd, 1, 0); + if (nfds <= 0) { + break; + } + + if (Pfd.revents & POLLIN) { + solaris_readLog(Pfd.fd); + } else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) { + //logerror("kernel log driver poll error"); + break; + } + } + +} diff --git a/plugins/imsolaris/sun_cddl.h b/plugins/imsolaris/sun_cddl.h new file mode 100644 index 00000000..0139b3d8 --- /dev/null +++ b/plugins/imsolaris/sun_cddl.h @@ -0,0 +1,5 @@ +rsRetVal sun_openklog(char *name, int *); +void prepare_sys_poll(void); +void sun_sys_poll(void); +void sun_open_door(void); +void sun_delete_doorfiles(void); |