source: trunk/src/sh_err_console.c@ 502

Last change on this file since 502 was 489, checked in by katerina, 9 years ago

Version 4.1.0 final.

File size: 9.0 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#include "sh_sem.h"
28
29#undef FIL__
30#define FIL__ _("sh_err_console.c")
31
32#include <stdio.h>
33#include <sys/types.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <signal.h>
37
38extern int OnlyStderr;
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
55#if !defined(EIDRM)
56#define EIDRM (EINVAL)
57#endif
58
59struct sh_msgbuf {
60 long mtype;
61 char mtext[1]; /* <-- sizeof(mtext) will be 1+MY_MAX_MSG */
62};
63
64static int msgq_enabled = S_FALSE;
65
66/* The identifier of the message queue
67 */
68static int msgid = -1;
69
70/* Open the SysV message queue, creating it when neccesary
71 */
72static int open_queue(void)
73{
74 key_t key;
75#if defined(WITH_TPT)
76 char errbuf[SH_ERRBUF_SIZE];
77#endif
78
79 SL_ENTER(_("open_queue"));
80
81 /* get key
82 */
83 key = ftok (DEFAULT_DATAROOT, '#');
84
85 if (key == (key_t) -1)
86 {
87 TPT(( 0, FIL__, __LINE__, _("msg=<ftok: %s> errno=<%d>\n"),
88 sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
89 SL_RETURN(-1, _("open_queue"));
90 }
91
92 /* get message identifier
93 */
94 msgid = msgget (key, IPC_CREAT|MESSAGE_QUEUE_MODE);
95
96 if (msgid < 0)
97 {
98 TPT(( 0, FIL__, __LINE__, _("msg=<msgget: %s> errno=<%d>\n"),
99 sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
100 SL_RETURN(-1, _("open_queue"));
101 }
102
103 SL_RETURN(0, _("open_queue"));
104}
105
106/* Close the SysV message queue and/or semaphore
107 */
108void close_ipc (void)
109{
110 if (msgid != (-1))
111 (void) msgctl (msgid, IPC_RMID, NULL);
112 sh_sem_close();
113 return;
114}
115
116/* Enable the message queue
117 */
118int enable_msgq(const char * foo)
119{
120 int i;
121
122 SL_ENTER(_("enable_msgq"));
123 i = sh_util_flagval(foo, &msgq_enabled);
124 SL_RETURN(i, _("enable_msgq"));
125}
126
127#define MY_MAX_MSG 1022
128
129static void remove_message()
130{
131 int rc;
132 struct {
133 long mtype; /* Message type. */
134 char mtext[128]; /* Message text. */
135 } recv_msg;
136
137 recv_msg.mtype = 1;
138 do {
139 rc = msgrcv(msgid, &recv_msg, sizeof(recv_msg.mtext), 1,
140 MSG_NOERROR|IPC_NOWAIT);
141 } while (rc < 0 && errno == EINTR);
142
143 memset(&recv_msg, '\0', sizeof(recv_msg));
144 return;
145}
146
147static int push_message_queue (const char * msg)
148{
149 struct sh_msgbuf* recv_msg = NULL;
150 int rc = -1;
151 static int status = -1;
152 int count = 0;
153#if defined(WITH_TPT)
154 char errbuf[SH_ERRBUF_SIZE];
155#endif
156
157 SL_ENTER(_("push_message_queue"));
158
159 if (msgq_enabled == -1)
160 {
161 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not enabled>\n")));
162 SL_RETURN(0, _("push_message_queue"));
163 }
164
165 if (status < 0)
166 {
167 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
168 status = open_queue();
169 }
170
171 if (status < 0)
172 {
173 TPT(( 0, FIL__, __LINE__, _("msg=<open_queue() failed>\n")));
174 SL_RETURN(-1, _("push_message_queue"));
175 }
176
177 /* struct msgbuf {
178 * long mtype;
179 * char mtext[1]; <-- sizeof(mtext) will be 1+MY_MAX_MSG
180 * } */
181
182 recv_msg = (struct sh_msgbuf*) SH_ALLOC(sizeof(struct sh_msgbuf)+MY_MAX_MSG);
183 recv_msg->mtype = 1;
184 sl_strlcpy (recv_msg->mtext, msg, MY_MAX_MSG+1);
185
186 count = 0;
187
188 send_it:
189
190 if (count > 1)
191 {
192 memset(recv_msg, '\0', MY_MAX_MSG+1);
193 SH_FREE(recv_msg);
194 SL_RETURN(-1, _("push_message_queue"));
195 }
196
197 do { errno = 0;
198 rc = msgsnd(msgid, recv_msg, strlen(recv_msg->mtext)+1, IPC_NOWAIT);
199
200 if (rc == -1 && errno == EAGAIN)
201 remove_message();
202 } while (rc < 0 && (errno == EINTR && errno == EAGAIN));
203
204 if (rc == -1 && errno != EAGAIN)
205 {
206 /* EIDRM is not in OpenBSD */
207 if (errno == EINVAL || errno == EIDRM) {
208 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
209 status = open_queue();
210 if (status == 0) {
211 ++count;
212 goto send_it; }
213 } else {
214 TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"),
215 sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
216 memset(recv_msg, '\0', MY_MAX_MSG+1);
217 SH_FREE(recv_msg);
218 SL_RETURN(-1, _("push_message_queue"));
219 }
220 }
221
222 memset(recv_msg, '\0', MY_MAX_MSG+1);
223 SH_FREE(recv_msg);
224
225 SL_RETURN(0, _("push_message_queue"));
226}
227/* if defined(HAVE_SYS_MSG_H) */
228#else
229
230#error **********************************************
231#error
232#error The sys/msg.h header was not found,
233#error cannot compile with --enable-message-queue
234#error
235#error **********************************************
236
237#endif
238
239#else /* no message queue */
240
241void close_ipc() { sh_sem_close(); return; }
242
243#endif
244
245static int count_dev_console = 0;
246
247void reset_count_dev_console(void)
248{
249 count_dev_console = 0;
250 return;
251}
252
253/* ---- Set the console device. ----
254 */
255int sh_log_set_console (const char * address)
256{
257 SL_ENTER(_("sh_log_set_console"));
258 if (address != NULL && count_dev_console < 2
259 && sl_strlen(address) < SH_PATHBUF)
260 {
261 if (count_dev_console == 0)
262 (void) sl_strlcpy (sh.srvcons.name, address, SH_PATHBUF);
263 else
264 (void) sl_strlcpy (sh.srvcons.alt, address, SH_PATHBUF);
265
266 ++count_dev_console;
267 SL_RETURN(0, _("sh_log_set_console"));
268 }
269 SL_RETURN((-1), _("sh_log_set_console"));
270}
271
272#if defined(WITH_TRACE) || defined(WITH_TPT)
273char * sh_log_console_name (void)
274{
275 if (sh.srvcons.name[0] == '\0' ||
276 0 == strcmp(sh.srvcons.name, _("NULL")))
277 return (_("/dev/console"));
278 return sh.srvcons.name;
279}
280#endif
281
282#ifndef STDERR_FILENO
283#define STDERR_FILENO 2
284#endif
285
286/* ---- Print out a message. ----
287 */
288int sh_log_console (const /*@null@*/char *errmsg)
289{
290 static int service_failure[2] = { 0, 0};
291 int fd[2] = { -1, -1};
292 int cc;
293 size_t len;
294 int ccMax = 1;
295 int retval = -1;
296 /* static int logkey_seen = 0; */
297 int error;
298 static int blockMe = 0;
299 int val_return;
300
301 SL_ENTER(_("sh_log_console"));
302
303 if (errmsg == NULL || blockMe == 1)
304 {
305 SL_RETURN(0, _("sh_log_console"));
306 }
307 else
308 blockMe = 1;
309
310
311#ifdef WITH_MESSAGE_QUEUE
312 if (0 != push_message_queue (errmsg))
313 {
314 TPT(( 0, FIL__, __LINE__, _("msg=<push_message_queue() failed>\n")));
315 }
316#endif
317
318 if (sh.flag.isdaemon == S_FALSE || OnlyStderr == S_TRUE)
319 {
320 len = strlen(errmsg);
321 do {
322 val_return = write(STDERR_FILENO, errmsg, len);
323 } while (val_return < 0 && errno == EINTR);
324 do {
325 val_return = write(STDERR_FILENO, "\n", 1);
326 } while (val_return < 0 && errno == EINTR);
327 /*
328 * fprintf (stderr, "%s\n", errmsg);
329 */
330 blockMe = 0;
331 SL_RETURN(0, _("sh_log_console"));
332 }
333
334 /* --- daemon && initialized ---
335 */
336 if ( OnlyStderr == S_FALSE )
337 {
338 fd[0] = open ( sh.srvcons.name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
339
340 if (sh.srvcons.alt[0] != '\0')
341 {
342 fd[1] = open (sh.srvcons.alt, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
343 ccMax = 2;
344 }
345
346 for (cc = 0; cc < ccMax; ++cc)
347 {
348
349 if (fd[cc] < 0 && service_failure[cc] == 0)
350 {
351 error = errno;
352 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_SRV_FAIL,
353 _("console"),
354 (cc == 0) ? sh.srvcons.name : sh.srvcons.alt);
355 service_failure[cc] = 1;
356 }
357
358 if (fd[cc] >= 0)
359 {
360 do {
361 val_return = write(fd[cc], errmsg, strlen(errmsg));
362 } while (val_return < 0 && errno == EINTR);
363 do {
364 val_return = write(fd[cc], "\r\n", 2);
365 } while (val_return < 0 && errno == EINTR);
366 (void) sl_close_fd(FIL__, __LINE__, fd[cc]);
367 service_failure[cc] = 0;
368 }
369 }
370 }
371 else
372 retval = 0;
373
374 blockMe = 0;
375 SL_RETURN(retval, _("sh_log_console"));
376}
377
378
Note: See TracBrowser for help on using the repository browser.