diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2011-09-15 15:17:47 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2011-09-15 15:17:47 +0200 |
commit | 1d0e4ba3b34464343c388ccef3ca8b08df42076a (patch) | |
tree | d17f746f7c8cb2f00aa3ab956740fd616e2390c0 /plugins/imsolaris | |
parent | b7e69a240037277e77685af5ea5623cdd89ec2d2 (diff) | |
parent | 11ee5cbdfb08ba3e42a853c08144fa24cd55d6da (diff) | |
download | rsyslog-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.am | 6 | ||||
-rw-r--r-- | plugins/imsolaris/imsolaris.c | 391 | ||||
-rw-r--r-- | plugins/imsolaris/imsolaris.h | 2 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.c | 419 | ||||
-rw-r--r-- | plugins/imsolaris/sun_cddl.h | 7 |
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 */ |