summaryrefslogtreecommitdiffstats
path: root/plugins/imsolaris
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-09-15 15:17:47 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2011-09-15 15:17:47 +0200
commit1d0e4ba3b34464343c388ccef3ca8b08df42076a (patch)
treed17f746f7c8cb2f00aa3ab956740fd616e2390c0 /plugins/imsolaris
parentb7e69a240037277e77685af5ea5623cdd89ec2d2 (diff)
parent11ee5cbdfb08ba3e42a853c08144fa24cd55d6da (diff)
downloadrsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.tar.gz
rsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.tar.xz
rsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.zip
Merge branch 'v4-stable' of git+ssh://git.adiscon.com/git/rsyslog into v4-stable
Diffstat (limited to 'plugins/imsolaris')
-rw-r--r--plugins/imsolaris/Makefile.am6
-rw-r--r--plugins/imsolaris/imsolaris.c391
-rw-r--r--plugins/imsolaris/imsolaris.h2
-rw-r--r--plugins/imsolaris/sun_cddl.c419
-rw-r--r--plugins/imsolaris/sun_cddl.h7
5 files changed, 825 insertions, 0 deletions
diff --git a/plugins/imsolaris/Makefile.am b/plugins/imsolaris/Makefile.am
new file mode 100644
index 00000000..b4ee1c29
--- /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.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..6b07ba2b
--- /dev/null
+++ b/plugins/imsolaris/imsolaris.c
@@ -0,0 +1,391 @@
+/* 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 <unistd.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)
+
+
+/* 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! */
+
+
+/* a function to replace the sun logerror() function.
+ * It generates an error message from the supplied string. The main
+ * reason for not calling logError directly is that sun_cddl.c does not
+ * know or has acces to rsyslog objects (namely errmsg) -- and we do not
+ * want to do this effort. -- rgerhards, 2010-04-19
+ */
+void
+imsolaris_logerror(int err, char *errStr)
+{
+ errmsg.LogError(err, RS_RET_ERR_DOOR, "%s", errStr);
+}
+
+
+/* we try to recover a failed file by closing and re-opening
+ * it. We loop until the re-open works, but wait between each
+ * failure. If the open succeeds, we assume all is well. If it is
+ * not, we will run into the retry process with the next
+ * iteration.
+ * rgerhards, 2010-04-19
+ */
+static void
+tryRecover(void)
+{
+ int tryNum = 1;
+ int waitsecs;
+ int waitusecs;
+ rsRetVal iRet;
+
+ close(sun_Pfd.fd);
+ sun_Pfd.fd = -1;
+
+ while(1) { /* loop broken inside */
+ iRet = sun_openklog((LogName == NULL) ? PATH_LOG : LogName);
+ if(iRet == RS_RET_OK) {
+ if(tryNum > 1) {
+ errmsg.LogError(0, iRet, "failure on system log socket recovered.");
+ }
+ break;
+ }
+ /* failure, so sleep a bit. We wait try*10 ms, with a max of 15 seconds */
+ if(tryNum == 1) {
+ errmsg.LogError(0, iRet, "failure on system log socket, trying to recover...");
+ }
+ waitusecs = tryNum * 10000;
+ waitsecs = waitusecs / 1000000;
+ DBGPRINTF("imsolaris: try %d to recover system log socket in %d.%d seconds\n",
+ tryNum, waitsecs, waitusecs);
+ if(waitsecs > 15) {
+ waitsecs = 15;
+ waitusecs = 0;
+ } else {
+ waitusecs = waitusecs % 1000000;
+ }
+ srSleep(waitsecs, waitusecs);
+ ++tryNum;
+ }
+}
+
+
+/* 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
+ */
+static rsRetVal
+readLog(int fd, uchar *pRcv, int iMaxLine)
+{
+ DEFiRet;
+ struct strbuf data;
+ struct strbuf ctl;
+ struct log_ctl hdr;
+ int flags;
+ msg_t *pMsg;
+ int ret;
+ char errStr[1024];
+
+ 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) {
+ if(errno == EINTR) {
+ FINALIZE;
+ } else {
+ int en = errno;
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("imsolaris: stream input error on fd %d: %s.\n", fd, errStr);
+ errmsg.LogError(en, NO_ERRCODE, "imsolaris: stream input error: %s", errStr);
+ tryRecover();
+ }
+ } else {
+ DBGPRINTF("imsolaris: message from log stream %d: %s\n", fd, pRcv);
+ pRcv[data.len] = '\0'; /* make sure it is a valid C-String */
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)pRcv, strlen((char*)pRcv));
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ pMsg->iFacility = LOG_FAC(hdr.pri);
+ pMsg->iSeverity = LOG_PRI(hdr.pri);
+ pMsg->bParseHOSTNAME = 0;
+ pMsg->msgFlags = NEEDS_PARSING | NO_PRI_IN_RAW;
+ CHKiRet(submitMsg(pMsg));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* once the system is fully initialized, we wait for new messages.
+ * We may think about replacing this with a read-loop, thus saving
+ * us the overhead of the poll.
+ * The timeout variable is the timeout to use for poll. During startup,
+ * it should be set to 0 (non-blocking) and later to -1 (infinit, blocking).
+ * This mimics the (strange) behaviour of the original syslogd.
+ * rgerhards, 2010-04-19
+ */
+static inline rsRetVal
+getMsgs(int timeout)
+{
+ DEFiRet;
+ int nfds;
+ int iMaxLine;
+ uchar *pRcv = NULL; /* receive buffer */
+ uchar bufRcv[4096+1];
+ char errStr[1024];
+
+ 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)));
+ }
+
+ do {
+ DBGPRINTF("imsolaris: waiting for next message (timeout %d)...\n", timeout);
+ if(timeout == 0) {
+ nfds = poll(&sun_Pfd, 1, timeout); /* wait without timeout */
+
+ /* v5-TODO: here we must check if we should terminante! */
+
+ if(nfds == 0) {
+ if(timeout == 0) {
+ DBGPRINTF("imsolaris: no more messages, getMsgs() terminates\n");
+ FINALIZE;
+ } else {
+ continue;
+ }
+ }
+
+ if(nfds < 0) {
+ if(errno != EINTR) {
+ int en = errno;
+ rs_strerror_r(en, errStr, sizeof(errStr));
+ DBGPRINTF("imsolaris: poll error: %d = %s.\n", errno, errStr);
+ errmsg.LogError(en, NO_ERRCODE, "imsolaris: poll error: %s",
+ errStr);
+ }
+ continue;
+ }
+ if(sun_Pfd.revents & POLLIN) {
+ readLog(sun_Pfd.fd, pRcv, iMaxLine);
+ } else if(sun_Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
+ tryRecover();
+ }
+ } else {
+ /* if we have an infinite wait, we do not use poll at all
+ * I'd consider this a waste of time. However, I do not totally
+ * remove the code, as it may be useful if we decide at some
+ * point to provide a capability to support multiple input streams
+ * at once (this may be useful for a jail). In that case, the poll()
+ * loop would be needed, and so it doesn't make much sense to change
+ * the code to not support it. -- rgerhards, 2010-04-20
+ */
+ readLog(sun_Pfd.fd, pRcv, iMaxLine);
+ }
+
+ } while(1); /* TODO: in v5, we must check the termination predicate */
+
+ /* Note: in v4, this code is never reached (our thread will be cancelled) */
+
+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: doing startup poll before openeing door()\n");
+ CHKiRet(getMsgs(0));
+
+ /* note: sun's syslogd code claims that the door should only
+ * be opened when the log stream has been polled. So file header
+ * comment of this file for more details.
+ */
+ sun_open_door();
+ DBGPRINTF("imsolaris: starting regular poll loop\n");
+ iRet = getMsgs(-1); /* this is the primary poll loop, infinite timeout */
+
+finalize_it:
+ 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);
+ 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);
+ free(LogName);
+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));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imsolarislogsocketname", 0, eCmdHdlrGetWord,
+ NULL, &LogName, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imsolaris/imsolaris.h b/plugins/imsolaris/imsolaris.h
new file mode 100644
index 00000000..e73380fa
--- /dev/null
+++ b/plugins/imsolaris/imsolaris.h
@@ -0,0 +1,2 @@
+rsRetVal solaris_readLog(int fd);
+void imsolaris_logerror(int err, char *errStr);
diff --git a/plugins/imsolaris/sun_cddl.c b/plugins/imsolaris/sun_cddl.c
new file mode 100644
index 00000000..6d49c8bc
--- /dev/null
+++ b/plugins/imsolaris/sun_cddl.c
@@ -0,0 +1,419 @@
+/*
+ * 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 <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <stropts.h>
+#include <assert.h>
+
+#include <sys/param.h>
+#include <sys/strlog.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <door.h>
+#include <sys/door.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "debug.h"
+#include "imsolaris.h"
+
+#define DOORFILE "/var/run/syslog_door"
+#define RELATIVE_DOORFILE "../var/run/syslog_door"
+#define OLD_DOORFILE "/etc/.syslog_door"
+
+/* Buffer to allocate for error messages: */
+#define ERRMSG_LEN 1024
+
+/* 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
+
+
+struct pollfd sun_Pfd; /* Pollfd for local 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);
+}
+
+/*
+ * 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)
+{
+ struct stat sb;
+ int err;
+ char line[ERRMSG_LEN+1];
+
+ 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);
+ imsolaris_logerror(err, line);
+ DBGPRINTF("delete_doorfiles: error: %s, "
+ "errno=%d\n", line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles: deleted %s\n", 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: %s\n", line);
+
+ if (err != EROFS) {
+ errno = err;
+ (void) strlcat(line, " - fatal",
+ sizeof (line));
+ imsolaris_logerror(err, line);
+ DBGPRINTF("delete_doorfiles: "
+ "error: %s, errno=%d\n",
+ line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles: unlink() "
+ "failure OK on RO file system\n");
+ }
+
+ DBGPRINTF("delete_doorfiles: deleted %s\n",
+ OLD_DOORFILE);
+ }
+ }
+
+ if (DoorFd != -1) {
+ (void) door_revoke(DoorFd);
+ }
+
+ DBGPRINTF("delete_doorfiles: revoked door: DoorFd=%d\n",
+ 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[ERRMSG_LEN+1];
+ int err;
+
+ /* first see if another instance of imsolaris OR another
+ * syslogd is running by trying a door call - if it succeeds,
+ * there is already one active.
+ */
+
+ if (!DoorCreated) {
+ int door;
+
+ if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
+ DBGPRINTF("open_door: %s opened "
+ "successfully\n", DoorFileName);
+
+ if (door_info(door, &info) >= 0) {
+ DBGPRINTF("open_door: "
+ "door_info:info.di_target = %ld\n",
+ 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: error: "
+ "%s\n", line);
+ imsolaris_logerror(0, line);
+ exit(1);
+ }
+ }
+
+ (void) close(door);
+ } else {
+ if (lstat(DoorFileName, &buf) < 0) {
+ err = errno;
+
+ DBGPRINTF("open_door: lstat() of %s "
+ "failed, errno=%d\n",
+ DoorFileName, err);
+
+ if ((door = creat(DoorFileName, 0644)) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "creat() of %s failed - fatal",
+ DoorFileName);
+ DBGPRINTF("open_door: error: %s, "
+ "errno=%d\n", line,
+ err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ (void) fchmod(door,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+ DBGPRINTF("open_door: creat() of %s "
+ "succeeded\n",
+ DoorFileName);
+
+ (void) close(door);
+ }
+ }
+
+ if (strcmp(DoorFileName, DOORFILE) == 0) {
+ if (lstat(OLD_DOORFILE, &buf) == 0) {
+ DBGPRINTF("open_door: lstat() of %s "
+ "succeeded\n", OLD_DOORFILE);
+
+ if (S_ISDIR(buf.st_mode)) {
+ (void) snprintf(line, sizeof (line),
+ "%s is a directory - fatal",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door: error: "
+ "%s\n", line);
+ imsolaris_logerror(0, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: %s is not a "
+ "directory\n", OLD_DOORFILE);
+ if (unlink(OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door: %s\n",
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door: "
+ "error: %s, "
+ "errno=%d\n",
+ line, err);
+ (void) strcat(line, " - fatal");
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: unlink "
+ "failure OK on RO file "
+ "system\n");
+ }
+ } else {
+ DBGPRINTF("open_door: file %s doesn't "
+ "exist\n", 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: %s\n",
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door: error: %s, "
+ "errno=%d\n", line,
+ err);
+ (void) strcat(line, " - fatal");
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: symlink failure OK "
+ "on RO file system\n");
+ } else {
+ DBGPRINTF("open_door: symlink %s -> %s "
+ "succeeded\n",
+ 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: error: %s, errno=%d\n",
+ line, err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+ //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
+ DBGPRINTF("open_door: door_create() succeeded, "
+ "DoorFd=%d\n", 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: error: %s, errno=%d\n",
+ line, err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: attached server() to %s\n",
+ DoorFileName);
+
+}
+
+
+/* Attempts to open the local log device
+ * and return a file descriptor.
+ */
+rsRetVal
+sun_openklog(char *name)
+{
+ DEFiRet;
+ int fd;
+ 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);
+ }
+ sun_Pfd.fd = fd;
+ sun_Pfd.events = POLLIN;
+ DBGPRINTF("imsolaris/openklog: opened '%s' as fd %d.\n", name, fd);
+
+finalize_it:
+ RETiRet;
+}
diff --git a/plugins/imsolaris/sun_cddl.h b/plugins/imsolaris/sun_cddl.h
new file mode 100644
index 00000000..42e4b799
--- /dev/null
+++ b/plugins/imsolaris/sun_cddl.h
@@ -0,0 +1,7 @@
+rsRetVal sun_openklog(char *name);
+void prepare_sys_poll(void);
+void sun_sys_poll(void);
+void sun_open_door(void);
+void sun_delete_doorfiles(void);
+
+extern struct pollfd sun_Pfd; /* Pollfd for local log device */