syslog.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. * Copyright (C) 2004 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. * -
  33. * Portions Copyright (c) 1983, 1988, 1993
  34. * The Regents of the University of California. All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. * 1. Redistributions of source code must retain the above copyright
  40. * notice, this list of conditions and the following disclaimer.
  41. * 2. Redistributions in binary form must reproduce the above copyright
  42. * notice, this list of conditions and the following disclaimer in the
  43. * documentation and/or other materials provided with the distribution.
  44. * 3. Neither the name of the University nor the names of its contributors
  45. * may be used to endorse or promote products derived from this software
  46. * without specific prior written permission.
  47. *
  48. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  49. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  51. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  52. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  53. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  54. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  55. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  56. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  57. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  58. * SUCH DAMAGE.
  59. */
  60. /*!
  61. * \file pro/syslog.c
  62. * \brief Syslog Client
  63. *
  64. * \verbatim
  65. *
  66. * $Log$
  67. * Revision 1.5 2009/02/13 14:52:05 haraldkipp
  68. * Include memdebug.h for heap management debugging support.
  69. *
  70. * Revision 1.4 2008/08/11 07:00:36 haraldkipp
  71. * BSD types replaced by stdint types (feature request #1282721).
  72. *
  73. * Revision 1.3 2005/08/02 17:47:04 haraldkipp
  74. * Major API documentation update.
  75. *
  76. * Revision 1.2 2004/10/03 18:41:43 haraldkipp
  77. * RAM saving calls added
  78. *
  79. * Revision 1.1 2004/09/19 11:18:45 haraldkipp
  80. * Syslog client added
  81. *
  82. * \endverbatim
  83. */
  84. #include <cfg/syslog.h>
  85. #include <sys/confos.h>
  86. #include <sys/confnet.h>
  87. #include <stdlib.h>
  88. #include <string.h>
  89. #include <stdio.h>
  90. #include <stdarg.h>
  91. #include <io.h>
  92. #include <time.h>
  93. #include <memdebug.h>
  94. #define SYSLOG_INTERNAL
  95. #include <sys/syslog.h>
  96. #ifndef SYSLOG_PERROR_ONLY
  97. #include <sys/socket.h>
  98. #include <arpa/inet.h>
  99. static UDPSOCKET *syslog_sock;
  100. #ifndef SYSLOG_PORT
  101. #define SYSLOG_PORT 514
  102. #endif
  103. static uint32_t syslog_server;
  104. static uint16_t syslog_port = SYSLOG_PORT;
  105. #endif /* SYSLOG_PERROR_ONLY */
  106. /*!
  107. * \addtogroup xgSyslog
  108. */
  109. /*@{*/
  110. static int syslog_fac = LOG_USER;
  111. static int syslog_mask = 0xFF;
  112. static int syslog_stat;
  113. static size_t syslog_taglen;
  114. static char *syslog_tag;
  115. char *syslog_buf;
  116. /*!
  117. * \brief Assemble syslog header.
  118. *
  119. * For internal use only.
  120. *
  121. * \param pri Value of the syslog PRI part.
  122. *
  123. * \return Number of characters in the global syslog buffer.
  124. */
  125. size_t syslog_header(int pri)
  126. {
  127. size_t rc;
  128. /* Remove invalid bits. */
  129. pri &= LOG_PRIMASK | LOG_FACMASK;
  130. /* Check priority against setlog mask values. */
  131. if ((LOG_MASK(LOG_PRI(pri)) & syslog_mask) == 0) {
  132. return 0;
  133. }
  134. /* Set default facility if none specified. */
  135. if ((pri & LOG_FACMASK) == 0) {
  136. pri |= syslog_fac;
  137. }
  138. /* Open log if not done before. */
  139. if (syslog_buf == 0) {
  140. openlog(0, syslog_stat | LOG_NDELAY, syslog_fac);
  141. }
  142. /* PRI field.
  143. ** This is common to all syslog formats. */
  144. rc = sprintf(syslog_buf, "<%d>", pri);
  145. /* VERSION field.
  146. ** Note, that there is no space separator. */
  147. #ifdef SYSLOG_RFC5424
  148. syslog_buf[rc++] = '1';
  149. #endif
  150. /* TIMESTAMP field. */
  151. #ifdef SYSLOG_OMIT_TIMESTAMP
  152. #ifdef SYSLOG_RFC5424
  153. syslog_buf[rc++] = ' ';
  154. syslog_buf[rc++] = '-';
  155. #endif
  156. #else
  157. {
  158. time_t now;
  159. struct _tm *tip;
  160. time(&now);
  161. #ifdef SYSLOG_RFC5424
  162. tip = gmtime(&now);
  163. rc += sprintf(&syslog_buf[rc], " %04d-%02d-%02dT%02d:%02d:%02dZ",
  164. tip->tm_year + 1900, tip->tm_mon + 1, tip->tm_mday,
  165. tip->tm_hour, tip->tm_min, tip->tm_sec);
  166. #else
  167. {
  168. static char mon_name[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  169. tip = localtime(&now);
  170. rc += sprintf(&syslog_buf[rc], "%.3s%3d %02d:%02d:%02d",
  171. &mon_name[tip->tm_mon * 3], tip->tm_mday,
  172. tip->tm_hour, tip->tm_min, tip->tm_sec);
  173. }
  174. #endif /* SYSLOG_RFC5424 */
  175. }
  176. #endif /* SYSLOG_OMIT_TIMESTAMP */
  177. /* HOSTNAME field. */
  178. #ifdef SYSLOG_OMIT_HOSTNAME
  179. #ifdef SYSLOG_RFC5424
  180. syslog_buf[rc++] = ' ';
  181. syslog_buf[rc++] = '-';
  182. #endif
  183. #else
  184. #ifdef SYSLOG_RFC5424
  185. syslog_buf[rc++] = ' ';
  186. if (confnet.cdn_cip_addr) {
  187. strcpy(&syslog_buf[rc], inet_ntoa(confnet.cdn_cip_addr));
  188. rc += strlen(&syslog_buf[rc]);
  189. }
  190. else if (confos.hostname[0]) {
  191. strcpy(&syslog_buf[rc], confos.hostname);
  192. rc += strlen(&syslog_buf[rc]);
  193. }
  194. else if (confnet.cdn_ip_addr) {
  195. strcpy(&syslog_buf[rc], inet_ntoa(confnet.cdn_ip_addr));
  196. rc += strlen(&syslog_buf[rc]);
  197. } else {
  198. syslog_buf[rc++] = '-';
  199. }
  200. #else
  201. syslog_buf[rc++] = ' ';
  202. strcpy(&syslog_buf[rc], confos.hostname);
  203. rc += strlen(confos.hostname);
  204. #endif /* SYSLOG_RFC5424 */
  205. #endif /* SYSLOG_OMIT_HOSTNAME */
  206. /* APP-NAME field. */
  207. if (syslog_taglen) {
  208. syslog_buf[rc++] = ' ';
  209. strcpy(&syslog_buf[rc], syslog_tag);
  210. rc += syslog_taglen;
  211. #ifndef SYSLOG_RFC5424
  212. syslog_buf[rc++] = ':';
  213. #endif
  214. }
  215. /* No PROCID and MSGID fields. */
  216. #ifdef SYSLOG_RFC5424
  217. syslog_buf[rc++] = ' ';
  218. syslog_buf[rc++] = '-';
  219. syslog_buf[rc++] = ' ';
  220. syslog_buf[rc++] = '-';
  221. #endif
  222. syslog_buf[rc++] = ' ';
  223. syslog_buf[rc] = '\0';
  224. return rc;
  225. }
  226. #ifndef SYSLOG_PERROR_ONLY
  227. /*!
  228. * \brief Send syslog buffer.
  229. *
  230. * For internal use only.
  231. *
  232. * \param len Number of valid characters in buffer.
  233. */
  234. void syslog_flush(size_t len)
  235. {
  236. /* Output to stderr if requested */
  237. if (syslog_stat & LOG_PERROR) {
  238. _write(_fileno(stderr), syslog_buf, len);
  239. _write(_fileno(stderr), "\n", 1);
  240. }
  241. /* Output the message to a remote logger. */
  242. if (syslog_server) {
  243. NutUdpSendTo(syslog_sock, syslog_server, syslog_port, syslog_buf, len);
  244. }
  245. }
  246. #endif
  247. /*!
  248. * \brief Print log message.
  249. *
  250. * Alternate form of syslog(), in which the arguments have already been captured
  251. * using the variable-length argument facilities.
  252. *
  253. * \param pri Priority level of this message. See syslog().
  254. * \param fmt Format string containing conversion specifications like printf.
  255. * \param ap List of arguments.
  256. */
  257. void vsyslog(int pri, const char *fmt, va_list ap)
  258. {
  259. /* Build the header. */
  260. size_t cnt = syslog_header(pri);
  261. if (cnt) {
  262. #ifdef SYSLOG_PERROR_ONLY
  263. fputs(syslog_buf, stderr);
  264. vfprintf(stderr, fmt, ap);
  265. fputc('\n', stderr);
  266. #else
  267. cnt += vsnprintf(&syslog_buf[cnt], SYSLOG_MAXBUF - cnt, fmt, ap);
  268. syslog_flush(cnt);
  269. #endif /* SYSLOG_PERROR_ONLY */
  270. }
  271. }
  272. /*!
  273. * \brief Print log message.
  274. *
  275. * The message is tagged with priority.
  276. *
  277. * \param pri Priority level of this message, selected from the following
  278. * ordered list (high to low):
  279. * - LOG_EMERG A panic condition.
  280. * - LOG_ALERT A condition that should be corrected immediately.
  281. * - LOG_CRIT Critical conditions, e.g., hard device errors.
  282. * - LOG_ERR Errors.
  283. * - LOG_WARNING Warning messages.
  284. * - LOG_NOTICE Conditions that are not error conditions, but should
  285. * possibly be handled specially.
  286. * - LOG_INFO Informational messages.
  287. * - LOG_DEBUG Messages that contain information normally of use only
  288. * when debugging a program.
  289. * \param fmt Format string containing conversion specifications like printf.
  290. */
  291. void syslog(int pri, const char *fmt, ...)
  292. {
  293. va_list ap;
  294. va_start(ap, fmt);
  295. vsyslog(pri, (char *) fmt, ap);
  296. va_end(ap);
  297. }
  298. /*!
  299. * \brief Set the log priority mask level.
  300. *
  301. * Calls to syslog() with a priority not set are ignored. The default allows all
  302. * priorities to be logged.
  303. *
  304. * \param logmask New priority mask.
  305. *
  306. * \return Previous mask.
  307. */
  308. int setlogmask(int logmask)
  309. {
  310. int rc = syslog_mask;
  311. if (logmask) {
  312. syslog_mask = logmask;
  313. }
  314. return rc;
  315. }
  316. /*!
  317. * \brief Set the log server's IP address.
  318. *
  319. * \param ip IP address in network byte order. If 0, no messages will be sent out.
  320. * \param port Port number. If 0, then standard port is used.
  321. *
  322. * \return Previous IP or (uint32_t)-1 (all bits set) if UDP is not supported.
  323. */
  324. uint32_t setlogserver(uint32_t ip, uint16_t port)
  325. {
  326. #ifdef SYSLOG_PERROR_ONLY
  327. return (uint32_t)-1;
  328. #else
  329. uint32_t rc = syslog_server;
  330. syslog_server = ip;
  331. if (port) {
  332. syslog_port = port;
  333. }
  334. return rc;
  335. #endif
  336. }
  337. /*!
  338. * \brief Open logging for specialized processing.
  339. *
  340. * This function provides for more specialized processing of the messages sent by
  341. * syslog() and vsyslog().
  342. *
  343. * \param ident This string that will be prepended to every message.
  344. * \param logstat A bit field specifying logging options, which is formed by
  345. * OR'ing one or more of the following values:
  346. * - LOG_CONS Ignored but accepted for compatibility.
  347. * - LOG_NDELAY Ignored but accepted for compatibility.
  348. * - LOG_PERROR Additionally write the message to standard error output.
  349. * - LOG_PID Ignored but accepted for compatibility.
  350. * \param logfac Encodes a default facility to be assigned to all messages that do not
  351. * have an explicit facility encoded:
  352. * - LOG_AUTH The authorization system:
  353. * - LOG_AUTHPRIV The same as LOG_AUTH.
  354. * - LOG_CRON The cron daemon,
  355. * - LOG_DAEMON System daemons, that are not provided for explicitly by
  356. * other facilities.
  357. * - LOG_FTP The file transfer protocol daemon,
  358. * - LOG_KERN Messages generated by the kernel. These should not be
  359. * generated by applications.
  360. * - LOG_LPR The line printer spooling system.
  361. * - LOG_MAIL The mail system.
  362. * - LOG_NEWS The network news system.
  363. * - LOG_SYSLOG Messages generated internally by syslog.
  364. * - LOG_USER This is the default facility identifier if none is specified.
  365. * - LOG_UUCP The UUCP system.
  366. * - LOG_LOCAL0..LOG_LOCAL7 Reserved for local use.
  367. */
  368. void openlog(const char *ident, int logstat, int logfac)
  369. {
  370. if (ident == 0) {
  371. ident = syslog_tag;
  372. syslog_taglen = 0;
  373. }
  374. closelog();
  375. syslog_stat = logstat;
  376. syslog_fac = logfac;
  377. if (ident && *ident) {
  378. syslog_taglen = strlen(ident);
  379. syslog_tag = malloc(syslog_taglen + 1);
  380. strcpy(syslog_tag, ident);
  381. }
  382. if (syslog_stat & LOG_NDELAY) {
  383. if (syslog_buf == 0) {
  384. syslog_buf = malloc(SYSLOG_MAXBUF);
  385. }
  386. #ifndef SYSLOG_PERROR_ONLY
  387. if (syslog_sock == 0) {
  388. syslog_sock = NutUdpCreateSocket(514);
  389. }
  390. #endif
  391. }
  392. }
  393. /*!
  394. * \brief Release system resources occupied by syslog().
  395. */
  396. void closelog(void)
  397. {
  398. if (syslog_buf) {
  399. free(syslog_buf);
  400. syslog_buf = 0;
  401. }
  402. if (syslog_taglen) {
  403. free(syslog_tag);
  404. syslog_taglen = 0;
  405. }
  406. #ifndef SYSLOG_PERROR_ONLY
  407. if (syslog_sock) {
  408. NutUdpDestroySocket(syslog_sock);
  409. syslog_sock = 0;
  410. }
  411. #endif
  412. }
  413. /*@}*/