Tests about a simple python3 fastcgi runner using libfcgi and the Python-C API.
python
c
wsgi
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

logger.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. #include "logger.h"
  2. int pyfcgi_logger_init()
  3. {
  4. pyfcgi_conf_logger_t *conf;
  5. conf = &PyFCGI_conf.logs;
  6. memset(conf, 0, sizeof(pyfcgi_conf_logger_t));
  7. return 0;
  8. }
  9. int pyfcgi_logger_stop()
  10. {
  11. pyfcgi_conf_logger_t *conf;
  12. pyfcgi_logger_format_t *fmt;
  13. size_t i, j;
  14. conf = &PyFCGI_conf.logs;
  15. for(i=0; i<conf->logger_sz; i++)
  16. {
  17. _pyfcgi_logger_free(&(conf->loggers[i]));
  18. }
  19. for(i=0; i<conf->format_sz; i++)
  20. {
  21. fmt = &(conf->formats[i]);
  22. for(j=0; j<fmt->nfield; j++)
  23. {
  24. pyfcgi_logger_field_free(&(fmt->fields[j]));
  25. }
  26. free(conf->formats[i].buf);
  27. }
  28. return 0;
  29. }
  30. void pyfcgi_logger_enable_syslog(const char* nident)
  31. {
  32. pyfcgi_conf_logger_t *conf;
  33. char ident[64];
  34. size_t ret;
  35. conf = &PyFCGI_conf.logs;
  36. if(conf->flags & PYFCGI_LOG_FSYSLOG)
  37. {
  38. closelog();
  39. }
  40. conf->flags |= PYFCGI_LOG_FSYSLOG;
  41. ret = 0;
  42. if(nident)
  43. {
  44. ret = snprintf(ident, 64, PYFCGI_SYSLOG_IDENT_FMT,
  45. getpid(), nident);
  46. }
  47. if(!nident || ret >= 64)
  48. {
  49. ret = snprintf(ident, 64, PYFCGI_SYSLOG_IDENT_FMT_SHORT,
  50. getpid());
  51. if(ret <= 64)
  52. {
  53. snprintf(ident, 64, "pyfcgi");
  54. }
  55. }
  56. if(conf->syslog_ident)
  57. {
  58. free(conf->syslog_ident);
  59. }
  60. conf->syslog_ident = strdup(ident);
  61. openlog(conf->syslog_ident, LOG_CONS | LOG_PERROR, LOG_DAEMON | LOG_USER);
  62. }
  63. void _pyfcgi_logger_free(pyfcgi_logger_t *logger)
  64. {
  65. free(logger->filename);
  66. }
  67. int pyfcgi_logger_add(const char *filename, logmask_t loglvl, logmask_t logtyp,
  68. const char *format)
  69. {
  70. pyfcgi_conf_logger_t *conf;
  71. pyfcgi_logger_t logger;
  72. size_t new_idx;
  73. int err;
  74. conf = &PyFCGI_conf.logs;
  75. if(conf->logger_sz >= PYFCGI_LOGGER_MAX)
  76. {
  77. pyfcgi_log(LOG_ERR, "Maximum of 255 logger reached, unable to add this one...");
  78. return PYFCGI_ERR;
  79. }
  80. if(pyfcgi_logger_format_add(format, &(logger.fmt_id)))
  81. {
  82. return PYFCGI_FATAL;
  83. }
  84. logger.loglvl = loglvl;
  85. logger.logtyp = logtyp;
  86. logger.filename = strdup(filename);
  87. if(!logger.filename)
  88. {
  89. err = errno;
  90. pyfcgi_log(LOG_ALERT,
  91. "Unable to duplicate logger filename : %s",
  92. strerror(err));
  93. return PYFCGI_FATAL;
  94. }
  95. new_idx = conf->logger_sz;
  96. conf->logger_sz++;
  97. conf->loggers[new_idx] = logger;
  98. pyfcgi_logger_open(&(conf->loggers[new_idx]));
  99. return 0;
  100. }
  101. int pyfcgi_logger_format_add(const char* format, size_t* idx)
  102. {
  103. size_t i;
  104. pyfcgi_conf_logger_t *conf;
  105. int ret;
  106. conf = &PyFCGI_conf.logs;
  107. if(!format)
  108. {
  109. format = PYFCGI_LOGGER_FMT_DEFAULT;
  110. }
  111. for(i=0; i<conf->format_sz; i++)
  112. {
  113. if(!strcmp(format, conf->formats[i].fmt)) { break; }
  114. }
  115. if(idx) { *idx = i; }
  116. if( i<conf->format_sz )
  117. {
  118. return 0;
  119. }
  120. conf->format_sz++;
  121. if( !(ret = pyfcgi_logger_parse_format(format, &(conf->formats[i]))) )
  122. { // No error, allocating format buffer
  123. pyfcgi_logger_format_bufinit(&(conf->formats[i]));
  124. }
  125. return ret;
  126. }
  127. int pyfcgi_logger_parse_format(const char* fmt,
  128. pyfcgi_logger_format_t* fmt_data)
  129. {
  130. const char *ptr, *str_start;
  131. int err;
  132. char reason_err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
  133. pyfcgi_logger_fmt_field_t *cur_field;
  134. memset(fmt_data, 0, sizeof(pyfcgi_logger_format_t));
  135. if( !(fmt_data->fmt = strdup(fmt)) )
  136. {
  137. pyfcgi_log(LOG_ALERT, "Fails to strdup new format : %s",
  138. strerror(errno));
  139. return PYFCGI_FATAL;
  140. }
  141. ptr = fmt;
  142. fmt_data->nfield = 0;
  143. cur_field = fmt_data->fields;
  144. while(*ptr)
  145. {
  146. if(fmt_data->nfield >= PYFCGI_LOGGER_FIELD_MAX)
  147. {
  148. //TODO error truncate !
  149. //break;
  150. goto parse_err;
  151. }
  152. str_start = ptr;
  153. cur_field->len = 0;
  154. while(*ptr && (*ptr != '{' || *(ptr+1) == '{'))
  155. { // handling const chr fields
  156. //TODO : issue warning/error when unescaped '}' found
  157. if(*ptr == '{' && *(ptr+1) == '{')
  158. {
  159. cur_field->len++;
  160. ptr++;
  161. }
  162. cur_field->len++;
  163. ptr++;
  164. }
  165. if(cur_field->len)
  166. {
  167. cur_field->known_length = 1;
  168. cur_field->type = pyfcgi_logger_field_const;
  169. cur_field->val = strndup(str_start, cur_field->len);
  170. if(!cur_field->val)
  171. {
  172. err = errno;
  173. pyfcgi_log(LOG_ALERT,
  174. "Unable to strdup part of format : %s",
  175. strerror(err));
  176. goto exit_err;
  177. }
  178. fmt_data->nfield++;
  179. cur_field = &(fmt_data->fields[fmt_data->nfield]); // next_field
  180. continue; // to check fmt_data->nfield
  181. }
  182. if(*ptr == '{') //should be this or '\0'...
  183. {
  184. ptr++;
  185. if( pyfcgi_logger_parse_field(&ptr, fmt, cur_field,
  186. reason_err) )
  187. {
  188. goto parse_err;
  189. }
  190. fmt_data->nfield++;
  191. cur_field = &(fmt_data->fields[fmt_data->nfield]); // next_field
  192. }
  193. ptr++;
  194. };
  195. return 0;
  196. parse_err:
  197. pyfcgi_log(LOG_ERR, "Logger format parse error at chr %ld : %s",
  198. ptr - fmt, reason_err);
  199. exit_err:
  200. //TODO free const str from fields
  201. memset(fmt_data, 0, sizeof(pyfcgi_logger_format_t));
  202. return PYFCGI_ERR;
  203. }
  204. int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
  205. {
  206. unsigned short i;
  207. size_t pre_sz, suf_sz;
  208. char *cur, pid[PYFCGI_LOG_PID_LEN];
  209. fmt->buf = fmt->prefix = fmt->suffix = NULL;
  210. if(!fmt || !fmt->nfield)
  211. {
  212. return 1;
  213. }
  214. if(fmt->nfield == 1 && fmt->fields[0].type == pyfcgi_logger_field_msg)
  215. {
  216. // no other field than message, buf, prefix & suffix are NULL
  217. return 0;
  218. }
  219. if(fmt->buf)
  220. { // if it is not the first call
  221. free(fmt->buf);
  222. }
  223. if(fmt->_msg)
  224. { // delete message buffer to force prefix copy
  225. free(fmt->_msg);
  226. fmt->_msg = NULL;
  227. }
  228. i = 0;
  229. pre_sz = 0;
  230. while(i<fmt->nfield && fmt->fields[i].type != pyfcgi_logger_field_msg)
  231. {
  232. fmt->fields[i].buf_off = pre_sz;
  233. fmt->fields[i].suff = 0;
  234. pre_sz+=fmt->fields[i].len;
  235. i++;
  236. }
  237. i++;
  238. suf_sz = 0;
  239. while(i<fmt->nfield && fmt->fields[i].type != pyfcgi_logger_field_msg)
  240. {
  241. fmt->fields[i].buf_off = suf_sz;
  242. fmt->fields[i].suff = 1;
  243. suf_sz+=fmt->fields[i].len;
  244. i++;
  245. }
  246. pre_sz += pre_sz?1:0;
  247. suf_sz += suf_sz?1:0;
  248. fmt->buf = malloc(sizeof(char) * (pre_sz + suf_sz));
  249. if(!fmt->buf)
  250. {
  251. fmt->buf = fmt->prefix = fmt->suffix = NULL;
  252. pyfcgi_log(LOG_ALERT, "Unable to allocate logger buffer : %s",
  253. strerror(errno));
  254. return PYFCGI_ERR;
  255. }
  256. memset(fmt->buf, ' ', (pre_sz + suf_sz));
  257. fmt->prefix = pre_sz?fmt->buf:NULL;
  258. fmt->suffix = suf_sz?(fmt->buf + pre_sz):NULL;
  259. fmt->prefix[pre_sz-1] = '\0';
  260. if(fmt->suffix)
  261. {
  262. fmt->suffix[suf_sz-1] = '\0';
  263. }
  264. fmt->buflen[0] = pre_sz - 1;//not counting '\0'
  265. fmt->buflen[1] = suf_sz;
  266. i=0;
  267. cur = fmt->prefix;
  268. while(i<fmt->nfield)
  269. {
  270. while(i<fmt->nfield &&
  271. fmt->fields[i].type != pyfcgi_logger_field_msg)
  272. {
  273. fmt->fields[i].buf_ptr = cur;
  274. memset(cur, ' ', fmt->fields[i].len);
  275. switch(fmt->fields[i].type)
  276. {
  277. case pyfcgi_logger_field_const:
  278. memcpy(cur, fmt->fields[i].val,
  279. fmt->fields[i].len);
  280. break;
  281. case pyfcgi_logger_field_ident:
  282. memcpy(cur, *((char**)fmt->fields[i].val),
  283. fmt->fields[i].len);
  284. break;
  285. case pyfcgi_logger_field_pid:
  286. snprintf(pid, PYFCGI_LOG_PID_LEN+1,
  287. PYFCGI_LOG_PID_FMT,
  288. *((pid_t*)fmt->fields[i].val));
  289. memcpy(cur, pid, PYFCGI_LOG_PID_LEN);
  290. break;
  291. default:
  292. break;
  293. }
  294. //dprintf(2, "field %d type %d off %ld len %ld '%s' p'%s' s'%s'\n", i, fmt->fields[i].type, fmt->fields[i].buf_off, fmt->fields[i].len, cur, fmt->prefix, fmt->suffix);
  295. cur += fmt->fields[i].len;
  296. i++;
  297. }
  298. if(fmt->fields[i].type == pyfcgi_logger_field_msg)
  299. {
  300. cur = fmt->suffix;
  301. i++;
  302. }
  303. }
  304. return 0;
  305. }
  306. int pyfcgi_logger_parse_field(const char** ptr, const char *start,
  307. pyfcgi_logger_fmt_field_t* cur_field,
  308. char fail_reason[PYFCGI_LOGGER_FMT_PARSE_ERRSZ])
  309. {
  310. const char *str_start, *field_start;
  311. int ret;
  312. char **name, *cname, **format;
  313. size_t default_len;
  314. pyfcgi_logger_field_type_e *type;
  315. char *field_names[] = {"datetime", "level", "facility", "pid", "ident",
  316. "msg", NULL};
  317. pyfcgi_logger_field_type_e field_types[] = {
  318. pyfcgi_logger_field_datetime, pyfcgi_logger_field_level,
  319. pyfcgi_logger_field_facility, pyfcgi_logger_field_pid,
  320. pyfcgi_logger_field_ident, pyfcgi_logger_field_msg};
  321. str_start = *ptr;
  322. field_start = *ptr;
  323. name = field_names;
  324. type = field_types;
  325. while(*name)
  326. {
  327. cname = *name;
  328. if(*cname != **ptr)
  329. {
  330. name++;
  331. type++;
  332. continue;
  333. }
  334. // Name found ?
  335. while(**ptr && *cname && **ptr != ':' && **ptr != '}' &&
  336. **ptr == *cname)
  337. {
  338. (*ptr)++;
  339. cname++;
  340. }
  341. if(**ptr == ':' || **ptr == '}')
  342. {
  343. cur_field->type = *type;
  344. break;
  345. }
  346. else
  347. {
  348. *name = field_names[6]; // NULL
  349. break;
  350. }
  351. }
  352. if(!name)
  353. {
  354. snprintf(fail_reason, PYFCGI_LOGGER_FMT_PARSE_ERRSZ,
  355. "unknown field type '%s' chr %ld",
  356. str_start, str_start - start);
  357. return 1;
  358. }
  359. if(**ptr == ':') { (*ptr)++; } // next option
  360. if(pyfcgi_logger_parse_field_sz(ptr, &(cur_field->len)))
  361. {
  362. snprintf(fail_reason, PYFCGI_LOGGER_FMT_PARSE_ERRSZ,
  363. "Unable to parse field size chr %ld '%s'",
  364. str_start - start, str_start);
  365. return 1;
  366. }
  367. if(**ptr == ':') { (*ptr)++; } // next option
  368. str_start = *ptr;
  369. cur_field->known_length = 1;
  370. switch(cur_field->type)
  371. {
  372. case pyfcgi_logger_field_datetime:
  373. default_len = PYFCGI_LOG_DTM_LEN;
  374. cur_field->val = (void*)strftime;
  375. format = &(cur_field->args.datetime.format);
  376. ret = pyfcgi_logger_parse_field_dtfmt(ptr,format);
  377. if(ret){
  378. return ret;
  379. }
  380. break;
  381. case pyfcgi_logger_field_level:
  382. default_len = PYFCGI_LOG_LVL_LEN;
  383. cur_field->val = (void*)pyfcgi_logger_value_level;
  384. break;
  385. case pyfcgi_logger_field_facility:
  386. default_len = PYFCGI_LOG_TYP_LEN;
  387. cur_field->val = (void*)pyfcgi_logger_value_facility;
  388. break;
  389. case pyfcgi_logger_field_pid:
  390. default_len = PYFCGI_LOG_PID_LEN;
  391. cur_field->val = &(PyFCGI_conf.context.pid);
  392. break;
  393. case pyfcgi_logger_field_ident:
  394. default_len = PyFCGI_conf.logs.ident?strlen(PyFCGI_conf.logs.ident):0;
  395. cur_field->val = &(PyFCGI_conf.logs.ident);
  396. break;
  397. case pyfcgi_logger_field_msg:
  398. cur_field->known_length = 0;
  399. default_len = 0;
  400. break;
  401. default:
  402. snprintf(fail_reason, PYFCGI_LOGGER_FMT_PARSE_ERRSZ,
  403. "Unknown error parsing field '%s' at chr %ld",
  404. field_start , *ptr - start);
  405. return 1;
  406. }
  407. if(!cur_field->len && default_len)
  408. {
  409. cur_field->len = default_len;
  410. }
  411. return 0;
  412. }
  413. void pyfcgi_logger_field_free(pyfcgi_logger_fmt_field_t* field)
  414. {
  415. switch(field->type)
  416. {
  417. case pyfcgi_logger_field_const:
  418. if(field->val)
  419. {
  420. free(field->val);
  421. }
  422. break;
  423. case pyfcgi_logger_field_datetime:
  424. if(field->args.datetime.format)
  425. {
  426. free(field->args.datetime.format);
  427. }
  428. break;
  429. case pyfcgi_logger_field_null:
  430. case pyfcgi_logger_field_level:
  431. case pyfcgi_logger_field_facility:
  432. case pyfcgi_logger_field_pid:
  433. case pyfcgi_logger_field_ppid:
  434. case pyfcgi_logger_field_ident:
  435. case pyfcgi_logger_field_msg:
  436. break;
  437. }
  438. }
  439. int pyfcgi_logger_parse_field_dtfmt(const char** ptr, char** format)
  440. {
  441. const char *fmt;
  442. size_t fmt_len;
  443. fmt_len = 0;
  444. fmt = *ptr;
  445. while(**ptr && **ptr != '}' && *((*ptr)+1) != '}')
  446. {
  447. (*ptr)++;
  448. fmt_len++;
  449. }
  450. if(!(**ptr))
  451. {
  452. //TODO error
  453. }
  454. if(!fmt_len)
  455. {
  456. fmt_len = sizeof(PYFCGI_LOGGER_TIME_FMT_DEFAULT);
  457. fmt = PYFCGI_LOGGER_TIME_FMT_DEFAULT;
  458. }
  459. if(!(*format = strndup(fmt, fmt_len+1)))
  460. {
  461. pyfcgi_log(LOG_ALERT,
  462. "Unable to strdup field datetime format : %s",
  463. strerror(errno));
  464. return PYFCGI_FATAL;
  465. }
  466. return 0;
  467. }
  468. int pyfcgi_logger_parse_field_sz(const char **ptr, size_t *size)
  469. {
  470. char *end;
  471. *size = 0;
  472. if(**ptr == '}' || **ptr == ':')
  473. {
  474. return 0;
  475. }
  476. if(**ptr < '0' || **ptr > '9')
  477. {
  478. return 1; // parse error
  479. }
  480. *size = strtoull(*ptr, &end, 10);
  481. *ptr = end;
  482. return 0;
  483. }
  484. const char* pyfcgi_logger_value_level(short lvl)
  485. {
  486. short idx;
  487. idx = ((lvl & 0xF0) >> 4)-1;
  488. if(idx < 0 || idx > 7)
  489. {
  490. return NULL;
  491. }
  492. return PYFCGI_LOGGER_LVLNAME[idx];
  493. }
  494. const char* pyfcgi_logger_value_facility(short typ)
  495. {
  496. short idx;
  497. idx = typ & 0x0F;
  498. if(idx < 0 || idx >= sizeof(PYFCGI_LOGGER_TYPNAME))
  499. {
  500. return NULL;
  501. }
  502. return PYFCGI_LOGGER_TYPNAME[idx];
  503. }
  504. int pyfcgi_logger_open(pyfcgi_logger_t *logger)
  505. {
  506. if( ((logger->fd = open(logger->filename,
  507. O_WRONLY | O_APPEND | O_CREAT, 00640)) < 0) )
  508. {
  509. pyfcgi_log(LOG_ERR,
  510. "Unable to open log file '%s' : %s",
  511. strerror(errno));
  512. return PYFCGI_ERR;
  513. }
  514. return 0;
  515. }
  516. int pyfcgi_logger_set_ident(const char* new_ident)
  517. {
  518. pyfcgi_conf_logger_t *conf;
  519. pyfcgi_logger_format_t *fmt;
  520. pyfcgi_logger_fmt_field_t *field;
  521. size_t i, j, len;
  522. short upd;
  523. conf = &PyFCGI_conf.logs;
  524. if( !(conf->ident = strdup(new_ident)) )
  525. {
  526. pyfcgi_log(LOG_ALERT,
  527. "Error duplicating identity for logger : %s",
  528. strerror(errno));
  529. return PYFCGI_FATAL;
  530. }
  531. if(conf->flags & PYFCGI_LOG_FSYSLOG)
  532. {
  533. pyfcgi_logger_enable_syslog(new_ident);
  534. }
  535. len = strlen(conf->ident);
  536. for(i=0; i<conf->format_sz; i++)
  537. {
  538. fmt = &(conf->formats[i]);
  539. upd = 0;
  540. for(j=0; j<fmt->nfield; j++)
  541. {
  542. field = &(fmt->fields[j]);
  543. if(field->type == pyfcgi_logger_field_ident)
  544. {
  545. field->len = len;
  546. upd = 1;
  547. }
  548. }
  549. if(upd)
  550. {
  551. pyfcgi_logger_format_bufinit(fmt);
  552. }
  553. }
  554. return 0;
  555. }
  556. char* vpyfcgi_logger_format_message(pyfcgi_logger_format_t *fmt,
  557. loglvl_t lvl, const char* message, size_t fmt_msg_len)
  558. {
  559. /**@todo Add '\n' when suffix is used ! */
  560. char *_msgptr;
  561. size_t maxlen;
  562. int ret;
  563. void *tmp;
  564. size_t i, suff_off;
  565. pyfcgi_logger_fmt_field_t *field;
  566. struct tm *curtime;
  567. time_t _curtime;
  568. size_t (*_strftime)(char*, size_t, const char*, const struct tm*);
  569. if(!fmt->_msg)
  570. { //first message, allocating message buffer
  571. fmt->_msglen = fmt->buflen[0] + fmt->buflen[1] + fmt_msg_len + 1;
  572. // rounding upper
  573. fmt->_msglen >>= 6;
  574. fmt->_msglen++;
  575. fmt->_msglen <<= 6;
  576. fmt->_msg = malloc(sizeof(char) * fmt->_msglen);
  577. if(!fmt->_msg)
  578. {
  579. //TODO : error
  580. dprintf(2, "ERROR ALLOC _msg : %s\n", strerror(errno));
  581. return NULL;
  582. }
  583. memset(fmt->_msg, ' ', sizeof(char)*fmt->_msglen);
  584. fmt->_msg[fmt->_msglen - 1] = '\0';
  585. memcpy(fmt->_msg, fmt->prefix, fmt->buflen[0]);
  586. }
  587. while(1)
  588. {
  589. maxlen = fmt->_msglen - (fmt->buflen[0] + fmt->buflen[1]);
  590. if(fmt_msg_len < maxlen)
  591. {
  592. // TODO check errors
  593. break;
  594. }
  595. fmt->_msglen = fmt_msg_len + fmt->buflen[0] + fmt->buflen[1] + 1;
  596. fmt->_msglen >>= 6;
  597. fmt->_msglen++;
  598. fmt->_msglen <<= 6;
  599. tmp = realloc(fmt->_msg, sizeof(char) * fmt->_msglen);
  600. if(!tmp)
  601. {
  602. //TODO : error
  603. dprintf(2, "ERROR REALLOC _msg : %s", strerror(errno));
  604. return NULL;
  605. }
  606. fmt->_msg = tmp;
  607. }
  608. memcpy(fmt->_msg + fmt->buflen[0], message, fmt_msg_len);
  609. suff_off = fmt->buflen[0] + fmt_msg_len;
  610. if(fmt->buflen[1])
  611. {
  612. strncpy(fmt->_msg + suff_off, fmt->suffix,
  613. fmt->buflen[1]);
  614. //TODO check errors
  615. fmt->_msg[suff_off+fmt->buflen[1]] = '\n';
  616. fmt->_msg[suff_off+fmt->buflen[1]+1] = '\0';
  617. }
  618. else
  619. {
  620. fmt->_msg[suff_off] = '\n';
  621. fmt->_msg[suff_off+1] = '\0';
  622. }
  623. // update fmt->_msg dynamic fields
  624. time(&_curtime);
  625. curtime = localtime(&_curtime);
  626. for(i=0; i<fmt->nfield; i++)
  627. {
  628. field = &(fmt->fields[i]);
  629. _msgptr = fmt->_msg;
  630. _msgptr += fmt->fields->suff?suff_off:0;
  631. _msgptr += field->buf_off;
  632. switch(field->type)
  633. {
  634. case pyfcgi_logger_field_datetime:
  635. _strftime = field->val?field->val:strftime;
  636. ret = _strftime(_msgptr, field->len,
  637. field->args.datetime.format,
  638. curtime);
  639. if(!ret)
  640. {
  641. //TODO ERROR
  642. dprintf(2,"Not enough space to write datetime in '%s', need more than %ld\n",
  643. fmt->fmt, field->len);
  644. }
  645. _msgptr[ret] = ' ';
  646. break;
  647. case pyfcgi_logger_field_level:
  648. memcpy(_msgptr,
  649. pyfcgi_logger_value_level(lvl),
  650. field->len);
  651. break;
  652. default:
  653. break;
  654. }
  655. }
  656. return fmt->_msg;
  657. }
  658. int pyfcgi_log(loglvl_t lvl, const char *fmt, ...)
  659. {
  660. int ret;
  661. va_list ap;
  662. va_start(ap, fmt);
  663. ret = vpyfcgi_log(lvl, fmt, ap);
  664. va_end(ap);
  665. return ret;
  666. }
  667. int vpyfcgi_log(loglvl_t lvl, const char *fmt, va_list ap)
  668. {
  669. int len, ret;
  670. pyfcgi_conf_logger_t *conf;
  671. pyfcgi_logger_t *logger;
  672. unsigned char i;
  673. size_t msglen, real_len;
  674. void *tmp;
  675. va_list o_ap;
  676. conf = &PyFCGI_conf.logs;
  677. va_copy(o_ap, ap);
  678. _vsyslog(lvl, fmt, o_ap);
  679. va_end(o_ap);
  680. ret = 0;
  681. // processing message before sending it to formats
  682. while(1)
  683. {
  684. va_copy(o_ap, ap);
  685. msglen = vsnprintf(conf->msg_buf, conf->msg_buf_sz, fmt, o_ap);
  686. real_len = msglen;
  687. va_end(o_ap);
  688. // Rounding msglen
  689. msglen >>=6;
  690. msglen++;
  691. msglen <<=6;
  692. if(msglen <= conf->msg_buf_sz)
  693. {
  694. break;
  695. }
  696. conf->msg_buf_sz = msglen;
  697. tmp = realloc(conf->msg_buf,
  698. sizeof(char)*conf->msg_buf_sz);
  699. if(!tmp)
  700. {
  701. // TODO : error
  702. dprintf(2, "ERROR REALLOC conf_msg : %s", strerror(errno));
  703. if(conf->msg_buf) { free(conf->msg_buf); }
  704. return PYFCGI_FATAL;
  705. }
  706. conf->msg_buf = tmp;
  707. }
  708. // populating format messages
  709. for(i=0; i<conf->format_sz; i++)
  710. {
  711. vpyfcgi_logger_format_message(&(conf->formats[i]), lvl,
  712. conf->msg_buf, real_len);
  713. }
  714. for(i=0; i<conf->logger_sz; i++)
  715. {
  716. logger = &(conf->loggers[i]);
  717. len = dprintf(logger->fd, conf->formats[logger->fmt_id]._msg);
  718. if(len < 0)
  719. {
  720. _syslog(LOG_ALERT,
  721. "Unable to write to single FD to '%s' when trying to log : %s",
  722. conf->loggers[i].filename, strerror(errno));
  723. ret = PYFCGI_FATAL;
  724. }
  725. }
  726. return ret;
  727. }