source: trunk/src/sh_err_console.c @ 489

Last change on this file since 489 was 489, checked in by katerina, 6 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.