rule.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /*
  2. * This file is part of the zlog Library.
  3. *
  4. * Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
  5. *
  6. * Licensed under the LGPL v2.1, see the file COPYING in base directory.
  7. */
  8. #include "fmacros.h"
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <syslog.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <pthread.h>
  19. #include "rule.h"
  20. #include "format.h"
  21. #include "buf.h"
  22. #include "thread.h"
  23. #include "level_list.h"
  24. #include "rotater.h"
  25. #include "spec.h"
  26. #include "conf.h"
  27. #include "zc_defs.h"
  28. void zlog_rule_profile(zlog_rule_t * a_rule, int flag)
  29. {
  30. int i;
  31. zlog_spec_t *a_spec;
  32. zc_assert(a_rule,);
  33. zc_profile(flag, "---rule:[%p][%s%c%d]-[%d,%d][%s,%p,%d:%ld*%d~%s][%d][%d][%s:%s:%p];[%p]---",
  34. a_rule,
  35. a_rule->category,
  36. a_rule->compare_char,
  37. a_rule->level,
  38. a_rule->file_perms,
  39. a_rule->file_open_flags,
  40. a_rule->file_path,
  41. a_rule->dynamic_specs,
  42. a_rule->static_fd,
  43. a_rule->archive_max_size,
  44. a_rule->archive_max_count,
  45. a_rule->archive_path,
  46. a_rule->pipe_fd,
  47. a_rule->syslog_facility,
  48. a_rule->record_name,
  49. a_rule->record_path,
  50. a_rule->record_func,
  51. a_rule->format);
  52. if (a_rule->dynamic_specs) {
  53. zc_arraylist_foreach(a_rule->dynamic_specs, i, a_spec) {
  54. zlog_spec_profile(a_spec, flag);
  55. }
  56. }
  57. return;
  58. }
  59. /*******************************************************************************/
  60. static int zlog_rule_output_static_file_single(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  61. {
  62. struct stat stb;
  63. int do_file_reload = 0;
  64. int redo_inode_stat = 0;
  65. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  66. zc_error("zlog_format_gen_msg fail");
  67. return -1;
  68. }
  69. /* check if the output file was changed by an external tool by comparing the inode to our saved off one */
  70. if (stat(a_rule->file_path, &stb)) {
  71. if (errno != ENOENT) {
  72. zc_error("stat fail on [%s], errno[%d]", a_rule->file_path, errno);
  73. return -1;
  74. } else {
  75. do_file_reload = 1;
  76. redo_inode_stat = 1; /* we'll have to restat the newly created file to get the inode info */
  77. }
  78. } else {
  79. do_file_reload = (stb.st_ino != a_rule->static_ino || stb.st_dev != a_rule->static_dev);
  80. }
  81. if (do_file_reload) {
  82. close(a_rule->static_fd);
  83. a_rule->static_fd = open(a_rule->file_path,
  84. O_WRONLY | O_APPEND | O_CREAT | a_rule->file_open_flags,
  85. a_rule->file_perms);
  86. if (a_rule->static_fd < 0) {
  87. zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno);
  88. return -1;
  89. }
  90. /* save off the new dev/inode info from the stat call we already did */
  91. if (redo_inode_stat) {
  92. if (stat(a_rule->file_path, &stb)) {
  93. zc_error("stat fail on new file[%s], errno[%d]", a_rule->file_path, errno);
  94. return -1;
  95. }
  96. }
  97. a_rule->static_dev = stb.st_dev;
  98. a_rule->static_ino = stb.st_ino;
  99. }
  100. if (write(a_rule->static_fd,
  101. zlog_buf_str(a_thread->msg_buf),
  102. zlog_buf_len(a_thread->msg_buf)) < 0) {
  103. zc_error("write fail, errno[%d]", errno);
  104. return -1;
  105. }
  106. /* not so thread safe here, as multiple thread may ++fsync_count at the same time */
  107. if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) {
  108. a_rule->fsync_count = 0;
  109. if (fsync(a_rule->static_fd)) {
  110. zc_error("fsync[%d] fail, errno[%d]", a_rule->static_fd, errno);
  111. }
  112. }
  113. return 0;
  114. }
  115. static char * zlog_rule_gen_archive_path(zlog_rule_t *a_rule, zlog_thread_t *a_thread)
  116. {
  117. int i;
  118. zlog_spec_t *a_spec;
  119. if (!a_rule->archive_specs) return a_rule->archive_path;
  120. zlog_buf_restart(a_thread->archive_path_buf);
  121. zc_arraylist_foreach(a_rule->archive_specs, i, a_spec) {
  122. if (zlog_spec_gen_archive_path(a_spec, a_thread)) {
  123. zc_error("zlog_spec_gen_path fail");
  124. return NULL;
  125. }
  126. }
  127. zlog_buf_seal(a_thread->archive_path_buf);
  128. return zlog_buf_str(a_thread->archive_path_buf);
  129. }
  130. static int zlog_rule_output_static_file_rotate(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  131. {
  132. size_t len;
  133. struct zlog_stat info;
  134. int fd;
  135. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  136. zc_error("zlog_format_gen_msg fail");
  137. return -1;
  138. }
  139. fd = open(a_rule->file_path,
  140. a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms);
  141. if (fd < 0) {
  142. zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno);
  143. return -1;
  144. }
  145. len = zlog_buf_len(a_thread->msg_buf);
  146. if (write(fd, zlog_buf_str(a_thread->msg_buf), len) < 0) {
  147. zc_error("write fail, errno[%d]", errno);
  148. close(fd);
  149. return -1;
  150. }
  151. if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) {
  152. a_rule->fsync_count = 0;
  153. if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno);
  154. }
  155. if (close(fd) < 0) {
  156. zc_error("close fail, maybe cause by write, errno[%d]", errno);
  157. return -1;
  158. }
  159. if (len > a_rule->archive_max_size) {
  160. zc_debug("one msg's len[%ld] > archive_max_size[%ld], no rotate",
  161. (long)len, (long)a_rule->archive_max_size);
  162. return 0;
  163. }
  164. if (stat(a_rule->file_path, &info)) {
  165. zc_warn("stat [%s] fail, errno[%d], maybe in rotating", a_rule->file_path, errno);
  166. return 0;
  167. }
  168. /* file not so big, return */
  169. if (info.st_size + len < a_rule->archive_max_size) return 0;
  170. if (zlog_rotater_rotate(zlog_env_conf->rotater,
  171. a_rule->file_path, len,
  172. zlog_rule_gen_archive_path(a_rule, a_thread),
  173. a_rule->archive_max_size, a_rule->archive_max_count)
  174. ) {
  175. zc_error("zlog_rotater_rotate fail");
  176. return -1;
  177. } /* success or no rotation do nothing */
  178. return 0;
  179. }
  180. /* return path success
  181. * return NULL fail
  182. */
  183. #define zlog_rule_gen_path(a_rule, a_thread) do { \
  184. int i; \
  185. zlog_spec_t *a_spec; \
  186. \
  187. zlog_buf_restart(a_thread->path_buf); \
  188. \
  189. zc_arraylist_foreach(a_rule->dynamic_specs, i, a_spec) { \
  190. if (zlog_spec_gen_path(a_spec, a_thread)) { \
  191. zc_error("zlog_spec_gen_path fail"); \
  192. return -1; \
  193. } \
  194. } \
  195. \
  196. zlog_buf_seal(a_thread->path_buf); \
  197. } while(0)
  198. static int zlog_rule_output_dynamic_file_single(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  199. {
  200. int fd;
  201. zlog_rule_gen_path(a_rule, a_thread);
  202. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  203. zc_error("zlog_format_output fail");
  204. return -1;
  205. }
  206. fd = open(zlog_buf_str(a_thread->path_buf),
  207. a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms);
  208. if (fd < 0) {
  209. zc_error("open file[%s] fail, errno[%d]", zlog_buf_str(a_thread->path_buf), errno);
  210. return -1;
  211. }
  212. if (write(fd, zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) {
  213. zc_error("write fail, errno[%d]", errno);
  214. close(fd);
  215. return -1;
  216. }
  217. if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) {
  218. a_rule->fsync_count = 0;
  219. if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno);
  220. }
  221. if (close(fd) < 0) {
  222. zc_error("close fail, maybe cause by write, errno[%d]", errno);
  223. return -1;
  224. }
  225. return 0;
  226. }
  227. static int zlog_rule_output_dynamic_file_rotate(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  228. {
  229. int fd;
  230. char *path;
  231. size_t len;
  232. struct zlog_stat info;
  233. zlog_rule_gen_path(a_rule, a_thread);
  234. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  235. zc_error("zlog_format_output fail");
  236. return -1;
  237. }
  238. path = zlog_buf_str(a_thread->path_buf);
  239. fd = open(path, a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms);
  240. if (fd < 0) {
  241. zc_error("open file[%s] fail, errno[%d]", zlog_buf_str(a_thread->path_buf), errno);
  242. return -1;
  243. }
  244. len = zlog_buf_len(a_thread->msg_buf);
  245. if (write(fd, zlog_buf_str(a_thread->msg_buf), len) < 0) {
  246. zc_error("write fail, errno[%d]", errno);
  247. close(fd);
  248. return -1;
  249. }
  250. if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) {
  251. a_rule->fsync_count = 0;
  252. if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno);
  253. }
  254. if (close(fd) < 0) {
  255. zc_error("write fail, maybe cause by write, errno[%d]", errno);
  256. return -1;
  257. }
  258. if (len > a_rule->archive_max_size) {
  259. zc_debug("one msg's len[%ld] > archive_max_size[%ld], no rotate",
  260. (long)len, (long) a_rule->archive_max_size);
  261. return 0;
  262. }
  263. if (stat(path, &info)) {
  264. zc_warn("stat [%s] fail, errno[%d], maybe in rotating", path, errno);
  265. return 0;
  266. }
  267. /* file not so big, return */
  268. if (info.st_size + len < a_rule->archive_max_size) return 0;
  269. if (zlog_rotater_rotate(zlog_env_conf->rotater,
  270. path, len,
  271. zlog_rule_gen_archive_path(a_rule, a_thread),
  272. a_rule->archive_max_size, a_rule->archive_max_count)
  273. ) {
  274. zc_error("zlog_rotater_rotate fail");
  275. return -1;
  276. } /* success or no rotation do nothing */
  277. return 0;
  278. }
  279. static int zlog_rule_output_pipe(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  280. {
  281. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  282. zc_error("zlog_format_gen_msg fail");
  283. return -1;
  284. }
  285. if (write(a_rule->pipe_fd,
  286. zlog_buf_str(a_thread->msg_buf),
  287. zlog_buf_len(a_thread->msg_buf)) < 0) {
  288. zc_error("write fail, errno[%d]", errno);
  289. return -1;
  290. }
  291. return 0;
  292. }
  293. static int zlog_rule_output_syslog(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  294. {
  295. zlog_level_t *a_level;
  296. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  297. zc_error("zlog_format_gen_msg fail");
  298. return -1;
  299. }
  300. /*
  301. msg = a_thread->msg_buf->start;
  302. msg_len = a_thread->msg_buf->end - a_thread->msg_buf->start;
  303. */
  304. a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level);
  305. zlog_buf_seal(a_thread->msg_buf);
  306. syslog(a_rule->syslog_facility | a_level->syslog_level,
  307. "%s", zlog_buf_str(a_thread->msg_buf));
  308. return 0;
  309. }
  310. static int zlog_rule_output_static_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  311. {
  312. zlog_msg_t msg;
  313. if (!a_rule->record_func) {
  314. zc_error("user defined record funcion for [%s] not set, no output",
  315. a_rule->record_name);
  316. return -1;
  317. }
  318. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  319. zc_error("zlog_format_gen_msg fail");
  320. return -1;
  321. }
  322. zlog_buf_seal(a_thread->msg_buf);
  323. msg.buf = zlog_buf_str(a_thread->msg_buf);
  324. msg.len = zlog_buf_len(a_thread->msg_buf);
  325. msg.path = a_rule->record_path;
  326. if (a_rule->record_func(&msg)) {
  327. zc_error("a_rule->record fail");
  328. return -1;
  329. }
  330. return 0;
  331. }
  332. static int zlog_rule_output_dynamic_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  333. {
  334. zlog_msg_t msg;
  335. if (!a_rule->record_func) {
  336. zc_error("user defined record funcion for [%s] not set, no output",
  337. a_rule->record_name);
  338. return -1;
  339. }
  340. zlog_rule_gen_path(a_rule, a_thread);
  341. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  342. zc_error("zlog_format_gen_msg fail");
  343. return -1;
  344. }
  345. zlog_buf_seal(a_thread->msg_buf);
  346. msg.buf = zlog_buf_str(a_thread->msg_buf);
  347. msg.len = zlog_buf_len(a_thread->msg_buf);
  348. msg.path = zlog_buf_str(a_thread->path_buf);
  349. if (a_rule->record_func(&msg)) {
  350. zc_error("a_rule->record fail");
  351. return -1;
  352. }
  353. return 0;
  354. }
  355. static int zlog_rule_output_stdout(zlog_rule_t * a_rule,
  356. zlog_thread_t * a_thread)
  357. {
  358. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  359. zc_error("zlog_format_gen_msg fail");
  360. return -1;
  361. }
  362. if (write(STDOUT_FILENO,
  363. zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) {
  364. zc_error("write fail, errno[%d]", errno);
  365. return -1;
  366. }
  367. return 0;
  368. }
  369. static int zlog_rule_output_stderr(zlog_rule_t * a_rule,
  370. zlog_thread_t * a_thread)
  371. {
  372. if (zlog_format_gen_msg(a_rule->format, a_thread)) {
  373. zc_error("zlog_format_gen_msg fail");
  374. return -1;
  375. }
  376. if (write(STDERR_FILENO,
  377. zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) {
  378. zc_error("write fail, errno[%d]", errno);
  379. return -1;
  380. }
  381. return 0;
  382. }
  383. /*******************************************************************************/
  384. static int syslog_facility_atoi(char *facility)
  385. {
  386. /* guess no unix system will choose -187
  387. * as its syslog facility, so it is a safe return value
  388. */
  389. zc_assert(facility, -187);
  390. if (STRICMP(facility, ==, "LOG_LOCAL0")) return LOG_LOCAL0;
  391. if (STRICMP(facility, ==, "LOG_LOCAL1")) return LOG_LOCAL1;
  392. if (STRICMP(facility, ==, "LOG_LOCAL2")) return LOG_LOCAL2;
  393. if (STRICMP(facility, ==, "LOG_LOCAL3")) return LOG_LOCAL3;
  394. if (STRICMP(facility, ==, "LOG_LOCAL4")) return LOG_LOCAL4;
  395. if (STRICMP(facility, ==, "LOG_LOCAL5")) return LOG_LOCAL5;
  396. if (STRICMP(facility, ==, "LOG_LOCAL6")) return LOG_LOCAL6;
  397. if (STRICMP(facility, ==, "LOG_LOCAL7")) return LOG_LOCAL7;
  398. if (STRICMP(facility, ==, "LOG_USER")) return LOG_USER;
  399. if (STRICMP(facility, ==, "LOG_AUTHPRIV")) return LOG_AUTHPRIV;
  400. if (STRICMP(facility, ==, "LOG_CRON")) return LOG_CRON;
  401. if (STRICMP(facility, ==, "LOG_DAEMON")) return LOG_DAEMON;
  402. if (STRICMP(facility, ==, "LOG_FTP")) return LOG_FTP;
  403. if (STRICMP(facility, ==, "LOG_KERN")) return LOG_KERN;
  404. if (STRICMP(facility, ==, "LOG_LPR")) return LOG_LPR;
  405. if (STRICMP(facility, ==, "LOG_MAIL")) return LOG_MAIL;
  406. if (STRICMP(facility, ==, "LOG_NEWS")) return LOG_NEWS;
  407. if (STRICMP(facility, ==, "LOG_SYSLOG")) return LOG_SYSLOG;
  408. return LOG_AUTHPRIV;
  409. zc_error("wrong syslog facility[%s], must in LOG_LOCAL[0-7] or LOG_USER", facility);
  410. return -187;
  411. }
  412. static int zlog_rule_parse_path(char *path_start, /* start with a " */
  413. char *path_str, size_t path_size, zc_arraylist_t **path_specs,
  414. int *time_cache_count)
  415. {
  416. char *p, *q;
  417. size_t len;
  418. zlog_spec_t *a_spec;
  419. zc_arraylist_t *specs;
  420. p = path_start + 1;
  421. q = strrchr(p, '"');
  422. if (!q) {
  423. zc_error("matching \" not found in conf line[%s]", path_start);
  424. return -1;
  425. }
  426. len = q - p;
  427. if (len > path_size - 1) {
  428. zc_error("file_path too long %ld > %ld", len, path_size - 1);
  429. return -1;
  430. }
  431. memcpy(path_str, p, len);
  432. /* replace any environment variables like %E(HOME) */
  433. if (zc_str_replace_env(path_str, path_size)) {
  434. zc_error("zc_str_replace_env fail");
  435. return -1;
  436. }
  437. if (strchr(path_str, '%') == NULL) {
  438. /* static, no need create specs */
  439. return 0;
  440. }
  441. specs = zc_arraylist_new((zc_arraylist_del_fn)zlog_spec_del);
  442. if (!path_specs) {
  443. zc_error("zc_arraylist_new fail");
  444. return -1;
  445. }
  446. for (p = path_str; *p != '\0'; p = q) {
  447. a_spec = zlog_spec_new(p, &q, time_cache_count);
  448. if (!a_spec) {
  449. zc_error("zlog_spec_new fail");
  450. goto err;
  451. }
  452. if (zc_arraylist_add(specs, a_spec)) {
  453. zc_error("zc_arraylist_add fail");
  454. goto err;
  455. }
  456. }
  457. *path_specs = specs;
  458. return 0;
  459. err:
  460. if (specs) zc_arraylist_del(specs);
  461. if (a_spec) zlog_spec_del(a_spec);
  462. return -1;
  463. }
  464. zlog_rule_t *zlog_rule_new(char *line,
  465. zc_arraylist_t *levels,
  466. zlog_format_t * default_format,
  467. zc_arraylist_t * formats,
  468. unsigned int file_perms,
  469. size_t fsync_period,
  470. int * time_cache_count)
  471. {
  472. int rc = 0;
  473. int nscan = 0;
  474. int nread = 0;
  475. zlog_rule_t *a_rule;
  476. char selector[MAXLEN_CFG_LINE + 1];
  477. char category[MAXLEN_CFG_LINE + 1];
  478. char level[MAXLEN_CFG_LINE + 1];
  479. char *action;
  480. char output[MAXLEN_CFG_LINE + 1];
  481. char format_name[MAXLEN_CFG_LINE + 1];
  482. char file_path[MAXLEN_CFG_LINE + 1];
  483. char archive_max_size[MAXLEN_CFG_LINE + 1];
  484. char *file_limit;
  485. char *p;
  486. char *q;
  487. size_t len;
  488. zc_assert(line, NULL);
  489. zc_assert(default_format, NULL);
  490. zc_assert(formats, NULL);
  491. a_rule = calloc(1, sizeof(zlog_rule_t));
  492. if (!a_rule) {
  493. zc_error("calloc fail, errno[%d]", errno);
  494. return NULL;
  495. }
  496. a_rule->file_perms = file_perms;
  497. a_rule->fsync_period = fsync_period;
  498. /* line [f.INFO "%H/log/aa.log", 20MB * 12; MyTemplate]
  499. * selector [f.INFO]
  500. * *action ["%H/log/aa.log", 20MB * 12; MyTemplate]
  501. */
  502. memset(&selector, 0x00, sizeof(selector));
  503. nscan = sscanf(line, "%s %n", selector, &nread);
  504. if (nscan != 1) {
  505. zc_error("sscanf [%s] fail, selector", line);
  506. goto err;
  507. }
  508. action = line + nread;
  509. /*
  510. * selector [f.INFO]
  511. * category [f]
  512. * level [.INFO]
  513. */
  514. memset(category, 0x00, sizeof(category));
  515. memset(level, 0x00, sizeof(level));
  516. nscan = sscanf(selector, " %[^.].%s", category, level);
  517. if (nscan != 2) {
  518. zc_error("sscanf [%s] fail, category or level is null",
  519. selector);
  520. goto err;
  521. }
  522. /* check and set category */
  523. for (p = category; *p != '\0'; p++) {
  524. if ((!isalnum(*p)) && (*p != '_') && (*p != '-') && (*p != '*') && (*p != '!')) {
  525. zc_error("category name[%s] character is not in [a-Z][0-9][_!*-]", category);
  526. goto err;
  527. }
  528. }
  529. /* as one line can't be longer than MAXLEN_CFG_LINE, same as category */
  530. strcpy(a_rule->category, category);
  531. /* check and set level */
  532. switch (level[0]) {
  533. case '=':
  534. /* aa.=debug */
  535. a_rule->compare_char = '=';
  536. p = level + 1;
  537. break;
  538. case '!':
  539. /* aa.!debug */
  540. a_rule->compare_char = '!';
  541. p = level + 1;
  542. break;
  543. case '*':
  544. /* aa.* */
  545. a_rule->compare_char = '*';
  546. p = level;
  547. break;
  548. default:
  549. /* aa.debug */
  550. a_rule->compare_char = '.';
  551. p = level;
  552. break;
  553. }
  554. a_rule->level = zlog_level_list_atoi(levels, p);
  555. /* level_bit is a bitmap represents which level can be output
  556. * 32bytes, [0-255] levels, see level.c
  557. * which bit field is 1 means allow output and 0 not
  558. */
  559. switch (a_rule->compare_char) {
  560. case '=':
  561. memset(a_rule->level_bitmap, 0x00, sizeof(a_rule->level_bitmap));
  562. a_rule->level_bitmap[a_rule->level / 8] |= (1 << (7 - a_rule->level % 8));
  563. break;
  564. case '!':
  565. memset(a_rule->level_bitmap, 0xFF, sizeof(a_rule->level_bitmap));
  566. a_rule->level_bitmap[a_rule->level / 8] &= ~(1 << (7 - a_rule->level % 8));
  567. break;
  568. case '*':
  569. memset(a_rule->level_bitmap, 0xFF, sizeof(a_rule->level_bitmap));
  570. break;
  571. case '.':
  572. memset(a_rule->level_bitmap, 0x00, sizeof(a_rule->level_bitmap));
  573. a_rule->level_bitmap[a_rule->level / 8] |= ~(0xFF << (8 - a_rule->level % 8));
  574. memset(a_rule->level_bitmap + a_rule->level / 8 + 1, 0xFF,
  575. sizeof(a_rule->level_bitmap) - a_rule->level / 8 - 1);
  576. break;
  577. }
  578. /* action ["%H/log/aa.log", 20MB * 12 ; MyTemplate]
  579. * output ["%H/log/aa.log", 20MB * 12]
  580. * format [MyTemplate]
  581. */
  582. memset(output, 0x00, sizeof(output));
  583. memset(format_name, 0x00, sizeof(format_name));
  584. nscan = sscanf(action, " %[^;];%s", output, format_name);
  585. if (nscan < 1) {
  586. zc_error("sscanf [%s] fail", action);
  587. goto err;
  588. }
  589. /* check and get format */
  590. if (STRCMP(format_name, ==, "")) {
  591. zc_debug("no format specified, use default");
  592. a_rule->format = default_format;
  593. } else {
  594. int i;
  595. int find_flag = 0;
  596. zlog_format_t *a_format;
  597. zc_arraylist_foreach(formats, i, a_format) {
  598. if (zlog_format_has_name(a_format, format_name)) {
  599. a_rule->format = a_format;
  600. find_flag = 1;
  601. break;
  602. }
  603. }
  604. if (!find_flag) {
  605. zc_error("in conf file can't find format[%s], pls check",
  606. format_name);
  607. goto err;
  608. }
  609. }
  610. /* output [-"%E(HOME)/log/aa.log" , 20MB*12] [>syslog , LOG_LOCAL0 ]
  611. * file_path [-"%E(HOME)/log/aa.log" ] [>syslog ]
  612. * *file_limit [20MB * 12 ~ "aa.#i.log" ] [LOG_LOCAL0]
  613. */
  614. memset(file_path, 0x00, sizeof(file_path));
  615. nscan = sscanf(output, " %[^,],", file_path);
  616. if (nscan < 1) {
  617. zc_error("sscanf [%s] fail", action);
  618. goto err;
  619. }
  620. file_limit = strchr(output, ',');
  621. if (file_limit) {
  622. file_limit++; /* skip the , */
  623. while( isspace(*file_limit) ) {
  624. file_limit++;
  625. }
  626. }
  627. p = NULL;
  628. switch (file_path[0]) {
  629. case '-' :
  630. /* sync file each time write log */
  631. if (file_path[1] != '"') {
  632. zc_error(" - must set before a file output");
  633. goto err;
  634. }
  635. /* no need to fsync, as file is opened by O_SYNC, write immediately */
  636. a_rule->fsync_period = 0;
  637. p = file_path + 1;
  638. a_rule->file_open_flags = O_SYNC;
  639. /* fall through */
  640. case '"' :
  641. if (!p) p = file_path;
  642. rc = zlog_rule_parse_path(p, a_rule->file_path, sizeof(a_rule->file_path),
  643. &(a_rule->dynamic_specs), time_cache_count);
  644. if (rc) {
  645. zc_error("zlog_rule_parse_path fail");
  646. goto err;
  647. }
  648. if (file_limit) {
  649. memset(archive_max_size, 0x00, sizeof(archive_max_size));
  650. nscan = sscanf(file_limit, " %[0-9MmKkBb] * %d ~",
  651. archive_max_size, &(a_rule->archive_max_count));
  652. if (nscan) {
  653. a_rule->archive_max_size = zc_parse_byte_size(archive_max_size);
  654. }
  655. p = strchr(file_limit, '"');
  656. if (p) { /* archive file path exist */
  657. rc = zlog_rule_parse_path(p,
  658. a_rule->archive_path, sizeof(a_rule->file_path),
  659. &(a_rule->archive_specs), time_cache_count);
  660. if (rc) {
  661. zc_error("zlog_rule_parse_path fail");
  662. goto err;
  663. }
  664. p = strchr(a_rule->archive_path, '#');
  665. if ( (p == NULL) || ((strchr(p, 'r') == NULL) && (strchr(p, 's') == NULL))) {
  666. zc_error("archive_path must contain #r or #s");
  667. goto err;
  668. }
  669. }
  670. }
  671. /* try to figure out if the log file path is dynamic or static */
  672. if (a_rule->dynamic_specs) {
  673. if (a_rule->archive_max_size <= 0) {
  674. a_rule->output = zlog_rule_output_dynamic_file_single;
  675. } else {
  676. a_rule->output = zlog_rule_output_dynamic_file_rotate;
  677. }
  678. } else {
  679. struct stat stb;
  680. if (a_rule->archive_max_size <= 0) {
  681. a_rule->output = zlog_rule_output_static_file_single;
  682. } else {
  683. /* as rotate, so need to reopen everytime */
  684. a_rule->output = zlog_rule_output_static_file_rotate;
  685. }
  686. a_rule->static_fd = open(a_rule->file_path,
  687. O_WRONLY | O_APPEND | O_CREAT | a_rule->file_open_flags,
  688. a_rule->file_perms);
  689. if (a_rule->static_fd < 0) {
  690. zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno);
  691. goto err;
  692. }
  693. /* save off the inode information for checking for a changed file later on */
  694. if (fstat(a_rule->static_fd, &stb)) {
  695. zc_error("stat [%s] fail, errno[%d], failing to open static_fd", a_rule->file_path, errno);
  696. goto err;
  697. }
  698. if (a_rule->archive_max_size > 0) {
  699. close(a_rule->static_fd);
  700. a_rule->static_fd = -1;
  701. }
  702. a_rule->static_dev = stb.st_dev;
  703. a_rule->static_ino = stb.st_ino;
  704. }
  705. break;
  706. case '|' :
  707. a_rule->pipe_fp = popen(output + 1, "w");
  708. if (!a_rule->pipe_fp) {
  709. zc_error("popen fail, errno[%d]", errno);
  710. goto err;
  711. }
  712. a_rule->pipe_fd = fileno(a_rule->pipe_fp);
  713. if (a_rule->pipe_fd < 0 ) {
  714. zc_error("fileno fail, errno[%d]", errno);
  715. goto err;
  716. }
  717. a_rule->output = zlog_rule_output_pipe;
  718. break;
  719. case '>' :
  720. if (STRNCMP(file_path + 1, ==, "syslog", 6)) {
  721. a_rule->syslog_facility = syslog_facility_atoi(file_limit);
  722. if (a_rule->syslog_facility == -187) {
  723. zc_error("-187 get");
  724. goto err;
  725. }
  726. a_rule->output = zlog_rule_output_syslog;
  727. openlog(NULL, LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_USER);
  728. } else if (STRNCMP(file_path + 1, ==, "stdout", 6)) {
  729. a_rule->output = zlog_rule_output_stdout;
  730. } else if (STRNCMP(file_path + 1, ==, "stderr", 6)) {
  731. a_rule->output = zlog_rule_output_stderr;
  732. } else {
  733. zc_error
  734. ("[%s]the string after is not syslog, stdout or stderr", output);
  735. goto err;
  736. }
  737. break;
  738. case '$' :
  739. sscanf(file_path + 1, "%s", a_rule->record_name);
  740. if (file_limit) { /* record path exists */
  741. p = strchr(file_limit, '"');
  742. if (!p) {
  743. zc_error("record_path not start with \", [%s]", file_limit);
  744. goto err;
  745. }
  746. p++; /* skip 1st " */
  747. q = strrchr(p, '"');
  748. if (!q) {
  749. zc_error("matching \" not found in conf line[%s]", p);
  750. goto err;
  751. }
  752. len = q - p;
  753. if (len > sizeof(a_rule->record_path) - 1) {
  754. zc_error("record_path too long %ld > %ld", len, sizeof(a_rule->record_path) - 1);
  755. goto err;
  756. }
  757. memcpy(a_rule->record_path, p, len);
  758. }
  759. /* replace any environment variables like %E(HOME) */
  760. rc = zc_str_replace_env(a_rule->record_path, sizeof(a_rule->record_path));
  761. if (rc) {
  762. zc_error("zc_str_replace_env fail");
  763. goto err;
  764. }
  765. /* try to figure out if the log file path is dynamic or static */
  766. if (strchr(a_rule->record_path, '%') == NULL) {
  767. a_rule->output = zlog_rule_output_static_record;
  768. } else {
  769. zlog_spec_t *a_spec;
  770. a_rule->output = zlog_rule_output_dynamic_record;
  771. a_rule->dynamic_specs = zc_arraylist_new((zc_arraylist_del_fn)zlog_spec_del);
  772. if (!(a_rule->dynamic_specs)) {
  773. zc_error("zc_arraylist_new fail");
  774. goto err;
  775. }
  776. for (p = a_rule->record_path; *p != '\0'; p = q) {
  777. a_spec = zlog_spec_new(p, &q, time_cache_count);
  778. if (!a_spec) {
  779. zc_error("zlog_spec_new fail");
  780. goto err;
  781. }
  782. rc = zc_arraylist_add(a_rule->dynamic_specs, a_spec);
  783. if (rc) {
  784. zlog_spec_del(a_spec);
  785. zc_error("zc_arraylist_add fail");
  786. goto err;
  787. }
  788. }
  789. }
  790. break;
  791. default :
  792. zc_error("the 1st char[%c] of file_path[%s] is wrong",
  793. file_path[0], file_path);
  794. goto err;
  795. }
  796. return a_rule;
  797. err:
  798. zlog_rule_del(a_rule);
  799. return NULL;
  800. }
  801. void zlog_rule_del(zlog_rule_t * a_rule)
  802. {
  803. zc_assert(a_rule,);
  804. if (a_rule->dynamic_specs) {
  805. zc_arraylist_del(a_rule->dynamic_specs);
  806. a_rule->dynamic_specs = NULL;
  807. }
  808. if (a_rule->static_fd > 0) {
  809. if (close(a_rule->static_fd)) {
  810. zc_error("close fail, maybe cause by write, errno[%d]", errno);
  811. }
  812. }
  813. if (a_rule->pipe_fp) {
  814. if (pclose(a_rule->pipe_fp) == -1) {
  815. zc_error("pclose fail, errno[%d]", errno);
  816. }
  817. }
  818. if (a_rule->archive_specs) {
  819. zc_arraylist_del(a_rule->archive_specs);
  820. a_rule->archive_specs = NULL;
  821. }
  822. zc_debug("zlog_rule_del[%p]", a_rule);
  823. free(a_rule);
  824. return;
  825. }
  826. /*******************************************************************************/
  827. int zlog_rule_output(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
  828. {
  829. switch (a_rule->compare_char) {
  830. case '*' :
  831. return a_rule->output(a_rule, a_thread);
  832. break;
  833. case '.' :
  834. if (a_thread->event->level >= a_rule->level) {
  835. return a_rule->output(a_rule, a_thread);
  836. } else {
  837. return 0;
  838. }
  839. break;
  840. case '=' :
  841. if (a_thread->event->level == a_rule->level) {
  842. return a_rule->output(a_rule, a_thread);
  843. } else {
  844. return 0;
  845. }
  846. break;
  847. case '!' :
  848. if (a_thread->event->level != a_rule->level) {
  849. return a_rule->output(a_rule, a_thread);
  850. } else {
  851. return 0;
  852. }
  853. break;
  854. }
  855. return 0;
  856. }
  857. /*******************************************************************************/
  858. int zlog_rule_is_wastebin(zlog_rule_t * a_rule)
  859. {
  860. zc_assert(a_rule, -1);
  861. if (STRCMP(a_rule->category, ==, "!")) {
  862. return 1;
  863. }
  864. return 0;
  865. }
  866. /*******************************************************************************/
  867. int zlog_rule_match_category(zlog_rule_t * a_rule, char *category)
  868. {
  869. zc_assert(a_rule, -1);
  870. zc_assert(category, -1);
  871. if (STRCMP(a_rule->category, ==, "*")) {
  872. /* '*' match anything, so go on */
  873. return 1;
  874. } else if (STRCMP(a_rule->category, ==, category)) {
  875. /* accurate compare */
  876. return 1;
  877. } else {
  878. /* aa_ match aa_xx & aa, but not match aa1_xx */
  879. size_t len;
  880. len = strlen(a_rule->category);
  881. if (a_rule->category[len - 1] == '_') {
  882. if (strlen(category) == len - 1) {
  883. len--;
  884. }
  885. if (STRNCMP(a_rule->category, ==, category, len)) {
  886. return 1;
  887. }
  888. }
  889. }
  890. return 0;
  891. }
  892. /*******************************************************************************/
  893. int zlog_rule_set_record(zlog_rule_t * a_rule, zc_hashtable_t *records)
  894. {
  895. zlog_record_t *a_record;
  896. if (a_rule->output != zlog_rule_output_static_record
  897. && a_rule->output != zlog_rule_output_dynamic_record) {
  898. return 0; /* fliter, may go through not record rule */
  899. }
  900. a_record = zc_hashtable_get(records, a_rule->record_name);
  901. if (a_record) {
  902. a_rule->record_func = a_record->output;
  903. }
  904. return 0;
  905. }