logsys.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713
  1. /*
  2. * Copyright (c) 2002-2004 MontaVista Software, Inc.
  3. * Copyright (c) 2006-2009 Red Hat, Inc.
  4. *
  5. * Author: Steven Dake (sdake@redhat.com)
  6. * Author: Lon Hohberger (lhh@redhat.com)
  7. * Author: Fabio M. Di Nitto (fdinitto@redhat.com)
  8. *
  9. * All rights reserved.
  10. *
  11. * This software licensed under BSD license, the text of which follows:
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. * - Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  22. * contributors may be used to endorse or promote products derived from this
  23. * software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. * THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include <config.h>
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <string.h>
  41. #include <stdarg.h>
  42. #include <sys/time.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #include <time.h>
  46. #include <errno.h>
  47. #include <sys/types.h>
  48. #include <sys/socket.h>
  49. #include <unistd.h>
  50. #if defined(COROSYNC_LINUX)
  51. #include <linux/un.h>
  52. #endif
  53. #if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  54. #include <sys/un.h>
  55. #endif
  56. #define SYSLOG_NAMES
  57. #include <syslog.h>
  58. #include <stdlib.h>
  59. #include <pthread.h>
  60. #include <limits.h>
  61. #include <corosync/engine/logsys.h>
  62. #define YIELD_AFTER_LOG_OPS 10
  63. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  64. /*
  65. * similar to syslog facilities/priorities tables,
  66. * make a tag table for internal use
  67. */
  68. #ifdef SYSLOG_NAMES
  69. struct syslog_names {
  70. const char *c_name;
  71. int c_val;
  72. };
  73. struct syslog_names tagnames[] =
  74. {
  75. { "log", LOGSYS_TAG_LOG },
  76. { "enter", LOGSYS_TAG_ENTER },
  77. { "leave", LOGSYS_TAG_LEAVE },
  78. { "trace1", LOGSYS_TAG_TRACE1 },
  79. { "trace2", LOGSYS_TAG_TRACE2 },
  80. { "trace3", LOGSYS_TAG_TRACE3 },
  81. { "trace4", LOGSYS_TAG_TRACE4 },
  82. { "trace5", LOGSYS_TAG_TRACE5 },
  83. { "trace6", LOGSYS_TAG_TRACE6 },
  84. { "trace7", LOGSYS_TAG_TRACE7 },
  85. { "trace8", LOGSYS_TAG_TRACE8 },
  86. { NULL, -1 }
  87. };
  88. #endif
  89. /*
  90. * These are not static so they can be read from the core file
  91. */
  92. int *flt_data;
  93. int flt_data_size;
  94. #define COMBINE_BUFFER_SIZE 2048
  95. /* values for logsys_logger init_status */
  96. #define LOGSYS_LOGGER_INIT_DONE 0
  97. #define LOGSYS_LOGGER_NEEDS_INIT 1
  98. static int logsys_system_needs_init = LOGSYS_LOGGER_NEEDS_INIT;
  99. static int logsys_after_log_ops_yield = 10;
  100. /*
  101. * need unlogical order to preserve 64bit alignment
  102. */
  103. struct logsys_logger {
  104. char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]; /* subsystem name */
  105. char *logfile; /* log to file */
  106. FILE *logfile_fp; /* track file descriptor */
  107. unsigned int mode; /* subsystem mode */
  108. unsigned int debug; /* debug on|off */
  109. unsigned int tags; /* trace tags */
  110. int syslog_facility; /* facility */
  111. int syslog_priority; /* priority */
  112. int logfile_priority; /* priority to file */
  113. int init_status; /* internal field to handle init queues
  114. for subsystems */
  115. };
  116. /*
  117. * operating global variables
  118. */
  119. static struct logsys_logger logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT + 1];
  120. static int wthread_active = 0;
  121. static int wthread_should_exit = 0;
  122. static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
  123. static unsigned int records_written = 1;
  124. static pthread_t logsys_thread_id;
  125. static pthread_cond_t logsys_cond;
  126. static pthread_mutex_t logsys_cond_mutex;
  127. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  128. static pthread_spinlock_t logsys_idx_spinlock;
  129. #else
  130. static pthread_mutex_t logsys_idx_mutex = PTHREAD_MUTEX_INITIALIZER;
  131. #endif
  132. static unsigned int log_rec_idx;
  133. static int logsys_buffer_full = 0;
  134. static char *format_buffer=NULL;
  135. static int log_requests_pending = 0;
  136. static int log_requests_lost = 0;
  137. void *logsys_rec_end;
  138. #define FDHEAD_INDEX (flt_data_size)
  139. #define FDTAIL_INDEX (flt_data_size + 1)
  140. /* forward declarations */
  141. static void logsys_close_logfile(int subsysid);
  142. #ifdef LOGSYS_DEBUG
  143. static char *decode_mode(int subsysid, char *buf, size_t buflen)
  144. {
  145. memset(buf, 0, buflen);
  146. if (logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE)
  147. snprintf(buf+strlen(buf), buflen, "FILE,");
  148. if (logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_STDERR)
  149. snprintf(buf+strlen(buf), buflen, "STDERR,");
  150. if (logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_SYSLOG)
  151. snprintf(buf+strlen(buf), buflen, "SYSLOG,");
  152. if (subsysid == LOGSYS_MAX_SUBSYS_COUNT) {
  153. if (logsys_loggers[subsysid].mode & LOGSYS_MODE_FORK)
  154. snprintf(buf+strlen(buf), buflen, "FORK,");
  155. if (logsys_loggers[subsysid].mode & LOGSYS_MODE_THREADED)
  156. snprintf(buf+strlen(buf), buflen, "THREADED,");
  157. }
  158. memset(buf+strlen(buf)-1,0,1);
  159. return buf;
  160. }
  161. static char *decode_tags(int subsysid, char *buf, size_t buflen)
  162. {
  163. unsigned int i;
  164. memset(buf, 0, buflen);
  165. for (i = 0; tagnames[i].c_name != NULL; i++) {
  166. if (logsys_loggers[subsysid].tags & tagnames[i].c_val) {
  167. snprintf(buf+strlen(buf), buflen, "%s,", tagnames[i].c_name);
  168. }
  169. }
  170. memset(buf+strlen(buf)-1,0,1);
  171. return buf;
  172. }
  173. static const char *decode_debug(int subsysid)
  174. {
  175. if (logsys_loggers[subsysid].debug)
  176. return "on";
  177. return "off";
  178. }
  179. static const char *decode_status(int subsysid)
  180. {
  181. if (!logsys_loggers[subsysid].init_status)
  182. return "INIT_DONE";
  183. return "NEEDS_INIT";
  184. }
  185. static void dump_subsys_config(int subsysid)
  186. {
  187. char modebuf[1024];
  188. char tagbuf[1024];
  189. fprintf(stderr,
  190. "ID: %d\n"
  191. "subsys: %s\n"
  192. "logfile: %s\n"
  193. "logfile_fp: %p\n"
  194. "mode: %s\n"
  195. "debug: %s\n"
  196. "tags: %s\n"
  197. "syslog_fac: %s\n"
  198. "syslog_pri: %s\n"
  199. "logfile_pri: %s\n"
  200. "init_status: %s\n",
  201. subsysid,
  202. logsys_loggers[subsysid].subsys,
  203. logsys_loggers[subsysid].logfile,
  204. logsys_loggers[subsysid].logfile_fp,
  205. decode_mode(subsysid, modebuf, sizeof(modebuf)),
  206. decode_debug(subsysid),
  207. decode_tags(subsysid, tagbuf, sizeof(tagbuf)),
  208. logsys_facility_name_get(logsys_loggers[subsysid].syslog_facility),
  209. logsys_priority_name_get(logsys_loggers[subsysid].syslog_priority),
  210. logsys_priority_name_get(logsys_loggers[subsysid].logfile_priority),
  211. decode_status(subsysid));
  212. }
  213. static void dump_full_config(void)
  214. {
  215. int i;
  216. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  217. if (strlen(logsys_loggers[i].subsys) > 0)
  218. dump_subsys_config(i);
  219. }
  220. }
  221. #endif
  222. /*
  223. * Helpers for _logsys_log_rec functionality
  224. */
  225. static inline void my_memcpy_32bit (int *dest, const int *src, unsigned int words)
  226. {
  227. unsigned int word_idx;
  228. for (word_idx = 0; word_idx < words; word_idx++) {
  229. dest[word_idx] = src[word_idx];
  230. }
  231. }
  232. static inline void my_memcpy_8bit (char *dest, const char *src,
  233. unsigned int bytes)
  234. {
  235. unsigned int byte_idx;
  236. for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
  237. dest[byte_idx] = src[byte_idx];
  238. }
  239. }
  240. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  241. static void logsys_lock (void)
  242. {
  243. pthread_spin_lock (&logsys_idx_spinlock);
  244. }
  245. static void logsys_unlock (void)
  246. {
  247. pthread_spin_unlock (&logsys_idx_spinlock);
  248. }
  249. #else
  250. static void logsys_lock (void)
  251. {
  252. pthread_mutex_lock (&logsys_idx_mutex);
  253. }
  254. static void logsys_unlock (void)
  255. {
  256. pthread_mutex_unlock (&logsys_idx_mutex);
  257. }
  258. #endif
  259. /*
  260. * Before any write operation, a reclaim on the buffer area must be executed
  261. */
  262. static inline void records_reclaim (unsigned int idx, unsigned int words)
  263. {
  264. unsigned int should_reclaim;
  265. should_reclaim = 0;
  266. if ((idx + words) >= flt_data_size) {
  267. logsys_buffer_full = 1;
  268. }
  269. if (logsys_buffer_full == 0) {
  270. return;
  271. }
  272. logsys_lock();
  273. if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
  274. if (idx + words >= flt_data[FDTAIL_INDEX]) {
  275. should_reclaim = 1;
  276. }
  277. } else {
  278. if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
  279. should_reclaim = 1;
  280. }
  281. }
  282. if (should_reclaim) {
  283. int words_needed = 0;
  284. words_needed = words + 1;
  285. do {
  286. unsigned int old_tail;
  287. words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
  288. old_tail = flt_data[FDTAIL_INDEX];
  289. flt_data[FDTAIL_INDEX] =
  290. (flt_data[FDTAIL_INDEX] +
  291. flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
  292. if (log_rec_idx == old_tail) {
  293. log_requests_lost += 1;
  294. log_rec_idx = flt_data[FDTAIL_INDEX];
  295. }
  296. } while (words_needed > 0);
  297. }
  298. logsys_unlock();
  299. }
  300. #define idx_word_step(idx) \
  301. do { \
  302. if (idx > (flt_data_size - 1)) { \
  303. idx = 0; \
  304. } \
  305. } while (0);
  306. #define idx_buffer_step(idx) \
  307. do { \
  308. if (idx > (flt_data_size - 1)) { \
  309. idx = ((idx) % (flt_data_size)); \
  310. } \
  311. } while (0);
  312. /*
  313. * Internal threaded logging implementation
  314. */
  315. static inline int strcpy_cutoff (char *dest, const char *src, size_t cutoff,
  316. size_t buf_len)
  317. {
  318. size_t len = strlen (src);
  319. if (buf_len <= 1) {
  320. if (buf_len == 0)
  321. dest[0] = 0;
  322. return 0;
  323. }
  324. if (cutoff == 0) {
  325. cutoff = len;
  326. }
  327. cutoff = MIN (cutoff, buf_len - 1);
  328. len = MIN (len, cutoff);
  329. memcpy (dest, src, len);
  330. memset (dest + len, ' ', cutoff - len);
  331. dest[cutoff] = '\0';
  332. return (cutoff);
  333. }
  334. /*
  335. * %s SUBSYSTEM
  336. * %n FUNCTION NAME
  337. * %f FILENAME
  338. * %l FILELINE
  339. * %p PRIORITY
  340. * %t TIMESTAMP
  341. * %b BUFFER
  342. *
  343. * any number between % and character specify field length to pad or chop
  344. */
  345. static void log_printf_to_logs (
  346. const char *subsys,
  347. const char *file_name,
  348. const char *function_name,
  349. int file_line,
  350. unsigned int level,
  351. unsigned int tag,
  352. const char *buffer)
  353. {
  354. char output_buffer[COMBINE_BUFFER_SIZE];
  355. char char_time[128];
  356. char line_no[30];
  357. unsigned int format_buffer_idx = 0;
  358. unsigned int output_buffer_idx = 0;
  359. struct timeval tv;
  360. size_t cutoff;
  361. unsigned int len;
  362. int subsysid;
  363. int c, i, has_tag = 0;
  364. subsysid = _logsys_config_subsys_get(subsys);
  365. if (subsysid <= - 1) {
  366. return;
  367. }
  368. for (i = 1; tagnames[i].c_name != NULL; i++) {
  369. if (tag & tagnames[i].c_val) {
  370. if ((logsys_loggers[subsysid].tags & tag) == 0) {
  371. return;
  372. } else {
  373. has_tag = 1;
  374. }
  375. }
  376. }
  377. while ((c = format_buffer[format_buffer_idx])) {
  378. cutoff = 0;
  379. if (c != '%') {
  380. output_buffer[output_buffer_idx++] = c;
  381. format_buffer_idx++;
  382. } else {
  383. const char *p;
  384. format_buffer_idx += 1;
  385. if (isdigit (format_buffer[format_buffer_idx])) {
  386. cutoff = atoi (&format_buffer[format_buffer_idx]);
  387. }
  388. while (isdigit (format_buffer[format_buffer_idx])) {
  389. format_buffer_idx += 1;
  390. }
  391. switch (format_buffer[format_buffer_idx]) {
  392. case 's':
  393. p = subsys;
  394. break;
  395. case 'n':
  396. p = function_name;
  397. break;
  398. case 'f':
  399. p = file_name;
  400. break;
  401. case 'l':
  402. sprintf (line_no, "%d", file_line);
  403. p = line_no;
  404. break;
  405. case 't':
  406. gettimeofday (&tv, NULL);
  407. (void)strftime (char_time, sizeof (char_time), "%b %d %T", localtime ((time_t *)&tv.tv_sec));
  408. p = char_time;
  409. break;
  410. case 'b':
  411. p = buffer;
  412. break;
  413. case 'p':
  414. default:
  415. p = "";
  416. break;
  417. }
  418. len = strcpy_cutoff (output_buffer + output_buffer_idx,
  419. p, cutoff,
  420. (sizeof (output_buffer)
  421. - output_buffer_idx));
  422. output_buffer_idx += len;
  423. format_buffer_idx += 1;
  424. }
  425. if (output_buffer_idx == sizeof (output_buffer)) {
  426. break;
  427. }
  428. }
  429. output_buffer[output_buffer_idx] = '\0';
  430. /*
  431. * Output to syslog
  432. */
  433. if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_SYSLOG) &&
  434. ((level <= logsys_loggers[subsysid].syslog_priority) ||
  435. (logsys_loggers[subsysid].debug != 0) || (has_tag > 0))) {
  436. syslog (level | logsys_loggers[subsysid].syslog_facility, "%s", output_buffer);
  437. }
  438. /*
  439. * Terminate string with \n \0
  440. */
  441. output_buffer[output_buffer_idx++] = '\n';
  442. output_buffer[output_buffer_idx] = '\0';
  443. /*
  444. * Output to configured file
  445. */
  446. if (((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE) &&
  447. (logsys_loggers[subsysid].logfile_fp != NULL)) &&
  448. ((level <= logsys_loggers[subsysid].logfile_priority) ||
  449. (logsys_loggers[subsysid].debug != 0) || (has_tag > 0))) {
  450. /*
  451. * Output to a file
  452. */
  453. if ((fwrite (output_buffer, strlen (output_buffer), 1,
  454. logsys_loggers[subsysid].logfile_fp) < 1) ||
  455. (fflush (logsys_loggers[subsysid].logfile_fp) == EOF)) {
  456. char tmpbuffer[1024];
  457. /*
  458. * if we are here, it's bad.. it's really really bad.
  459. * Best thing would be to light a candle in a church
  460. * and pray.
  461. */
  462. snprintf(tmpbuffer, sizeof(tmpbuffer),
  463. "LOGSYS EMERGENCY: %s Unable to write to %s.",
  464. logsys_loggers[subsysid].subsys,
  465. logsys_loggers[subsysid].logfile);
  466. pthread_mutex_lock (&logsys_config_mutex);
  467. logsys_close_logfile(subsysid);
  468. logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_FILE;
  469. pthread_mutex_unlock (&logsys_config_mutex);
  470. log_printf_to_logs(logsys_loggers[subsysid].subsys,
  471. __FILE__, __FUNCTION__, __LINE__,
  472. LOGSYS_LEVEL_EMERG, 0, tmpbuffer);
  473. }
  474. }
  475. /*
  476. * Output to stderr
  477. */
  478. if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_STDERR) &&
  479. ((level <= logsys_loggers[subsysid].logfile_priority) ||
  480. (logsys_loggers[subsysid].debug != 0) || (has_tag > 0))) {
  481. if (write (STDERR_FILENO, output_buffer, strlen (output_buffer)) < 0) {
  482. char tmpbuffer[1024];
  483. /*
  484. * if we are here, it's bad.. it's really really bad.
  485. * Best thing would be to light 20 candles for each saint
  486. * in the calendar and pray a lot...
  487. */
  488. pthread_mutex_lock (&logsys_config_mutex);
  489. logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_STDERR;
  490. pthread_mutex_unlock (&logsys_config_mutex);
  491. snprintf(tmpbuffer, sizeof(tmpbuffer),
  492. "LOGSYS EMERGENCY: %s Unable to write to STDERR.",
  493. logsys_loggers[subsysid].subsys);
  494. log_printf_to_logs(logsys_loggers[subsysid].subsys,
  495. __FILE__, __FUNCTION__, __LINE__,
  496. LOGSYS_LEVEL_EMERG, 0, tmpbuffer);
  497. }
  498. }
  499. }
  500. static void record_print (const char *buf)
  501. {
  502. const int *buf_uint32t = (const int *)buf;
  503. unsigned int rec_size = buf_uint32t[0];
  504. unsigned int level = buf_uint32t[1];
  505. unsigned int tag = buf_uint32t[2];
  506. unsigned int file_line = buf_uint32t[3];
  507. unsigned int i;
  508. unsigned int words_processed;
  509. unsigned int arg_size_idx;
  510. const void *arguments[64];
  511. unsigned int arg_count;
  512. arg_size_idx = 5;
  513. words_processed = 5;
  514. arg_count = 0;
  515. for (i = 0; words_processed < rec_size; i++) {
  516. arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
  517. arg_size_idx += buf_uint32t[arg_size_idx] + 1;
  518. words_processed += buf_uint32t[arg_size_idx] + 1;
  519. }
  520. /*
  521. * (char *)arguments[0] -> subsystem
  522. * (char *)arguments[1] -> file_name
  523. * (char *)arguments[2] -> function_name
  524. * (char *)arguments[3] -> message
  525. */
  526. log_printf_to_logs (
  527. (char *)arguments[0],
  528. (char *)arguments[1],
  529. (char *)arguments[2],
  530. file_line,
  531. level,
  532. tag,
  533. (char *)arguments[3]);
  534. }
  535. static int record_read (char *buf, int rec_idx, int *log_msg) {
  536. unsigned int rec_size;
  537. unsigned int rec_ident;
  538. unsigned int tag;
  539. int firstcopy, secondcopy;
  540. rec_size = flt_data[rec_idx];
  541. rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
  542. tag = flt_data[(rec_idx + 2) % flt_data_size];
  543. /*
  544. * Not a log record
  545. */
  546. if ((tag & LOGSYS_TAG_LOG) == 0) {
  547. *log_msg = 0;
  548. return ((rec_idx + rec_size) % flt_data_size);
  549. }
  550. /*
  551. * A log record
  552. */
  553. *log_msg = 1;
  554. firstcopy = rec_size;
  555. secondcopy = 0;
  556. if (firstcopy + rec_idx > flt_data_size) {
  557. firstcopy = flt_data_size - rec_idx;
  558. secondcopy -= firstcopy - rec_size;
  559. }
  560. memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
  561. if (secondcopy) {
  562. memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
  563. }
  564. return ((rec_idx + rec_size) % flt_data_size);
  565. }
  566. static inline void wthread_signal (void)
  567. {
  568. if (wthread_active == 0) {
  569. return;
  570. }
  571. pthread_mutex_lock (&logsys_cond_mutex);
  572. pthread_cond_signal (&logsys_cond);
  573. pthread_mutex_unlock (&logsys_cond_mutex);
  574. }
  575. static inline void wthread_wait (void)
  576. {
  577. pthread_mutex_lock (&logsys_cond_mutex);
  578. pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
  579. pthread_mutex_unlock (&logsys_cond_mutex);
  580. }
  581. static inline void wthread_wait_locked (void)
  582. {
  583. pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
  584. pthread_mutex_unlock (&logsys_cond_mutex);
  585. }
  586. static void *logsys_worker_thread (void *data) __attribute__((__noreturn__));
  587. static void *logsys_worker_thread (void *data)
  588. {
  589. int log_msg;
  590. char buf[COMBINE_BUFFER_SIZE];
  591. /*
  592. * Signal wthread_create that the initialization process may continue
  593. */
  594. wthread_signal ();
  595. logsys_lock();
  596. log_rec_idx = flt_data[FDTAIL_INDEX];
  597. logsys_unlock();
  598. for (;;) {
  599. wthread_wait ();
  600. /*
  601. * Read and copy the logging record index position
  602. * It may have been updated by records_reclaim if
  603. * messages were lost or or log_rec on the first new
  604. * logging record available
  605. */
  606. /*
  607. * Process any pending log messages here
  608. */
  609. for (;;) {
  610. int yield_counter = 1;
  611. logsys_lock();
  612. if (log_requests_lost > 0) {
  613. printf ("lost %d log requests\n", log_requests_lost);
  614. log_requests_pending -= log_requests_lost;
  615. log_requests_lost = 0;
  616. }
  617. if (log_requests_pending == 0) {
  618. logsys_unlock();
  619. break;
  620. }
  621. log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
  622. if (log_msg) {
  623. log_requests_pending -= 1;
  624. }
  625. logsys_unlock();
  626. /*
  627. * print the stored buffer
  628. */
  629. if (log_msg) {
  630. record_print (buf);
  631. if (yield_counter++ > logsys_after_log_ops_yield) {
  632. yield_counter = 0;
  633. sched_yield ();
  634. }
  635. }
  636. }
  637. if (wthread_should_exit) {
  638. pthread_exit (NULL);
  639. }
  640. }
  641. }
  642. static void wthread_create (void)
  643. {
  644. int res;
  645. if (wthread_active) {
  646. return;
  647. }
  648. wthread_active = 1;
  649. pthread_mutex_init (&logsys_cond_mutex, NULL);
  650. pthread_cond_init (&logsys_cond, NULL);
  651. pthread_mutex_lock (&logsys_cond_mutex);
  652. res = pthread_create (&logsys_thread_id, NULL,
  653. logsys_worker_thread, NULL);
  654. /*
  655. * Wait for thread to be started
  656. */
  657. wthread_wait_locked ();
  658. }
  659. static int _logsys_config_subsys_get_unlocked (const char *subsys)
  660. {
  661. unsigned int i;
  662. if (!subsys) {
  663. return LOGSYS_MAX_SUBSYS_COUNT;
  664. }
  665. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  666. if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
  667. pthread_mutex_unlock (&logsys_config_mutex);
  668. return i;
  669. }
  670. }
  671. return (-1);
  672. }
  673. static void syslog_facility_reconf (void)
  674. {
  675. closelog();
  676. openlog(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].subsys,
  677. LOG_CONS|LOG_PID,
  678. logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].syslog_facility);
  679. }
  680. /*
  681. * this is always invoked within the mutex, so it's safe to parse the
  682. * whole thing as we need.
  683. */
  684. static void logsys_close_logfile (
  685. int subsysid)
  686. {
  687. int i;
  688. if ((logsys_loggers[subsysid].logfile_fp == NULL) &&
  689. (logsys_loggers[subsysid].logfile == NULL)) {
  690. return;
  691. }
  692. /*
  693. * if there is another subsystem or system using the same fp,
  694. * then we clean our own structs, but we can't close the file
  695. * as it is in use by somebody else.
  696. * Only the last users will be allowed to perform the fclose.
  697. */
  698. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  699. if ((logsys_loggers[i].logfile_fp == logsys_loggers[subsysid].logfile_fp) &&
  700. (i != subsysid)) {
  701. logsys_loggers[subsysid].logfile = NULL;
  702. logsys_loggers[subsysid].logfile_fp = NULL;
  703. return;
  704. }
  705. }
  706. /*
  707. * if we are here, we are the last users of that fp, so we can safely
  708. * close it.
  709. */
  710. fclose (logsys_loggers[subsysid].logfile_fp);
  711. logsys_loggers[subsysid].logfile_fp = NULL;
  712. free (logsys_loggers[subsysid].logfile);
  713. logsys_loggers[subsysid].logfile = NULL;
  714. }
  715. /*
  716. * we need a version that can work when somebody else is already
  717. * holding a config mutex lock or we will never get out of here
  718. */
  719. static int logsys_config_file_set_unlocked (
  720. int subsysid,
  721. const char **error_string,
  722. const char *file)
  723. {
  724. static char error_string_response[512];
  725. int i;
  726. logsys_close_logfile(subsysid);
  727. if ((file == NULL) ||
  728. (strcmp(logsys_loggers[subsysid].subsys, "") == 0)) {
  729. return (0);
  730. }
  731. if (strlen(file) >= PATH_MAX) {
  732. snprintf (error_string_response,
  733. sizeof(error_string_response),
  734. "%s: logfile name exceed maximum system filename lenght\n",
  735. logsys_loggers[subsysid].subsys);
  736. *error_string = error_string_response;
  737. return (-1);
  738. }
  739. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  740. if ((logsys_loggers[i].logfile != NULL) &&
  741. (strcmp (logsys_loggers[i].logfile, file) == 0) &&
  742. (i != subsysid)) {
  743. logsys_loggers[subsysid].logfile =
  744. logsys_loggers[i].logfile;
  745. logsys_loggers[subsysid].logfile_fp =
  746. logsys_loggers[i].logfile_fp;
  747. return (0);
  748. }
  749. }
  750. logsys_loggers[subsysid].logfile = strdup(file);
  751. if (logsys_loggers[subsysid].logfile == NULL) {
  752. snprintf (error_string_response,
  753. sizeof(error_string_response),
  754. "Unable to allocate memory for logfile '%s'\n",
  755. file);
  756. *error_string = error_string_response;
  757. return (-1);
  758. }
  759. logsys_loggers[subsysid].logfile_fp = fopen (file, "a+");
  760. if (logsys_loggers[subsysid].logfile_fp == NULL) {
  761. free(logsys_loggers[subsysid].logfile);
  762. logsys_loggers[subsysid].logfile = NULL;
  763. snprintf (error_string_response,
  764. sizeof(error_string_response),
  765. "Can't open logfile '%s' for reason (%s).\n",
  766. file, strerror (errno));
  767. *error_string = error_string_response;
  768. return (-1);
  769. }
  770. return (0);
  771. }
  772. static void logsys_subsys_init (
  773. const char *subsys,
  774. int subsysid)
  775. {
  776. if (logsys_system_needs_init == LOGSYS_LOGGER_NEEDS_INIT) {
  777. logsys_loggers[subsysid].init_status =
  778. LOGSYS_LOGGER_NEEDS_INIT;
  779. } else {
  780. memcpy(&logsys_loggers[subsysid],
  781. &logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT],
  782. sizeof(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT]));
  783. logsys_loggers[subsysid].init_status =
  784. LOGSYS_LOGGER_INIT_DONE;
  785. }
  786. strncpy (logsys_loggers[subsysid].subsys, subsys,
  787. LOGSYS_MAX_SUBSYS_NAMELEN);
  788. }
  789. /*
  790. * Internal API - exported
  791. */
  792. int _logsys_system_setup(
  793. const char *mainsystem,
  794. unsigned int mode,
  795. unsigned int debug,
  796. const char *logfile,
  797. int logfile_priority,
  798. int syslog_facility,
  799. int syslog_priority,
  800. unsigned int tags)
  801. {
  802. int i;
  803. const char *errstr;
  804. char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];
  805. if ((mainsystem == NULL) ||
  806. (strlen(mainsystem) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
  807. return -1;
  808. }
  809. i = LOGSYS_MAX_SUBSYS_COUNT;
  810. pthread_mutex_lock (&logsys_config_mutex);
  811. snprintf(logsys_loggers[i].subsys,
  812. LOGSYS_MAX_SUBSYS_NAMELEN,
  813. "%s", mainsystem);
  814. logsys_loggers[i].mode = mode;
  815. logsys_loggers[i].debug = debug;
  816. if (logsys_config_file_set_unlocked (i, &errstr, logfile) < 0) {
  817. pthread_mutex_unlock (&logsys_config_mutex);
  818. return (-1);
  819. }
  820. logsys_loggers[i].logfile_priority = logfile_priority;
  821. logsys_loggers[i].syslog_facility = syslog_facility;
  822. logsys_loggers[i].syslog_priority = syslog_priority;
  823. syslog_facility_reconf();
  824. logsys_loggers[i].tags = tags;
  825. logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
  826. logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;
  827. for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
  828. if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
  829. (logsys_loggers[i].init_status ==
  830. LOGSYS_LOGGER_NEEDS_INIT)) {
  831. strncpy (tempsubsys, logsys_loggers[i].subsys,
  832. LOGSYS_MAX_SUBSYS_NAMELEN);
  833. logsys_subsys_init(tempsubsys, i);
  834. }
  835. }
  836. pthread_mutex_unlock (&logsys_config_mutex);
  837. return (0);
  838. }
  839. unsigned int _logsys_subsys_create (const char *subsys)
  840. {
  841. int i;
  842. if ((subsys == NULL) ||
  843. (strlen(subsys) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
  844. return -1;
  845. }
  846. pthread_mutex_lock (&logsys_config_mutex);
  847. i = _logsys_config_subsys_get_unlocked (subsys);
  848. if ((i > -1) && (i < LOGSYS_MAX_SUBSYS_COUNT)) {
  849. pthread_mutex_unlock (&logsys_config_mutex);
  850. return i;
  851. }
  852. for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
  853. if (strcmp (logsys_loggers[i].subsys, "") == 0) {
  854. logsys_subsys_init(subsys, i);
  855. break;
  856. }
  857. }
  858. if (i >= LOGSYS_MAX_SUBSYS_COUNT) {
  859. i = -1;
  860. }
  861. pthread_mutex_unlock (&logsys_config_mutex);
  862. return i;
  863. }
  864. int _logsys_wthread_create (void)
  865. {
  866. if (((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_FORK) == 0) &&
  867. ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) != 0)) {
  868. wthread_create();
  869. atexit (logsys_atexit);
  870. }
  871. return (0);
  872. }
  873. int _logsys_rec_init (unsigned int size)
  874. {
  875. /*
  876. * First record starts at zero
  877. * Last record ends at zero
  878. */
  879. flt_data = malloc ((size + 2) * sizeof (unsigned int));
  880. if (flt_data == NULL) {
  881. return (-1);
  882. }
  883. flt_data_size = size;
  884. flt_data[FDHEAD_INDEX] = 0;
  885. flt_data[FDTAIL_INDEX] = 0;
  886. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  887. pthread_spin_init (&logsys_idx_spinlock, 0);
  888. #endif
  889. return (0);
  890. }
  891. /*
  892. * u32 RECORD SIZE
  893. * u32 record ident
  894. * u32 arg count
  895. * u32 file line
  896. * u32 subsys length
  897. * buffer null terminated subsys
  898. * u32 filename length
  899. * buffer null terminated filename
  900. * u32 filename length
  901. * buffer null terminated function
  902. * u32 arg1 length
  903. * buffer arg1
  904. * ... repeats length & arg
  905. */
  906. void _logsys_log_rec (
  907. int subsysid,
  908. const char *function_name,
  909. const char *file_name,
  910. int file_line,
  911. unsigned int rec_ident,
  912. unsigned int tag,
  913. ...)
  914. {
  915. va_list ap;
  916. const void *buf_args[64];
  917. unsigned int buf_len[64];
  918. unsigned int i;
  919. unsigned int idx;
  920. unsigned int arguments = 0;
  921. unsigned int record_reclaim_size;
  922. unsigned int index_start;
  923. int words_written;
  924. record_reclaim_size = 0;
  925. /*
  926. * Decode VA Args
  927. */
  928. va_start (ap, tag);
  929. arguments = 3;
  930. for (;;) {
  931. buf_args[arguments] = va_arg (ap, void *);
  932. if (buf_args[arguments] == LOGSYS_REC_END) {
  933. break;
  934. }
  935. buf_len[arguments] = va_arg (ap, int);
  936. record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
  937. arguments++;
  938. if (arguments >= 64) {
  939. break;
  940. }
  941. }
  942. va_end (ap);
  943. /*
  944. * Encode logsys subsystem identity, filename, and function
  945. */
  946. buf_args[0] = logsys_loggers[subsysid].subsys;
  947. buf_len[0] = strlen (logsys_loggers[subsysid].subsys) + 1;
  948. buf_args[1] = file_name;
  949. buf_len[1] = strlen (file_name) + 1;
  950. buf_args[2] = function_name;
  951. buf_len[2] = strlen (function_name) + 1;
  952. for (i = 0; i < 3; i++) {
  953. record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
  954. }
  955. idx = flt_data[FDHEAD_INDEX];
  956. index_start = idx;
  957. /*
  958. * Reclaim data needed for record including 4 words for the header
  959. */
  960. records_reclaim (idx, record_reclaim_size + 5);
  961. /*
  962. * Write record size of zero and rest of header information
  963. */
  964. flt_data[idx++] = 0;
  965. idx_word_step(idx);
  966. flt_data[idx++] = rec_ident;
  967. idx_word_step(idx);
  968. flt_data[idx++] = tag;
  969. idx_word_step(idx);
  970. flt_data[idx++] = file_line;
  971. idx_word_step(idx);
  972. flt_data[idx++] = records_written;
  973. idx_word_step(idx);
  974. /*
  975. * Encode all of the arguments into the log message
  976. */
  977. for (i = 0; i < arguments; i++) {
  978. unsigned int bytes;
  979. unsigned int full_words;
  980. unsigned int total_words;
  981. bytes = buf_len[i];
  982. full_words = bytes >> 2;
  983. total_words = (bytes + 3) >> 2;
  984. flt_data[idx++] = total_words;
  985. idx_word_step(idx);
  986. /*
  987. * determine if this is a wrapped write or normal write
  988. */
  989. if (idx + total_words < flt_data_size) {
  990. /*
  991. * dont need to wrap buffer
  992. */
  993. my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
  994. if (bytes % 4) {
  995. my_memcpy_8bit ((char *)&flt_data[idx + full_words],
  996. ((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
  997. }
  998. } else {
  999. /*
  1000. * need to wrap buffer
  1001. */
  1002. unsigned int first;
  1003. unsigned int second;
  1004. first = flt_data_size - idx;
  1005. if (first > full_words) {
  1006. first = full_words;
  1007. }
  1008. second = full_words - first;
  1009. my_memcpy_32bit (&flt_data[idx],
  1010. (const int *)buf_args[i], first);
  1011. my_memcpy_32bit (&flt_data[0],
  1012. (const int *)(((const unsigned char *)buf_args[i]) + (first << 2)),
  1013. second);
  1014. if (bytes % 4) {
  1015. my_memcpy_8bit ((char *)&flt_data[0 + second],
  1016. ((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
  1017. }
  1018. }
  1019. idx += total_words;
  1020. idx_buffer_step (idx);
  1021. }
  1022. words_written = idx - index_start;
  1023. if (words_written < 0) {
  1024. words_written += flt_data_size;
  1025. }
  1026. /*
  1027. * Commit the write of the record size now that the full record
  1028. * is in the memory buffer
  1029. */
  1030. flt_data[index_start] = words_written;
  1031. /*
  1032. * If the index of the current head equals the current log_rec_idx,
  1033. * and this is not a log_printf operation, set the log_rec_idx to
  1034. * the new head position and commit the new head.
  1035. */
  1036. logsys_lock();
  1037. if (tag & LOGSYS_TAG_LOG) {
  1038. log_requests_pending += 1;
  1039. }
  1040. if (log_requests_pending == 0) {
  1041. log_rec_idx = idx;
  1042. }
  1043. flt_data[FDHEAD_INDEX] = idx;
  1044. logsys_unlock();
  1045. records_written++;
  1046. }
  1047. void _logsys_log_vprintf (
  1048. int subsysid,
  1049. const char *function_name,
  1050. const char *file_name,
  1051. int file_line,
  1052. unsigned int level,
  1053. unsigned int tag,
  1054. const char *format,
  1055. va_list ap)
  1056. {
  1057. char logsys_print_buffer[COMBINE_BUFFER_SIZE];
  1058. unsigned int len;
  1059. if (subsysid <= -1) {
  1060. subsysid = LOGSYS_MAX_SUBSYS_COUNT;
  1061. }
  1062. if ((level > logsys_loggers[subsysid].syslog_priority) &&
  1063. (level > logsys_loggers[subsysid].logfile_priority) &&
  1064. (logsys_loggers[subsysid].debug == 0)) {
  1065. return;
  1066. }
  1067. len = vsprintf (logsys_print_buffer, format, ap);
  1068. if (logsys_print_buffer[len - 1] == '\n') {
  1069. logsys_print_buffer[len - 1] = '\0';
  1070. len -= 1;
  1071. }
  1072. /*
  1073. * Create a log record
  1074. */
  1075. _logsys_log_rec (subsysid,
  1076. function_name,
  1077. file_name,
  1078. file_line,
  1079. level,
  1080. tag |= LOGSYS_TAG_LOG,
  1081. logsys_print_buffer, len + 1,
  1082. LOGSYS_REC_END);
  1083. if ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) == 0) {
  1084. /*
  1085. * Output (and block) if the log mode is not threaded otherwise
  1086. * expect the worker thread to output the log data once signaled
  1087. */
  1088. log_printf_to_logs (logsys_loggers[subsysid].subsys,
  1089. file_name, function_name, file_line, level, tag,
  1090. logsys_print_buffer);
  1091. } else {
  1092. /*
  1093. * Signal worker thread to display logging output
  1094. */
  1095. wthread_signal ();
  1096. }
  1097. }
  1098. void _logsys_log_printf (
  1099. int subsysid,
  1100. const char *function_name,
  1101. const char *file_name,
  1102. int file_line,
  1103. unsigned int level,
  1104. unsigned int tag,
  1105. const char *format,
  1106. ...)
  1107. {
  1108. char logsys_print_buffer[COMBINE_BUFFER_SIZE];
  1109. unsigned int len;
  1110. va_list ap;
  1111. if (subsysid <= -1) {
  1112. subsysid = LOGSYS_MAX_SUBSYS_COUNT;
  1113. }
  1114. if ((level > logsys_loggers[subsysid].syslog_priority) &&
  1115. (level > logsys_loggers[subsysid].logfile_priority) &&
  1116. (logsys_loggers[subsysid].debug == 0)) {
  1117. return;
  1118. }
  1119. va_start (ap, format);
  1120. len = vsprintf (logsys_print_buffer, format, ap);
  1121. va_end (ap);
  1122. if (logsys_print_buffer[len - 1] == '\n') {
  1123. logsys_print_buffer[len - 1] = '\0';
  1124. len -= 1;
  1125. }
  1126. /*
  1127. * Create a log record
  1128. */
  1129. _logsys_log_rec (subsysid,
  1130. function_name,
  1131. file_name,
  1132. file_line,
  1133. level,
  1134. tag |= LOGSYS_TAG_LOG,
  1135. logsys_print_buffer, len + 1,
  1136. LOGSYS_REC_END);
  1137. if ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) == 0) {
  1138. /*
  1139. * Output (and block) if the log mode is not threaded otherwise
  1140. * expect the worker thread to output the log data once signaled
  1141. */
  1142. log_printf_to_logs (logsys_loggers[subsysid].subsys,
  1143. file_name, function_name, file_line, level, tag,
  1144. logsys_print_buffer);
  1145. } else {
  1146. /*
  1147. * Signal worker thread to display logging output
  1148. */
  1149. wthread_signal ();
  1150. }
  1151. }
  1152. int _logsys_config_subsys_get (const char *subsys)
  1153. {
  1154. unsigned int i;
  1155. pthread_mutex_lock (&logsys_config_mutex);
  1156. i = _logsys_config_subsys_get_unlocked (subsys);
  1157. pthread_mutex_unlock (&logsys_config_mutex);
  1158. return i;
  1159. }
  1160. /*
  1161. * External Configuration and Initialization API
  1162. */
  1163. void logsys_fork_completed (void)
  1164. {
  1165. logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode &= ~LOGSYS_MODE_FORK;
  1166. _logsys_wthread_create ();
  1167. }
  1168. unsigned int logsys_config_mode_set (const char *subsys, unsigned int mode)
  1169. {
  1170. int i;
  1171. pthread_mutex_lock (&logsys_config_mutex);
  1172. if (subsys != NULL) {
  1173. i = _logsys_config_subsys_get_unlocked (subsys);
  1174. if (i >= 0) {
  1175. logsys_loggers[i].mode = mode;
  1176. i = 0;
  1177. }
  1178. } else {
  1179. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1180. logsys_loggers[i].mode = mode;
  1181. }
  1182. i = 0;
  1183. }
  1184. pthread_mutex_unlock (&logsys_config_mutex);
  1185. return i;
  1186. }
  1187. unsigned int logsys_config_mode_get (const char *subsys)
  1188. {
  1189. int i;
  1190. i = _logsys_config_subsys_get (subsys);
  1191. if (i < 0) {
  1192. return i;
  1193. }
  1194. return logsys_loggers[i].mode;
  1195. }
  1196. unsigned int logsys_config_tags_set (const char *subsys, unsigned int tags)
  1197. {
  1198. int i;
  1199. pthread_mutex_lock (&logsys_config_mutex);
  1200. if (subsys != NULL) {
  1201. i = _logsys_config_subsys_get_unlocked (subsys);
  1202. if (i >= 0) {
  1203. logsys_loggers[i].tags = tags;
  1204. i = 0;
  1205. }
  1206. } else {
  1207. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1208. logsys_loggers[i].tags = tags;
  1209. }
  1210. i = 0;
  1211. }
  1212. pthread_mutex_unlock (&logsys_config_mutex);
  1213. return i;
  1214. }
  1215. unsigned int logsys_config_tags_get (const char *subsys)
  1216. {
  1217. int i;
  1218. i = _logsys_config_subsys_get (subsys);
  1219. if (i < 0) {
  1220. return i;
  1221. }
  1222. return logsys_loggers[i].tags;
  1223. }
  1224. int logsys_config_file_set (
  1225. const char *subsys,
  1226. const char **error_string,
  1227. const char *file)
  1228. {
  1229. int i;
  1230. int res;
  1231. pthread_mutex_lock (&logsys_config_mutex);
  1232. if (subsys != NULL) {
  1233. i = _logsys_config_subsys_get_unlocked (subsys);
  1234. if (i < 0) {
  1235. res = i;
  1236. } else {
  1237. res = logsys_config_file_set_unlocked(i, error_string, file);
  1238. }
  1239. } else {
  1240. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1241. res = logsys_config_file_set_unlocked(i, error_string, file);
  1242. if (res < 0) {
  1243. break;
  1244. }
  1245. }
  1246. }
  1247. pthread_mutex_unlock (&logsys_config_mutex);
  1248. return res;
  1249. }
  1250. int logsys_format_set (const char *format)
  1251. {
  1252. int ret = 0;
  1253. pthread_mutex_lock (&logsys_config_mutex);
  1254. if (format_buffer) {
  1255. free(format_buffer);
  1256. format_buffer = NULL;
  1257. }
  1258. format_buffer = strdup(format ? format : "[%6s] %b");
  1259. if (format_buffer == NULL) {
  1260. ret = -1;
  1261. }
  1262. pthread_mutex_unlock (&logsys_config_mutex);
  1263. return ret;
  1264. }
  1265. char *logsys_format_get (void)
  1266. {
  1267. return format_buffer;
  1268. }
  1269. unsigned int logsys_config_syslog_facility_set (
  1270. const char *subsys,
  1271. unsigned int facility)
  1272. {
  1273. int i;
  1274. pthread_mutex_lock (&logsys_config_mutex);
  1275. if (subsys != NULL) {
  1276. i = _logsys_config_subsys_get_unlocked (subsys);
  1277. if (i >= 0) {
  1278. logsys_loggers[i].syslog_facility = facility;
  1279. if (i == LOGSYS_MAX_SUBSYS_COUNT) {
  1280. syslog_facility_reconf();
  1281. }
  1282. i = 0;
  1283. }
  1284. } else {
  1285. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1286. logsys_loggers[i].syslog_facility = facility;
  1287. }
  1288. syslog_facility_reconf();
  1289. i = 0;
  1290. }
  1291. pthread_mutex_unlock (&logsys_config_mutex);
  1292. return i;
  1293. }
  1294. unsigned int logsys_config_syslog_priority_set (
  1295. const char *subsys,
  1296. unsigned int priority)
  1297. {
  1298. int i;
  1299. pthread_mutex_lock (&logsys_config_mutex);
  1300. if (subsys != NULL) {
  1301. i = _logsys_config_subsys_get_unlocked (subsys);
  1302. if (i >= 0) {
  1303. logsys_loggers[i].syslog_priority = priority;
  1304. i = 0;
  1305. }
  1306. } else {
  1307. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1308. logsys_loggers[i].syslog_priority = priority;
  1309. }
  1310. i = 0;
  1311. }
  1312. pthread_mutex_unlock (&logsys_config_mutex);
  1313. return i;
  1314. }
  1315. unsigned int logsys_config_logfile_priority_set (
  1316. const char *subsys,
  1317. unsigned int priority)
  1318. {
  1319. int i;
  1320. pthread_mutex_lock (&logsys_config_mutex);
  1321. if (subsys != NULL) {
  1322. i = _logsys_config_subsys_get_unlocked (subsys);
  1323. if (i >= 0) {
  1324. logsys_loggers[i].logfile_priority = priority;
  1325. i = 0;
  1326. }
  1327. } else {
  1328. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1329. logsys_loggers[i].logfile_priority = priority;
  1330. }
  1331. i = 0;
  1332. }
  1333. pthread_mutex_unlock (&logsys_config_mutex);
  1334. return i;
  1335. }
  1336. unsigned int logsys_config_debug_set (
  1337. const char *subsys,
  1338. unsigned int debug)
  1339. {
  1340. int i;
  1341. pthread_mutex_lock (&logsys_config_mutex);
  1342. if (subsys != NULL) {
  1343. i = _logsys_config_subsys_get_unlocked (subsys);
  1344. if (i >= 0) {
  1345. logsys_loggers[i].debug = debug;
  1346. i = 0;
  1347. }
  1348. } else {
  1349. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1350. logsys_loggers[i].debug = debug;
  1351. }
  1352. i = 0;
  1353. }
  1354. pthread_mutex_unlock (&logsys_config_mutex);
  1355. return i;
  1356. }
  1357. int logsys_facility_id_get (const char *name)
  1358. {
  1359. unsigned int i;
  1360. for (i = 0; facilitynames[i].c_name != NULL; i++) {
  1361. if (strcasecmp(name, facilitynames[i].c_name) == 0) {
  1362. return (facilitynames[i].c_val);
  1363. }
  1364. }
  1365. return (-1);
  1366. }
  1367. const char *logsys_facility_name_get (unsigned int facility)
  1368. {
  1369. unsigned int i;
  1370. for (i = 0; facilitynames[i].c_name != NULL; i++) {
  1371. if (facility == facilitynames[i].c_val) {
  1372. return (facilitynames[i].c_name);
  1373. }
  1374. }
  1375. return (NULL);
  1376. }
  1377. int logsys_priority_id_get (const char *name)
  1378. {
  1379. unsigned int i;
  1380. for (i = 0; prioritynames[i].c_name != NULL; i++) {
  1381. if (strcasecmp(name, prioritynames[i].c_name) == 0) {
  1382. return (prioritynames[i].c_val);
  1383. }
  1384. }
  1385. return (-1);
  1386. }
  1387. const char *logsys_priority_name_get (unsigned int priority)
  1388. {
  1389. unsigned int i;
  1390. for (i = 0; prioritynames[i].c_name != NULL; i++) {
  1391. if (priority == prioritynames[i].c_val) {
  1392. return (prioritynames[i].c_name);
  1393. }
  1394. }
  1395. return (NULL);
  1396. }
  1397. int logsys_tag_id_get (const char *name)
  1398. {
  1399. unsigned int i;
  1400. for (i = 0; tagnames[i].c_name != NULL; i++) {
  1401. if (strcasecmp(name, tagnames[i].c_name) == 0) {
  1402. return (tagnames[i].c_val);
  1403. }
  1404. }
  1405. return (-1);
  1406. }
  1407. const char *logsys_tag_name_get (unsigned int tag)
  1408. {
  1409. unsigned int i;
  1410. for (i = 0; tagnames[i].c_name != NULL; i++) {
  1411. if (tag == tagnames[i].c_val) {
  1412. return (tagnames[i].c_name);
  1413. }
  1414. }
  1415. return (NULL);
  1416. }
  1417. int logsys_thread_priority_set (
  1418. int policy,
  1419. const struct sched_param *param,
  1420. unsigned int after_log_ops_yield)
  1421. {
  1422. int res = 0;
  1423. if (policy != SCHED_OTHER) {
  1424. res = pthread_setschedparam (logsys_thread_id, policy, param);
  1425. }
  1426. if (after_log_ops_yield > 0) {
  1427. logsys_after_log_ops_yield = after_log_ops_yield;
  1428. }
  1429. return (res);
  1430. }
  1431. int logsys_log_rec_store (const char *filename)
  1432. {
  1433. int fd;
  1434. ssize_t written_size;
  1435. size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
  1436. fd = open (filename, O_CREAT|O_RDWR, 0700);
  1437. if (fd < 0) {
  1438. return (-1);
  1439. }
  1440. written_size = write (fd, flt_data, size_to_write);
  1441. if (close (fd) != 0)
  1442. return (-1);
  1443. if (written_size < 0) {
  1444. return (-1);
  1445. } else if ((size_t)written_size != size_to_write) {
  1446. return (-1);
  1447. }
  1448. return (0);
  1449. }
  1450. void logsys_atexit (void)
  1451. {
  1452. if (wthread_active) {
  1453. wthread_should_exit = 1;
  1454. wthread_signal ();
  1455. pthread_join (logsys_thread_id, NULL);
  1456. }
  1457. }
  1458. void logsys_flush (void)
  1459. {
  1460. wthread_signal ();
  1461. }