source: trunk/src/sh_err_console.c@ 445

Last change on this file since 445 was 379, checked in by katerina, 13 years ago

Fix for ticket #277 (sigpipe).

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