Watt-32 tcp/ip  2.2 dev-rel.10
syslog.c
Go to the documentation of this file.
1 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <sys/syslog.h>
24 #include <sys/socket.h>
25 #include <fcntl.h>
26 #include <time.h>
27 #include <netdb.h>
28 
29 #include "wattcp.h"
30 #include "misc.h"
31 #include "run.h"
32 #include "printk.h"
33 #include "pctcp.h"
34 #include "pcsed.h"
35 #include "pcstat.h"
36 #include "pcbuf.h"
37 #include "pcdbug.h"
38 #include "pcconfig.h"
39 #include "netaddr.h"
40 #include "sock_ini.h"
41 #include "strings.h"
42 #include "syslog2.h"
43 
44 #if defined(USE_BSD_API)
45 
46 #if defined(__CCDL__) && !defined(getpid)
47 #define getpid() 0
48 #endif
49 
50 #if defined(__LCCDL__)
51 #define getpid() _getpid()
52 #endif
53 
54 #define INTERNALLOG (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID)
55 
56 static sock_type *log_sock = NULL; /* UDP socket for log */
57 static FILE *log_file = NULL; /* FILE* for log */
58 static DWORD log_host = 0UL; /* IP-address of host (host order) */
59 static BOOL log_opened = FALSE; /* have called openlog() (error or not) */
60 static int log_stat = 0; /* status bits, set by openlog() */
61 static char *log_tag = NULL; /* string to tag the entry with */
62 static int log_mask = LOG_INFO; /* default is LOG_EMERG - LOGINFO */
63 static DWORD log_facil = LOG_USER; /* default facility */
64 
65 /* These arrays used to be pulled in from <sys/syslog.h> when SYSLOG_NAMES
66  * was defined, but caused "multiple defined" problems.
67  */
68 CODE prioritynames[] = {
69  { LOG_ALERT, "alert" },
70  { LOG_CRIT, "crit" },
71  { LOG_DEBUG, "debug" },
72  { LOG_EMERG, "emerg" },
73  { LOG_ERR, "err" },
74  { LOG_ERR, "error" }, /* DEPRECATED */
75  { LOG_INFO, "info" },
76  { INTERNAL_NOPRI, "none" }, /* INTERNAL */
77  { LOG_NOTICE, "notice" },
78  { LOG_EMERG, "panic" }, /* DEPRECATED */
79  { LOG_WARNING, "warn" }, /* DEPRECATED */
80  { LOG_WARNING, "warning" },
81  { -1, NULL }
82  };
83 
84 CODE facilitynames[] = {
85  { LOG_AUTH, "auth" },
86  { LOG_AUTHPRIV, "authpriv" },
87  { LOG_CRON, "cron" },
88  { LOG_DAEMON, "daemon" },
89  { LOG_FTP, "ftp" },
90  { LOG_KERN, "kern" },
91  { LOG_LPR, "lpr" },
92  { LOG_MAIL, "mail" },
93  { INTERNAL_MARK, "mark" }, /* INTERNAL */
94  { LOG_NEWS, "news" },
95  { LOG_NTP, "ntp" },
96  { LOG_AUTH, "security" }, /* DEPRECATED */
97  { LOG_SYSLOG, "syslog" },
98  { LOG_USER, "user" },
99  { LOG_UUCP, "uucp" },
100  { LOG_LOCAL0, "local0" },
101  { LOG_LOCAL1, "local1" },
102  { LOG_LOCAL2, "local2" },
103  { LOG_LOCAL3, "local3" },
104  { LOG_LOCAL4, "local4" },
105  { LOG_LOCAL5, "local5" },
106  { LOG_LOCAL6, "local6" },
107  { LOG_LOCAL7, "local7" },
108  { -1, NULL }
109  };
110 
111 /*
112  * syslog, vsyslog --
113  * print message on log file; output is intended for syslogd(8).
114  */
115 void W32_CDECL syslog (int pri, const char *fmt, ...)
116 {
117  va_list args;
118  va_start (args, fmt);
119  vsyslog (pri, fmt, args);
120  va_end (args);
121 }
122 
123 void W32_CALL vsyslog (int pri, const char *fmt, va_list ap)
124 {
125 #if defined(USE_DEBUG)
126  const char *pri_name = "?";
127  const char *fac_name = "?";
128 #endif
129  const char *pri_end;
130  char *p, ct_buf[30];
131  char tbuffer [2048];
132  int left = sizeof(tbuffer);
133  int saved_errno = errno;
134  time_t t;
135 
136 #if 0
137  /* Check for invalid bits
138  */
139  if (pri & ~(LOG_PRIMASK|LOG_FACMASK))
140  {
141  syslog (INTERNALLOG, "syslog: unknown priority: %d", pri);
142  pri &= (LOG_PRIMASK | LOG_FACMASK);
143  }
144 #endif
145 
146  /* Set default facility if none specified
147  */
148  if (!(pri & LOG_FACMASK))
149  pri |= log_facil;
150 
151 #if defined(USE_DEBUG)
152  pri_name = list_lookup (LOG_PRI(pri),
153  (const struct search_list*)prioritynames,
154  DIM(prioritynames)-1);
155 
156  fac_name = list_lookup (LOG_FACMASK & pri,
157  (const struct search_list*)facilitynames,
158  DIM(facilitynames)-1);
159 #endif
160 
161  /* Check priority against setlogmask() values.
162  * Note: higher priorities are lower values !!
163  */
164  if (LOG_PRI(pri) > LOG_PRI(log_mask))
165  {
166 #if defined(USE_DEBUG)
167  if (debug_on >= 2)
168  (*_printf) ("syslog: Dropping %s (%d) priority message, "
169  "facility %s (%d), pri 0x%04X\n",
170  pri_name, LOG_PRI(pri),
171  fac_name, LOG_FAC(pri), pri);
172 #endif
173  return;
174  }
175 
176 #if defined(USE_DEBUG)
177  if (debug_on >= 2)
178  (*_printf) ("syslog: Accepting %s (%d) priority message, "
179  "facility %s (%d), pri 0x%04X\n",
180  pri_name, LOG_PRI(pri),
181  fac_name, LOG_FAC(pri), pri);
182 #endif
183 
184  /* Build the message
185  */
186  time (&t);
187  p = tbuffer;
188  p += _snprintk (p, left, "<%3d>%.15s ", pri, ctime_r(&t,ct_buf)+4);
189  left -= p - tbuffer;
190  pri_end = 1 + strchr (tbuffer, '>');
191 
192  if (log_tag)
193  {
194  p += _snprintk (p, left, log_tag);
195  left -= p - tbuffer;
196  }
197  if (log_stat & LOG_PID)
198  {
199  p += _snprintk (p, left, "[%d]", getpid());
200  left -= p - tbuffer;
201  }
202  if (log_tag)
203  {
204  p += _snprintk (p, left, ": ");
205  left -= p - tbuffer;
206  }
207 
208  SOCK_ERRNO (saved_errno);
209  p += _vsnprintk (p, left, fmt, ap);
210  if (*(p-1) != '\n')
211  {
212  *p++ = '\n';
213  *p = '\0';
214  }
215 
216  if (!log_opened)
217  openlog (log_tag, log_stat | LOG_NDELAY, log_facil);
218 
219  if (log_file)
220  _fputsk (pri_end, log_file);
221 
222  if ((log_stat & LOG_PERROR) ||
223  ((pri & LOG_PRIMASK) == LOG_ERR && (log_stat & LOG_CONS)))
224  _fputsk (pri_end, stdout);
225 
226  if (log_sock)
227  {
228  int len = strlen (tbuffer);
229  char *err;
230 
231  len = sock_write (log_sock, (const BYTE*)tbuffer, len);
232  err = (char*) sockerr (log_sock);
233 
234  if (len <= 0 || err)
235  {
236  err = strdup (err);
237  sock_close (log_sock);
238  free (log_sock);
239  log_sock = NULL;
240  syslog (log_stat | LOG_ERR, "UDP write failed: %s\n", err);
241  if (err)
242  free (err);
243  }
244  }
245 }
246 
247 
248 static const char *getlogname (void)
249 {
250  const char *name = get_argv0();
251  char *dot;
252  static char buf [MAX_PATHLEN];
253 
254  if (name && name[0])
255  {
256  name = _strlcpy (buf, name, sizeof(buf));
257  dot = strrchr (name, '.');
258  if (dot && (!strnicmp(dot,".exe",4) || !strnicmp(dot,".exp",4)))
259  {
260  strcpy (dot, ".log");
261  return (name);
262  }
263  }
264  return ("$unknown.log");
265 }
266 
267 static int openloghost (char **errbuf)
268 {
269  struct servent *sp;
270  struct hostent *hp;
271  static char buf [80];
272 
273  *errbuf = NULL;
274 
275  if (log_sock) /* reopen UDP connection */
276  {
277  sock_close (log_sock);
278  log_sock = NULL;
279  }
280 
281  sp = getservbyname ("syslog", "udp");
282  if (sp)
283  syslog_port = htons (sp->s_port);
284 
285  log_host = _inet_addr (syslog_host_name);
286  if (!log_host)
287  {
288  hp = gethostbyname (syslog_host_name);
289  if (!hp)
290  {
291  sprintf (buf, "unknown host `%s'", syslog_host_name);
292  *errbuf = buf;
293  return (0);
294  }
295  log_host = ntohl (*(DWORD*)hp->h_addr);
296  }
297 
298  if (!log_sock)
299  {
300  log_sock = (sock_type*) malloc (sizeof(_udp_Socket));
301  if (!log_sock)
302  {
303  _strlcpy (buf, strerror(errno), sizeof(buf));
304  *errbuf = buf;
305  return (0);
306  }
307  }
308 
309  if (!udp_open(&log_sock->udp, 0, log_host, syslog_port, NULL))
310  {
311  _strlcpy (buf, sockerr(log_sock), sizeof(buf));
312  *errbuf = buf;
313  sock_close (log_sock);
314  free (log_sock);
315  log_sock = NULL;
316  return (0);
317  }
318  return (1);
319 }
320 
321 static void _closelog (void)
322 {
323  closelog();
324 }
325 
326 void W32_CALL openlog (const char *ident, int logstat, int logfac)
327 {
328  static BOOL done = FALSE;
329  BOOL fail = FALSE;
330  char *error = NULL;
331 
332  if (ident)
333  log_tag = (char*)ident;
334  log_stat = logstat;
335 
336  if (logfac && !(logfac & ~LOG_FACMASK)) /* legal facility */
337  log_facil = logfac;
338 
339  if (!syslog_file_name[0]) /* not set in wattcp.cfg */
340  _strlcpy (syslog_file_name, getlogname(), sizeof(syslog_file_name));
341 
342  if (syslog_mask)
343  {
344  TCP_CONSOLE_MSG (2, ("setlogmask(0x%04X)\n", syslog_mask));
345  setlogmask (syslog_mask);
346  }
347 
348  /* Open immediately
349  * !! fix-me: the LOG_NDELAY flag is really for the network connection
350  */
351  if (syslog_file_name[0] && (log_stat & LOG_NDELAY))
352  {
353  if (log_file) /* reopen */
354  fclose (log_file);
355 
356  log_opened = TRUE;
357 
358  log_file = fopen (syslog_file_name, "at");
359  if (!log_file || fputs("\n",log_file) == EOF)
360  {
361  log_file = NULL;
362  error = strerror (errno);
363  fail = TRUE;
364  }
365 #if !defined(__BORLANDC__) /* buggy output with this */
366  else
367  {
368  static char fbuf [256];
369  setvbuf (log_file, fbuf, _IOLBF, sizeof(fbuf)); /* line-buffered */
370  }
371 #endif
372  }
373 
374  if (syslog_host_name[0] && !openloghost(&error))
375  fail = TRUE;
376 
377  _printk_file = log_file;
378 
379  if (!done)
380  {
381  RUNDOWN_ADD (_closelog, 110);
382  _printk_init (2000, NULL);
383  done = TRUE;
384  if (log_sock)
385  {
386  syslog (LOG_INFO, "syslog client at %I started", htonl(my_ip_addr));
387  if (_inet_addr(syslog_host_name))
388  syslog (LOG_INFO, "Logging to host %s", syslog_host_name);
389  else syslog (LOG_INFO, "Logging to host %s (%I)",
390  syslog_host_name, htonl(log_host));
391  }
392  }
393 
394  if (fail && (log_stat & LOG_CONS))
395  fprintf (stdout, "syslog: %s\n", error);
396 }
397 
398 
399 int W32_CALL setlogmask (int new_mask)
400 {
401  int old = log_mask;
402  if (new_mask)
403  log_mask = new_mask;
404  return (old);
405 }
406 
407 
408 char * W32_CALL setlogtag (char *new_tag)
409 {
410  char *old = log_tag;
411  log_tag = new_tag;
412  return (old);
413 }
414 
415 #include "nochkstk.h"
416 
417 void W32_CALL closelog (void)
418 {
419  if (!_watt_fatal_error)
420  {
421  if (log_file)
422  fclose (log_file);
423 
424  if (log_sock)
425  {
426  sock_close (log_sock);
427  free (log_sock);
428  }
429  }
430  log_sock = NULL;
431  log_file = NULL;
432  log_opened = FALSE;
433 }
434 #endif /* USE_BSD_API */
435 
436 
437 #if defined(TEST_PROG)
438 
439 #include "sock_ini.h"
440 #include "pcdbug.h"
441 
442 int main (void)
443 {
444  dbug_init();
445  sock_init();
446  debug_on = 2;
447 
448  openlog ("test", LOG_PID, LOG_LOCAL2);
449 
450  syslog (LOG_NOTICE, "NOTICE: time now %t. file %s at line %d\n",
451  __FILE__, __LINE__);
452 
453  SOCK_ERRNO (ENOMEM);
454  syslog (LOG_ERR | LOG_LOCAL0, "ERR: Allocation failed; %m");
455 
456  syslog (LOG_DEBUG, "DEBUG: my_ip_addr = %I", htonl(my_ip_addr));
457 
458  SOCK_ERRNO (ENETDOWN);
459  syslog (LOG_ALERT, "ALERT: Connection failed; %m");
460 
461  syslog (LOG_EMERG, "EMERG: Coffee mug empty");
462 
463  syslog (LOG_CRIT|LOG_KERN, "CRIT: Kernel message: General error reading disk.");
464 
465  SOCK_ERRNO (EILSEQ);
466  syslog (LOG_WARNING, "WARNING: Multibyte error; %m");
467 
468  syslog (LOG_INFO, "INFO: Leaving main()");
469 
470  printf ("Done. ");
471  if (log_file)
472  printf ("Look at `%s'", syslog_file_name);
473 
474  closelog();
475  return (0);
476 }
477 #endif /* TEST_PROG */
const char * get_argv0(void)
Return argv[0] as passed to main().
Definition: pcconfig.c:668
int W32_CALL udp_open(_udp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler)
UDP active open.
Definition: pctcp.c:192
Definition: netdb.h:122
int W32_CALL sock_close(sock_type *s)
Close a UDP/TCP socket.
Definition: pctcp.c:3139
Definition: netdb.h:102
Core definitions.
const char * list_lookup(DWORD type, const struct search_list *list, int num)
Search 'list' for 'type' and return it's name.
Definition: misc.c:929
int W32_CALL sock_write(sock_type *s, const BYTE *data, int len)
Writes data and returns length written.
Definition: pctcp.c:2960
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
FILE * _printk_file
Definition: printk.c:58
DWORD W32_CALL _inet_addr(const char *s)
Convert a string into an IP-address.
Definition: netaddr.c:69
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
BOOL _watt_fatal_error
Definition: misc.c:60
char * ctime_r(const time_t *t, char *res)
A reentrant ctime().
Definition: misc.c:878
Definition: syslog.h:79
int main(int argc, char **argv)
Definition: echo.c:223