|
@@ -196,7 +196,7 @@ int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
|
196
|
196
|
{
|
197
|
197
|
unsigned short i;
|
198
|
198
|
size_t pre_sz, suf_sz;
|
199
|
|
- char *cur;
|
|
199
|
+ char *cur, pid[PYFCGI_LOG_PID_LEN];
|
200
|
200
|
fmt->buf = fmt->prefix = fmt->suffix = NULL;
|
201
|
201
|
if(!fmt || !fmt->nfield)
|
202
|
202
|
{
|
|
@@ -216,6 +216,8 @@ int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
|
216
|
216
|
pre_sz = 0;
|
217
|
217
|
while(i<fmt->nfield && fmt->fields[i].type != pyfcgi_logger_field_msg)
|
218
|
218
|
{
|
|
219
|
+ fmt->fields[i].buf_off = pre_sz;
|
|
220
|
+ fmt->fields[i].suff = 0;
|
219
|
221
|
pre_sz+=fmt->fields[i].len;
|
220
|
222
|
i++;
|
221
|
223
|
}
|
|
@@ -223,6 +225,8 @@ int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
|
223
|
225
|
suf_sz = 0;
|
224
|
226
|
while(i<fmt->nfield && fmt->fields[i].type != pyfcgi_logger_field_msg)
|
225
|
227
|
{
|
|
228
|
+ fmt->fields[i].buf_off = suf_sz;
|
|
229
|
+ fmt->fields[i].suff = 1;
|
226
|
230
|
suf_sz+=fmt->fields[i].len;
|
227
|
231
|
i++;
|
228
|
232
|
}
|
|
@@ -236,8 +240,16 @@ int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
|
236
|
240
|
strerror(errno));
|
237
|
241
|
return PYFCGI_ERR;
|
238
|
242
|
}
|
|
243
|
+ memset(fmt->buf, ' ', (pre_sz + suf_sz));
|
239
|
244
|
fmt->prefix = pre_sz?fmt->buf:NULL;
|
240
|
245
|
fmt->suffix = suf_sz?(fmt->buf + pre_sz):NULL;
|
|
246
|
+ fmt->prefix[pre_sz-1] = '\0';
|
|
247
|
+ if(fmt->suffix)
|
|
248
|
+ {
|
|
249
|
+ fmt->suffix[suf_sz-1] = '\0';
|
|
250
|
+ }
|
|
251
|
+ fmt->buflen[0] = pre_sz - 1;//not counting '\0'
|
|
252
|
+ fmt->buflen[1] = suf_sz;
|
241
|
253
|
|
242
|
254
|
i=0;
|
243
|
255
|
cur = fmt->prefix;
|
|
@@ -247,13 +259,25 @@ int pyfcgi_logger_format_bufinit(pyfcgi_logger_format_t* fmt)
|
247
|
259
|
fmt->fields[i].type != pyfcgi_logger_field_msg)
|
248
|
260
|
{
|
249
|
261
|
fmt->fields[i].buf_ptr = cur;
|
250
|
|
- if(fmt->fields[i].len && (
|
251
|
|
- fmt->fields[i].type == pyfcgi_logger_field_const ||
|
252
|
|
- fmt->fields[i].type == pyfcgi_logger_field_ident))
|
253
|
|
- {// copy const fields
|
254
|
|
- strncpy(cur, fmt->fields[i].val,
|
255
|
|
- fmt->fields[i].len);
|
|
262
|
+ memset(cur, ' ', fmt->fields[i].len);
|
|
263
|
+ switch(fmt->fields[i].type)
|
|
264
|
+ {
|
|
265
|
+
|
|
266
|
+ case pyfcgi_logger_field_const:
|
|
267
|
+ case pyfcgi_logger_field_ident:
|
|
268
|
+ memcpy(cur, fmt->fields[i].val,
|
|
269
|
+ fmt->fields[i].len);
|
|
270
|
+ break;
|
|
271
|
+ case pyfcgi_logger_field_pid:
|
|
272
|
+ snprintf(pid, PYFCGI_LOG_PID_LEN+1,
|
|
273
|
+ PYFCGI_LOG_PID_FMT,
|
|
274
|
+ *((pid_t*)fmt->fields[i].val));
|
|
275
|
+ memcpy(cur, pid, PYFCGI_LOG_PID_LEN);
|
|
276
|
+ break;
|
|
277
|
+ default:
|
|
278
|
+ break;
|
256
|
279
|
}
|
|
280
|
+//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);
|
257
|
281
|
cur += fmt->fields[i].len;
|
258
|
282
|
i++;
|
259
|
283
|
}
|
|
@@ -356,7 +380,7 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
|
356
|
380
|
cur_field->val = &(PyFCGI_conf.context.pid);
|
357
|
381
|
break;
|
358
|
382
|
case pyfcgi_logger_field_ident:
|
359
|
|
- default_len = 0;
|
|
383
|
+ default_len = PyFCGI_conf.logs.ident?strlen(PyFCGI_conf.logs.ident):0;
|
360
|
384
|
cur_field->val = &(PyFCGI_conf.logs.ident);
|
361
|
385
|
break;
|
362
|
386
|
case pyfcgi_logger_field_msg:
|
|
@@ -456,8 +480,8 @@ int pyfcgi_logger_parse_field_sz(const char **ptr, size_t *size)
|
456
|
480
|
const char* pyfcgi_logger_value_level(short lvl)
|
457
|
481
|
{
|
458
|
482
|
short idx;
|
459
|
|
- idx = (lvl & 0xF0) >> 4;
|
460
|
|
- if(idx < 0 || idx >= sizeof(PYFCGI_LOGGER_LVLNAME))
|
|
483
|
+ idx = ((lvl & 0xF0) >> 4)-1;
|
|
484
|
+ if(idx < 0 || idx > 7)
|
461
|
485
|
{
|
462
|
486
|
return NULL;
|
463
|
487
|
}
|
|
@@ -489,6 +513,144 @@ int pyfcgi_logger_open(pyfcgi_logger_t *logger)
|
489
|
513
|
return 0;
|
490
|
514
|
}
|
491
|
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
|
+
|
|
524
|
+ conf = &PyFCGI_conf.logs;
|
|
525
|
+ if( !(conf->ident = strdup(new_ident)) )
|
|
526
|
+ {
|
|
527
|
+ pyfcgi_log(LOG_ALERT,
|
|
528
|
+ "Error duplicating identity for logger : %s",
|
|
529
|
+ strerror(errno));
|
|
530
|
+ return PYFCGI_FATAL;
|
|
531
|
+ }
|
|
532
|
+ len = strlen(new_ident);
|
|
533
|
+ for(i=0; i<conf->format_sz; i++)
|
|
534
|
+ {
|
|
535
|
+ fmt = &(conf->formats[i]);
|
|
536
|
+ upd = 0;
|
|
537
|
+ for(j=0; j<fmt->nfield; j++)
|
|
538
|
+ {
|
|
539
|
+ field = &(fmt->fields[j]);
|
|
540
|
+ if(field->type == pyfcgi_logger_field_ident)
|
|
541
|
+ {
|
|
542
|
+ field->len = len;
|
|
543
|
+ upd = 0;
|
|
544
|
+ }
|
|
545
|
+ }
|
|
546
|
+ if(upd)
|
|
547
|
+ {
|
|
548
|
+ pyfcgi_logger_format_bufinit(fmt);
|
|
549
|
+ }
|
|
550
|
+ }
|
|
551
|
+ return 0;
|
|
552
|
+}
|
|
553
|
+
|
|
554
|
+char* vpyfcgi_logger_format_message(pyfcgi_logger_format_t *fmt,
|
|
555
|
+ loglvl_t lvl, const char* message, size_t fmt_msg_len)
|
|
556
|
+{
|
|
557
|
+ char *_msgptr;
|
|
558
|
+ size_t maxlen;
|
|
559
|
+ int ret;
|
|
560
|
+ void *tmp;
|
|
561
|
+ size_t i, suff_off;
|
|
562
|
+ pyfcgi_logger_fmt_field_t *field;
|
|
563
|
+ struct tm *curtime;
|
|
564
|
+ time_t _curtime;
|
|
565
|
+ size_t (*_strftime)(char*, size_t, const char*, const struct tm*);
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+ if(!fmt->_msg)
|
|
569
|
+ { //first message, allocating message buffer
|
|
570
|
+ fmt->_msglen = fmt->buflen[0] + fmt->buflen[1] + fmt_msg_len;
|
|
571
|
+ // rounding upper
|
|
572
|
+ fmt->_msglen >>= 6;
|
|
573
|
+ fmt->_msglen++;
|
|
574
|
+ fmt->_msglen <<= 6;
|
|
575
|
+ fmt->_msg = malloc(sizeof(char) * fmt->_msglen);
|
|
576
|
+ if(!fmt->_msg)
|
|
577
|
+ {
|
|
578
|
+ //TODO : error
|
|
579
|
+dprintf(2, "ERROR ALLOC _msg : %s", strerror(errno));
|
|
580
|
+ return NULL;
|
|
581
|
+ }
|
|
582
|
+ memset(fmt->_msg, ' ', sizeof(char)*fmt->_msglen);
|
|
583
|
+ fmt->_msg[fmt->_msglen - 1] = '\0';
|
|
584
|
+ memcpy(fmt->_msg, fmt->prefix, fmt->buflen[0]);
|
|
585
|
+ }
|
|
586
|
+ while(1)
|
|
587
|
+ {
|
|
588
|
+ maxlen = fmt->_msglen - (fmt->buflen[0] + fmt->buflen[1]);
|
|
589
|
+ if(fmt_msg_len < maxlen)
|
|
590
|
+ {
|
|
591
|
+ // TODO check errors
|
|
592
|
+ break;
|
|
593
|
+ }
|
|
594
|
+ fmt->_msglen = fmt_msg_len + fmt->buflen[0] + fmt->buflen[1];
|
|
595
|
+ fmt->_msglen >>= 6;
|
|
596
|
+ fmt->_msglen++;
|
|
597
|
+ fmt->_msglen <<= 6;
|
|
598
|
+ tmp = realloc(fmt->_msg, sizeof(char) * fmt->_msglen);
|
|
599
|
+ if(!tmp)
|
|
600
|
+ {
|
|
601
|
+ //TODO : error
|
|
602
|
+dprintf(2, "ERROR REALLOC _msg : %s", strerror(errno));
|
|
603
|
+ return NULL;
|
|
604
|
+ }
|
|
605
|
+ }
|
|
606
|
+ memcpy(fmt->_msg + fmt->buflen[0], message, fmt_msg_len);
|
|
607
|
+ suff_off = fmt->buflen[0] + fmt_msg_len;
|
|
608
|
+ if(fmt->buflen[1])
|
|
609
|
+ {
|
|
610
|
+ strncpy(fmt->_msg + suff_off, fmt->suffix,
|
|
611
|
+ fmt->buflen[1]);
|
|
612
|
+ //TODO check errors
|
|
613
|
+ }
|
|
614
|
+ else
|
|
615
|
+ {
|
|
616
|
+ fmt->_msg[suff_off] = '\0';
|
|
617
|
+ }
|
|
618
|
+ // update fmt->_msg dynamic fields
|
|
619
|
+ time(&_curtime);
|
|
620
|
+ curtime = localtime(&_curtime);
|
|
621
|
+ for(i=0; i<fmt->nfield; i++)
|
|
622
|
+ {
|
|
623
|
+ field = &(fmt->fields[i]);
|
|
624
|
+ _msgptr = fmt->_msg;
|
|
625
|
+ _msgptr += fmt->fields->suff?suff_off:0;
|
|
626
|
+ _msgptr += field->buf_off;
|
|
627
|
+ switch(field->type)
|
|
628
|
+ {
|
|
629
|
+ case pyfcgi_logger_field_datetime:
|
|
630
|
+ _strftime = field->val?field->val:strftime;
|
|
631
|
+ ret = _strftime(_msgptr, field->len,
|
|
632
|
+ field->args.datetime.format,
|
|
633
|
+ curtime);
|
|
634
|
+ if(!ret)
|
|
635
|
+ {
|
|
636
|
+ //TODO ERROR
|
|
637
|
+dprintf(2,"Not enough space to write datetime in '%s', need more than %ld\n",
|
|
638
|
+ fmt->fmt, field->len);
|
|
639
|
+ }
|
|
640
|
+ _msgptr[ret] = ' ';
|
|
641
|
+ break;
|
|
642
|
+ case pyfcgi_logger_field_level:
|
|
643
|
+ memcpy(_msgptr,
|
|
644
|
+ pyfcgi_logger_value_level(lvl),
|
|
645
|
+ field->len);
|
|
646
|
+ break;
|
|
647
|
+ default:
|
|
648
|
+ break;
|
|
649
|
+ }
|
|
650
|
+ }
|
|
651
|
+ return fmt->_msg;
|
|
652
|
+}
|
|
653
|
+
|
492
|
654
|
int pyfcgi_log(loglvl_t lvl, const char *fmt, ...)
|
493
|
655
|
{
|
494
|
656
|
int ret;
|
|
@@ -503,76 +665,65 @@ int vpyfcgi_log(loglvl_t lvl, const char *fmt, va_list ap)
|
503
|
665
|
{
|
504
|
666
|
int len, ret;
|
505
|
667
|
pyfcgi_conf_logger_t *conf;
|
|
668
|
+ pyfcgi_logger_t *logger;
|
506
|
669
|
unsigned char i;
|
507
|
|
- char buf[512];
|
|
670
|
+ size_t msglen, real_len;
|
|
671
|
+ void *tmp;
|
508
|
672
|
va_list o_ap;
|
509
|
673
|
|
|
674
|
+
|
510
|
675
|
conf = &PyFCGI_conf.logs;
|
511
|
676
|
|
512
|
677
|
va_copy(o_ap, ap);
|
513
|
678
|
_vsyslog(lvl, fmt, o_ap);
|
514
|
679
|
va_end(o_ap);
|
515
|
680
|
|
516
|
|
- len = 0;
|
517
|
|
- if(conf->format_sz > 1)
|
518
|
|
- {
|
519
|
|
- len = vdprintf(conf->pipes[1], fmt, ap);
|
520
|
|
- if(len < 0)
|
|
681
|
+ ret = 0;
|
|
682
|
+ // processing message before sending it to formats
|
|
683
|
+ while(1)
|
|
684
|
+ {
|
|
685
|
+ va_copy(o_ap, ap);
|
|
686
|
+ msglen = vsnprintf(conf->msg_buf, conf->msg_buf_sz, fmt, o_ap);
|
|
687
|
+ real_len = msglen;
|
|
688
|
+ va_end(o_ap);
|
|
689
|
+ // Rounding msglen
|
|
690
|
+ msglen >>=6;
|
|
691
|
+ msglen++;
|
|
692
|
+ msglen <<=6;
|
|
693
|
+ if(msglen <= conf->msg_buf_sz)
|
521
|
694
|
{
|
522
|
|
- _syslog(LOG_ALERT,
|
523
|
|
- "Unable to write to multiplexer pipe when trying to log : %s",
|
524
|
|
- strerror(errno));
|
525
|
|
- return PYFCGI_FATAL;
|
|
695
|
+ break;
|
526
|
696
|
}
|
527
|
|
- }
|
528
|
|
- else if (conf->format_sz)
|
529
|
|
- {
|
530
|
|
- len = vdprintf(conf->loggers[0].fd, fmt, ap);
|
531
|
|
- if(len < 0)
|
|
697
|
+ conf->msg_buf_sz = msglen;
|
|
698
|
+ tmp = realloc(conf->msg_buf,
|
|
699
|
+ sizeof(char)*conf->msg_buf_sz);
|
|
700
|
+ if(!tmp)
|
532
|
701
|
{
|
533
|
|
- _syslog(LOG_ALERT,
|
534
|
|
- "Unable to write to single FD to '%s' when trying to log : %s",
|
535
|
|
- conf->loggers[0].filename, strerror(errno));
|
|
702
|
+ // TODO : error
|
|
703
|
+dprintf(2, "ERROR REALLOC conf_msg : %s", strerror(errno));
|
|
704
|
+ if(conf->msg_buf) { free(conf->msg_buf); }
|
536
|
705
|
return PYFCGI_FATAL;
|
537
|
706
|
}
|
538
|
|
- return 0;
|
|
707
|
+ conf->msg_buf = tmp;
|
|
708
|
+ }
|
|
709
|
+
|
|
710
|
+ // populating format messages
|
|
711
|
+ for(i=0; i<conf->format_sz; i++)
|
|
712
|
+ {
|
|
713
|
+ vpyfcgi_logger_format_message(&(conf->formats[i]), lvl,
|
|
714
|
+ conf->msg_buf, real_len);
|
539
|
715
|
}
|
540
|
|
- for(i=0; i<conf->logger_sz-1; i++)
|
|
716
|
+ for(i=0; i<conf->logger_sz; i++)
|
541
|
717
|
{
|
542
|
|
- ret = tee(conf->pipes[0], conf->loggers[i].fd, len, 0);
|
543
|
|
- if(ret < 0)
|
|
718
|
+ logger = &(conf->loggers[i]);
|
|
719
|
+ len = dprintf(logger->fd, conf->formats[logger->fmt_id]._msg);
|
|
720
|
+ if(len < 0)
|
544
|
721
|
{
|
545
|
722
|
_syslog(LOG_ALERT,
|
546
|
|
- "Unable to splice to last logfile '%s' : %s",
|
|
723
|
+ "Unable to write to single FD to '%s' when trying to log : %s",
|
547
|
724
|
conf->loggers[i].filename, strerror(errno));
|
548
|
|
- return PYFCGI_FATAL;
|
|
725
|
+ ret = PYFCGI_FATAL;
|
549
|
726
|
}
|
550
|
727
|
}
|
551
|
|
- ret = splice(conf->pipes[0], NULL, conf->loggers[i].fd, NULL, len, 0);
|
552
|
|
- if(ret < 0)
|
553
|
|
- {
|
554
|
|
- _syslog(LOG_ALERT,
|
555
|
|
- "Unable to splice to last logfile '%s' : %s",
|
556
|
|
- conf->loggers[i].filename, strerror(errno));
|
557
|
|
- return PYFCGI_ERR;
|
558
|
|
- }
|
559
|
|
- if(ret < len)
|
560
|
|
- {
|
561
|
|
- _syslog(LOG_WARNING,
|
562
|
|
- "Unable to splice all data to logfile. Flushing pipe.");
|
563
|
|
-
|
564
|
|
- do
|
565
|
|
- {
|
566
|
|
- len -= (ret<len)?ret:len;
|
567
|
|
- ret = read(conf->pipes[0], buf, (len>sizeof(buf))?sizeof(buf):len);
|
568
|
|
- if(ret < 0)
|
569
|
|
- {
|
570
|
|
- _syslog(LOG_CRIT,
|
571
|
|
- "Logger pipe seems broken, unable to flush : %s",
|
572
|
|
- strerror(errno));
|
573
|
|
- return PYFCGI_ERR;
|
574
|
|
- }
|
575
|
|
- }while(len);
|
576
|
|
- }
|
577
|
|
- return 0;
|
|
728
|
+ return ret;
|
578
|
729
|
}
|