source: trunk/src/sh_err_console.c@ 135

Last change on this file since 135 was 132, checked in by rainer, 17 years ago

Make utility functions thread-safe.

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