source: trunk/src/sh_err_console.c @ 474

Last change on this file since 474 was 474, checked in by katerina, 7 years ago

Fix for ticket #372 (Replace obsolete smatch by clang in test suite).

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#if defined(WITH_TPT)
72  int              error = 0;
73  char errbuf[SH_ERRBUF_SIZE];
74#endif
75
76  SL_ENTER(_("open_ipc"));
77
78  /* get key
79   */
80  key = ftok ("/tmp", '#');
81  if (key == (key_t) -1)
82    {
83#if defined(WITH_TPT)
84      error = errno;
85#endif
86      TPT(( 0, FIL__, __LINE__, _("msg=<ftok: %s> errno=<%d>\n"), 
87            sh_error_message(error, errbuf, sizeof(errbuf)), error));
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    {
97#if defined(WITH_TPT)
98      error = errno;
99#endif
100      TPT(( 0, FIL__, __LINE__, _("msg=<msgget: %s> errno=<%d>\n"), 
101            sh_error_message(error, errbuf, sizeof(errbuf)), error));
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 */
121int enable_msgq(const char * foo)
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
133static int push_message_queue (const char * msg)
134{
135  struct sh_msgbuf*   recv_msg = NULL;
136  int              rc       = -1;
137  static int       status   = -1;
138  int              count    = 0;
139#if defined(WITH_TPT)
140  int              error = 0;
141  char errbuf[SH_ERRBUF_SIZE];
142#endif
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        {
211#if defined(WITH_TPT)
212          error = errno;
213#endif
214          TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"), 
215                sh_error_message(error, errbuf, sizeof(errbuf)), error));
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 */
248int sh_log_set_console (const char * address)
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)
266char *  sh_log_console_name (void)
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 */
281int  sh_log_console (const /*@null@*/char *errmsg)
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;
293  int    val_return;
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);
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); 
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[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            {
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);
376              (void) sl_close_fd(FIL__, __LINE__, fd[cc]);
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.