source: branches/samhain-2_2-branch/src/sh_err_console.c@ 572

Last change on this file since 572 was 22, checked in by rainer, 19 years ago

Minor code revisions.

File size: 8.9 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <string.h>
23
24#include "samhain.h"
25#include "sh_error.h"
26#include "sh_utils.h"
27
28#undef FIL__
29#define FIL__ _("sh_err_console.c")
30
31#include <stdio.h>
32#include <sys/types.h>
33#include <fcntl.h>
34#include <unistd.h>
35#include <signal.h>
36
37extern int OnlyStderr;
38
39
40#if !defined(O_NONBLOCK)
41#if defined(O_NDELAY)
42#define O_NONBLOCK O_NDELAY
43#else
44#define O_NONBLOCK 0
45#endif
46#endif
47
48#if defined(WITH_MESSAGE_QUEUE)
49
50#if defined(HAVE_SYS_MSG_H)
51
52#include <sys/ipc.h>
53#include <sys/msg.h>
54
55struct sh_msgbuf {
56 long mtype;
57 char mtext[1]; /* <-- sizeof(mtext) will be 1+MY_MAX_MSG */
58};
59
60static int msgq_enabled = S_FALSE;
61
62/* The identifier of the message queue
63 */
64static int msgid = -1;
65
66/* Open the SysV message queue, creating it when neccesary
67 */
68static int open_ipc(void)
69{
70 key_t key;
71 int error;
72
73 SL_ENTER(_("open_ipc"));
74
75 /* get key
76 */
77 key = ftok ("/tmp", '#');
78 if (key == (key_t) -1)
79 {
80 error = errno;
81 TPT(( 0, FIL__, __LINE__, _("msg=<ftok: %s> errno=<%d>\n"),
82 sh_error_message(error), error));
83 SL_RETURN(-1, _("open_ipc"));
84 }
85
86 /* get message identifier
87 */
88 msgid = msgget (key, IPC_CREAT|MESSAGE_QUEUE_MODE);
89
90 if (msgid < 0)
91 {
92 error = errno;
93 TPT(( 0, FIL__, __LINE__, _("msg=<msgget: %s> errno=<%d>\n"),
94 sh_error_message(error), error));
95 SL_RETURN(-1, _("open_ipc"));
96 }
97
98 SL_RETURN(0, _("open_ipc"));
99}
100
101/* Close the SysV message queue
102 */
103void close_ipc (void)
104{
105 SL_ENTER(_("close_ipc"));
106
107 if (msgid != (-1))
108 (void) msgctl (msgid, IPC_RMID, NULL);
109 SL_RET0(_("close_ipc"));
110}
111
112/* Enable the message queue
113 */
114int enable_msgq(const char * foo)
115{
116 int i;
117
118 SL_ENTER(_("enable_msgq"));
119 i = sh_util_flagval(foo, &msgq_enabled);
120 SL_RETURN(i, _("enable_msgq"));
121}
122
123/* #define MY_MAX_MSG 254 */
124#define MY_MAX_MSG 1022
125
126static int push_message_queue (char * msg)
127{
128 struct sh_msgbuf* recv_msg = NULL;
129 int rc = -1;
130 static int status = -1;
131 int error;
132 int count = 0;
133
134 SL_ENTER(_("push_message_queue"));
135
136 if (msgq_enabled == -1)
137 {
138 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not enabled>\n")));
139 SL_RETURN(0, _("push_message_queue"));
140 }
141
142 if (status < 0)
143 {
144 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
145 status = open_ipc();
146 }
147
148 if (status < 0)
149 {
150 TPT(( 0, FIL__, __LINE__, _("msg=<open_ipc() failed>\n")));
151 SL_RETURN(-1, _("push_message_queue"));
152 }
153
154 /* struct msgbuf {
155 * long mtype;
156 * char mtext[1]; <-- sizeof(mtext) will be 1+MY_MAX_MSG
157 * }
158 */
159 recv_msg = (struct sh_msgbuf*) SH_ALLOC(sizeof(struct sh_msgbuf)+MY_MAX_MSG);
160 recv_msg->mtype = 1;
161 sl_strlcpy (recv_msg->mtext, msg, MY_MAX_MSG+1);
162
163 count = 0;
164
165 send_it:
166
167 if (count > 1)
168 {
169 SH_FREE(recv_msg);
170 SL_RETURN(-1, _("push_message_queue"));
171 }
172
173 /* send the message
174 */
175 do {
176 errno = 0;
177 rc = msgsnd(msgid, recv_msg, strlen(recv_msg->mtext)+1, IPC_NOWAIT);
178 }
179 while (rc < 0 && errno == EINTR);
180
181 if (rc == -1 && errno != EAGAIN)
182 {
183 /* EIDRM is not in OpenBSD
184 */
185 if (errno == EINVAL
186#if defined(EIDRM)
187 || errno == EIDRM
188#endif
189 )
190 {
191 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
192 status = open_ipc();
193 if (status == 0)
194 {
195 ++count;
196 goto send_it;
197 }
198 }
199 else
200 {
201 error = errno;
202 TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"),
203 sh_error_message(error), error));
204 SH_FREE(recv_msg);
205 SL_RETURN(-1, _("push_message_queue"));
206 }
207 }
208
209 SH_FREE(recv_msg);
210 SL_RETURN(0, _("push_message_queue"));
211}
212/* if defined(HAVE_SYS_MSG_H) */
213#else
214
215#error **********************************************
216#error
217#error The sys/msg.h header was not found,
218#error cannot compile with --enable-message-queue
219#error
220#error **********************************************
221
222#endif
223
224#endif
225
226static int count_dev_console = 0;
227
228void reset_count_dev_console(void)
229{
230 count_dev_console = 0;
231 return;
232}
233
234/* ---- Set the console device. ----
235 */
236int sh_log_set_console (const char * address)
237{
238 SL_ENTER(_("sh_log_set_console"));
239 if (address != NULL && count_dev_console < 2
240 && sl_strlen(address) < SH_PATHBUF)
241 {
242 if (count_dev_console == 0)
243 (void) sl_strlcpy (sh.srvcons.name, address, SH_PATHBUF);
244 else
245 (void) sl_strlcpy (sh.srvcons.alt, address, SH_PATHBUF);
246
247 ++count_dev_console;
248 SL_RETURN(0, _("sh_log_set_console"));
249 }
250 SL_RETURN((-1), _("sh_log_set_console"));
251}
252
253#if defined(WITH_TRACE) || defined(WITH_TPT)
254char * sh_log_console_name ()
255{
256 if (! sh.srvcons.name || sh.srvcons.name[0] == '\0' ||
257 0 == strcmp(sh.srvcons.name, _("NULL")))
258 return (_("/dev/console"));
259 return sh.srvcons.name;
260}
261#endif
262
263#ifndef STDERR_FILENO
264#define STDERR_FILENO 2
265#endif
266
267/* ---- Print out a message. ----
268 */
269int sh_log_console (/*@null@*/char *errmsg)
270{
271 static int service_failure[2] = { 0, 0};
272 int fd[2] = { -1, -1};
273 int sflags;
274 int cc;
275 size_t len;
276 int ccMax = 1;
277 int retval = -1;
278 /* static int logkey_seen = 0; */
279 int error;
280 struct sigaction sa_new, sa_old;
281 static int blockMe = 0;
282
283 SL_ENTER(_("sh_log_console"));
284
285 if (errmsg == NULL || blockMe == 1)
286 {
287 SL_RETURN(0, _("sh_log_console"));
288 }
289 else
290 blockMe = 1;
291
292
293#ifdef WITH_MESSAGE_QUEUE
294 if (0 != push_message_queue (errmsg))
295 {
296 TPT(( 0, FIL__, __LINE__, _("msg=<push_message_queue() failed>\n")));
297 }
298#endif
299
300 sa_new.sa_handler = SIG_IGN;
301 (void) sigemptyset(&sa_new.sa_mask);
302 sa_new.sa_flags = 0;
303
304 /* Ignore SIGPIPE in case the console is actually a pipe.
305 */
306 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_new, &sa_old);
307
308 if (sh.flag.isdaemon == S_FALSE || OnlyStderr == S_TRUE)
309 {
310 len = strlen(errmsg);
311 (void) write(STDERR_FILENO, errmsg, len);
312 (void) write(STDERR_FILENO, "\n", 1);
313 /*
314 * fprintf (stderr, "%s\n", errmsg);
315 */
316 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_old, NULL);
317 blockMe = 0;
318 SL_RETURN(0, _("sh_log_console"));
319 }
320
321 /* --- daemon && initialized ---
322 */
323 if ( (OnlyStderr == S_FALSE) )
324 {
325 fd[0] = open ( sh.srvcons.name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
326 if (fd[0] >= 0) {
327 sflags = (int) retry_fcntl(FIL__, __LINE__, fd[0], F_GETFL, 0);
328 if (sflags >= 0)
329 {
330 (void) retry_fcntl(FIL__, __LINE__, fd[0],
331 F_SETFL, sflags & ~O_NONBLOCK);
332 }
333 }
334
335 if (sh.srvcons.alt != NULL && sh.srvcons.alt[0] != '\0')
336 {
337 fd[1] = open (sh.srvcons.alt, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
338 if (fd[1] >= 0) {
339 sflags = (int) retry_fcntl(FIL__, __LINE__, fd[1], F_GETFL, 0);
340 if (sflags >= 0)
341 {
342 (void) retry_fcntl(FIL__, __LINE__, fd[1],
343 F_SETFL, sflags & ~O_NONBLOCK);
344 }
345 ccMax = 2;
346 }
347 }
348
349 for (cc = 0; cc < ccMax; ++cc)
350 {
351
352 if (fd[cc] < 0 && service_failure[cc] == 0)
353 {
354 error = errno;
355 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_SRV_FAIL,
356 _("console"),
357 (cc == 0) ? sh.srvcons.name : sh.srvcons.alt);
358 service_failure[cc] = 1;
359 }
360
361 if (fd[cc] >= 0)
362 {
363 (void) write(fd[cc], errmsg, strlen(errmsg));
364 (void) write(fd[cc], "\r\n", 2);
365 (void) close(fd[cc]);
366 service_failure[cc] = 0;
367 }
368 }
369 }
370 else
371 retval = 0;
372
373 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_old, NULL);
374 blockMe = 0;
375 SL_RETURN(retval, _("sh_log_console"));
376}
377
378
Note: See TracBrowser for help on using the repository browser.