Nut/OS  4.10.3
API Reference
syslog.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  * -
00033  * Portions Copyright (c) 1983, 1988, 1993
00034  *      The Regents of the University of California.  All rights reserved.
00035  *
00036  * Redistribution and use in source and binary forms, with or without
00037  * modification, are permitted provided that the following conditions
00038  * are met:
00039  * 1. Redistributions of source code must retain the above copyright
00040  *    notice, this list of conditions and the following disclaimer.
00041  * 2. Redistributions in binary form must reproduce the above copyright
00042  *    notice, this list of conditions and the following disclaimer in the
00043  *    documentation and/or other materials provided with the distribution.
00044  * 3. Neither the name of the University nor the names of its contributors
00045  *    may be used to endorse or promote products derived from this software
00046  *    without specific prior written permission.
00047  *
00048  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00049  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00050  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00051  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00052  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00053  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00054  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00055  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00056  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00057  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00058  * SUCH DAMAGE.
00059  */
00060 
00086 #include <cfg/syslog.h>
00087 #include <sys/confos.h>
00088 #include <sys/confnet.h>
00089 
00090 #include <stdlib.h>
00091 #include <string.h>
00092 #include <stdio.h>
00093 #include <stdarg.h>
00094 #include <io.h>
00095 #include <time.h>
00096 #include <memdebug.h>
00097 
00098 #define SYSLOG_INTERNAL
00099 #include <sys/syslog.h>
00100 
00101 #ifndef SYSLOG_PERROR_ONLY
00102 
00103 #include <sys/socket.h>
00104 #include <arpa/inet.h>
00105 static UDPSOCKET *syslog_sock;
00106 
00107 #ifndef SYSLOG_PORT
00108 #define SYSLOG_PORT     514
00109 #endif
00110 
00111 static uint32_t syslog_server;
00112 static uint16_t syslog_port = SYSLOG_PORT;
00113 
00114 #endif                          /* SYSLOG_PERROR_ONLY */
00115 
00120 
00121 static int syslog_fac = LOG_USER;
00122 static int syslog_mask = 0xFF;
00123 
00124 static int syslog_stat;
00125 static size_t syslog_taglen;
00126 static char *syslog_tag;
00127 char *syslog_buf;
00128 
00138 size_t syslog_header(int pri)
00139 {
00140     size_t rc;
00141 
00142     /* Remove invalid bits. */
00143     pri &= LOG_PRIMASK | LOG_FACMASK;
00144 
00145     /* Check priority against setlog mask values. */
00146     if ((LOG_MASK(LOG_PRI(pri)) & syslog_mask) == 0) {
00147         return 0;
00148     }
00149 
00150     /* Set default facility if none specified. */
00151     if ((pri & LOG_FACMASK) == 0) {
00152         pri |= syslog_fac;
00153     }
00154 
00155     /* Open log if not done before. */
00156     if (syslog_buf == 0) {
00157         openlog(0, syslog_stat | LOG_NDELAY, syslog_fac);
00158     }
00159 
00160     /* PRI field. 
00161     ** This is common to all syslog formats. */
00162     rc = sprintf(syslog_buf, "<%d>", pri);
00163 
00164     /* VERSION field. 
00165     ** Note, that there is no space separator. */
00166 #ifdef SYSLOG_RFC5424
00167     syslog_buf[rc++] = '1';
00168 #endif
00169 
00170     /* TIMESTAMP field. */
00171 #ifdef SYSLOG_OMIT_TIMESTAMP
00172 
00173 #ifdef SYSLOG_RFC5424
00174     syslog_buf[rc++] = ' ';
00175     syslog_buf[rc++] = '-';
00176 #endif
00177 
00178 #else
00179     {
00180         time_t now;
00181         struct _tm *tip;
00182 
00183         time(&now);
00184 
00185 #ifdef SYSLOG_RFC5424
00186         tip = gmtime(&now);
00187         rc += sprintf(&syslog_buf[rc], " %04d-%02d-%02dT%02d:%02d:%02dZ",
00188             tip->tm_year + 1900, tip->tm_mon + 1, tip->tm_mday,
00189             tip->tm_hour, tip->tm_min, tip->tm_sec);
00190 #else
00191         {
00192             static char mon_name[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
00193 
00194             tip = localtime(&now);
00195             rc += sprintf(&syslog_buf[rc], "%.3s%3d %02d:%02d:%02d", 
00196                 &mon_name[tip->tm_mon * 3], tip->tm_mday, 
00197                 tip->tm_hour, tip->tm_min, tip->tm_sec);
00198         }
00199 #endif /* SYSLOG_RFC5424 */
00200 
00201     }
00202 #endif /* SYSLOG_OMIT_TIMESTAMP */
00203 
00204     /* HOSTNAME field. */
00205 #ifdef SYSLOG_OMIT_HOSTNAME
00206 
00207 #ifdef SYSLOG_RFC5424
00208     syslog_buf[rc++] = ' ';
00209     syslog_buf[rc++] = '-';
00210 #endif
00211 
00212 #else
00213 
00214 #ifdef SYSLOG_RFC5424
00215     syslog_buf[rc++] = ' ';
00216     if (confnet.cdn_cip_addr) {
00217         strcpy(&syslog_buf[rc], inet_ntoa(confnet.cdn_cip_addr));
00218         rc += strlen(&syslog_buf[rc]);
00219     }
00220     else if (confos.hostname[0]) {
00221         strcpy(&syslog_buf[rc], confos.hostname);
00222         rc += strlen(&syslog_buf[rc]);
00223     }
00224     else if (confnet.cdn_ip_addr) {
00225         strcpy(&syslog_buf[rc], inet_ntoa(confnet.cdn_ip_addr));
00226         rc += strlen(&syslog_buf[rc]);
00227     } else {
00228         syslog_buf[rc++] = '-';
00229     }
00230 #else
00231     syslog_buf[rc++] = ' ';
00232     strcpy(&syslog_buf[rc], confos.hostname);
00233     rc += strlen(confos.hostname);
00234 #endif /* SYSLOG_RFC5424 */
00235 
00236 #endif /* SYSLOG_OMIT_HOSTNAME */
00237 
00238     /* APP-NAME field. */
00239     if (syslog_taglen) {
00240         syslog_buf[rc++] = ' ';
00241         strcpy(&syslog_buf[rc], syslog_tag);
00242         rc += syslog_taglen;
00243 #ifndef SYSLOG_RFC5424
00244         syslog_buf[rc++] = ':';
00245 #endif
00246     }
00247 
00248     /* No PROCID and MSGID fields. */
00249 #ifdef SYSLOG_RFC5424
00250     syslog_buf[rc++] = ' ';
00251     syslog_buf[rc++] = '-';
00252     syslog_buf[rc++] = ' ';
00253     syslog_buf[rc++] = '-';
00254 #endif
00255 
00256     syslog_buf[rc++] = ' ';
00257     syslog_buf[rc] = '\0';
00258     
00259     return rc;
00260 }
00261 
00262 #ifndef SYSLOG_PERROR_ONLY
00263 
00270 void syslog_flush(size_t len)
00271 {
00272     /* Output to stderr if requested */
00273     if (syslog_stat & LOG_PERROR) {
00274         _write(_fileno(stderr), syslog_buf, len);
00275         _write(_fileno(stderr), "\n", 1);
00276     }
00277 
00278     /* Output the message to a remote logger. */
00279     if (syslog_server) {
00280         NutUdpSendTo(syslog_sock, syslog_server, syslog_port, syslog_buf, len);
00281     }
00282 }
00283 #endif
00284 
00295 void vsyslog(int pri, CONST char *fmt, va_list ap)
00296 {
00297     /* Build the header. */
00298     size_t cnt = syslog_header(pri);
00299 
00300     if (cnt) {
00301 #ifdef SYSLOG_PERROR_ONLY
00302         fputs(syslog_buf, stderr);
00303         vfprintf(stderr, fmt, ap);
00304         fputc('\n', stderr);
00305 #else
00306         /* Potentially dangerous. We need vsnprintf() */
00307         if (cnt + strlen(fmt) >= SYSLOG_MAXBUF) {
00308             puts("Buffer overflow");
00309             return;
00310         }
00311         cnt += vsprintf(&syslog_buf[cnt], fmt, ap);
00312         syslog_flush(cnt);
00313 #endif /* SYSLOG_PERROR_ONLY */
00314     }
00315 }
00316 
00336 void syslog(int pri, CONST char *fmt, ...)
00337 {
00338     va_list ap;
00339 
00340     va_start(ap, fmt);
00341     vsyslog(pri, (char *) fmt, ap);
00342     va_end(ap);
00343 }
00344 
00355 int setlogmask(int logmask)
00356 {
00357     int rc = syslog_mask;
00358 
00359     if (logmask) {
00360         syslog_mask = logmask;
00361     }
00362     return rc;
00363 }
00364 
00373 uint32_t setlogserver(uint32_t ip, uint16_t port)
00374 {
00375 #ifdef SYSLOG_PERROR_ONLY
00376     return (uint32_t)-1;
00377 #else
00378     uint32_t rc = syslog_server;
00379 
00380     syslog_server = ip;
00381     if (port) {
00382         syslog_port = port;
00383     }
00384     return rc;
00385 #endif
00386 }
00387 
00419 void openlog(CONST char *ident, int logstat, int logfac)
00420 {
00421     if (ident == 0) {
00422         ident = syslog_tag;
00423         syslog_taglen = 0;
00424     }
00425 
00426     closelog();
00427 
00428     syslog_stat = logstat;
00429     syslog_fac = logfac;
00430     if (ident && *ident) {
00431         syslog_taglen = strlen(ident);
00432         syslog_tag = malloc(syslog_taglen + 1);
00433         strcpy(syslog_tag, ident);
00434     }
00435     if (syslog_stat & LOG_NDELAY) {
00436         if (syslog_buf == 0) {
00437             syslog_buf = malloc(SYSLOG_MAXBUF);
00438         }
00439 #ifndef SYSLOG_PERROR_ONLY
00440         if (syslog_sock == 0) {
00441             syslog_sock = NutUdpCreateSocket(514);
00442         }
00443 #endif
00444     }
00445 }
00446 
00450 void closelog(void)
00451 {
00452     if (syslog_buf) {
00453         free(syslog_buf);
00454         syslog_buf = 0;
00455     }
00456     if (syslog_taglen) {
00457         free(syslog_tag);
00458         syslog_taglen = 0;
00459     }
00460 #ifndef SYSLOG_PERROR_ONLY
00461     if (syslog_sock) {
00462         NutUdpDestroySocket(syslog_sock);
00463         syslog_sock = 0;
00464     }
00465 #endif
00466 }
00467