1
/**********************************************************************
2
* vanessa_logger.c September 2000
3
* Horms horms@vergenet.net
6
* Generic logging layer
7
* Copyright (C) 2000 Horms
9
* This library is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU Lesser General Public License
11
* as published by the Free Software Foundation; either version 2 of
12
* the License, or (at your option) any later version.
14
* This library is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with this library; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24
**********************************************************************/
36
/**********************************************************************
37
* Sun Solaris doesn't seem to define facilitynames so the
38
* following compatibility code is provided.
39
**********************************************************************/
43
#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
44
#define LOG_FTP (11<<3) /* ftp daemon */
46
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
48
#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
50
#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0)
51
typedef struct _code {
56
CODE facilitynames[] =
59
{ "authpriv", LOG_AUTHPRIV },
61
{ "daemon", LOG_DAEMON },
66
{ "mark", INTERNAL_MARK }, /* INTERNAL */
68
{ "security", LOG_AUTH }, /* DEPRECATED */
69
{ "syslog", LOG_SYSLOG },
72
{ "local0", LOG_LOCAL0 },
73
{ "local1", LOG_LOCAL1 },
74
{ "local2", LOG_LOCAL2 },
75
{ "local3", LOG_LOCAL3 },
76
{ "local4", LOG_LOCAL4 },
77
{ "local5", LOG_LOCAL5 },
78
{ "local6", LOG_LOCAL6 },
79
{ "local7", LOG_LOCAL7 },
86
#include "vanessa_logger.h"
89
/**********************************************************************
90
* Internal data structures
91
**********************************************************************/
96
} __vanessa_logger_filename_data_t;
101
__vanessa_logger_filename_data_t *d_filename;
103
} __vanessa_logger_data_t;
106
__vanessa_logger_filehandle,
107
__vanessa_logger_filename,
108
__vanessa_logger_syslog,
109
__vanessa_logger_none
110
} __vanessa_logger_type_t;
113
__vanessa_logger_true,
114
__vanessa_logger_false
115
} __vanessa_logger_bool_t;
118
__vanessa_logger_type_t type;
119
__vanessa_logger_data_t data;
120
__vanessa_logger_bool_t ready;
125
} __vanessa_logger_t;
128
/**********************************************************************
130
**********************************************************************/
132
#define __VANESSA_LOGGER_BUF_SIZE (size_t)1024
134
#define __VANESSA_LOGGER_SAFE_FREE(ptr) \
141
/**********************************************************************
142
* Prototype of internal functions
143
**********************************************************************/
145
static __vanessa_logger_t *__vanessa_logger_create(void);
146
static void __vanessa_logger_destroy(__vanessa_logger_t *vl);
147
static void __vanessa_logger_reset(__vanessa_logger_t *vl);
148
static __vanessa_logger_t *__vanessa_logger_set(
149
__vanessa_logger_t *vl,
151
const int max_priority,
152
const __vanessa_logger_type_t type,
156
static void __vanessa_logger_log(
157
__vanessa_logger_t *vl,
162
static int __vanessa_logger_reopen(__vanessa_logger_t *vl);
165
/**********************************************************************
166
* __vanessa_logger_create
167
* Internal function to create a new logger
169
* post: Memory for logger is allocated and values are initialised
172
* return: pointer to new logger
173
**********************************************************************/
175
static __vanessa_logger_t *__vanessa_logger_create(void){
176
__vanessa_logger_t *vl;
178
if((vl=(__vanessa_logger_t *)malloc(sizeof(__vanessa_logger_t)))==NULL){
179
perror("__vanessa_logger_create: malloc");
183
vl->type=__vanessa_logger_none;
185
vl->ready=__vanessa_logger_false;
195
/**********************************************************************
196
* __vanessa_logger_destroy
197
* Internal function to destroy a logger
198
* pre: vl: pointer to logger to destroy
199
* post: Memory for logger and any internal memory is freed
200
* Nothing if vl is NULL
202
**********************************************************************/
204
static void __vanessa_logger_destroy(__vanessa_logger_t *vl){
209
__vanessa_logger_reset(vl);
210
__VANESSA_LOGGER_SAFE_FREE(vl);
214
/**********************************************************************
215
* __vanessa_logger_reset
216
* Internal function to set all the values of a logger to their null state
217
* and free any allocated memory.
218
* pre: vl: pointer to logger to reset
219
* post: All internal memory is freed
220
* All internal values are set to null state
221
* Nothing if vl is NULL
223
**********************************************************************/
225
static void __vanessa_logger_reset(__vanessa_logger_t *vl){
226
__vanessa_logger_bool_t ready;
233
* Logger is no longer ready
235
ready=vl->ready; /* Remember state logger _was_ in */
236
vl->ready=__vanessa_logger_false;
239
* Close filehandles or log facilities as neccessary
240
* Free any memory used in storing data
243
case __vanessa_logger_filename:
244
if(ready==__vanessa_logger_true){
245
if(fclose(vl->data.d_filename->filehandle)){
246
perror("__vanessa_logger_reset: fclose");
249
if(vl->data.d_filename!=NULL){
250
__VANESSA_LOGGER_SAFE_FREE(vl->data.d_filename->filename);
252
__VANESSA_LOGGER_SAFE_FREE(vl->data.d_filename);
254
case __vanessa_logger_syslog:
255
__VANESSA_LOGGER_SAFE_FREE(vl->data.d_syslog);
256
if(vl->ready==__vanessa_logger_true){
265
* Reset type and data
267
vl->type=__vanessa_logger_none;
273
__VANESSA_LOGGER_SAFE_FREE(vl->ident);
276
* Reset buffer, buffer_len
278
__VANESSA_LOGGER_SAFE_FREE(vl->buffer);
288
/**********************************************************************
289
* __vanessa_logger_set
290
* Internal function to seed the values of a logger
291
* pre: vl: pointer to logger to seed values of
292
* ident: Identity string to prepend to each log
293
* type: Type of logger to initialise
294
* data: Type specific data for logger typecast to (void *)
295
* post: Values of logger are set to allow loging as per type
296
* Nothing if: vl is NULL or
297
* type is __vanessa_logger_none or
300
* On error vl is destroyed as per __vanessa_logger_destroy
301
* return: vl on success
303
**********************************************************************/
305
static __vanessa_logger_t *__vanessa_logger_set(
306
__vanessa_logger_t *vl,
308
const int max_priority,
309
const __vanessa_logger_type_t type,
313
if(vl==NULL || type==__vanessa_logger_none || data==NULL || ident==NULL){
318
* Free any previously allocated memory
320
__vanessa_logger_reset(vl);
325
if((vl->ident=strdup(ident))==NULL){
326
perror("__vanessa_logger_set: strdup 1");
327
__vanessa_logger_destroy(vl);
334
if((vl->buffer=(char *)malloc(__VANESSA_LOGGER_BUF_SIZE))==NULL){
335
perror("__vanessa_logger_set: malloc 1");
336
__vanessa_logger_destroy(vl);
339
vl->buffer_len=__VANESSA_LOGGER_BUF_SIZE;
350
case __vanessa_logger_filehandle:
351
vl->data.d_filehandle=(FILE *)data;
353
case __vanessa_logger_filename:
354
if((vl->data.d_filename=(__vanessa_logger_filename_data_t *)malloc(
355
sizeof(__vanessa_logger_filename_data_t)
357
perror("__vanessa_logger_set: malloc 2");
358
__vanessa_logger_destroy(vl);
361
if((vl->data.d_filename->filename=strdup((char *)data))==NULL){
362
perror("__vanessa_logger_set: malloc strdup 2");
363
__vanessa_logger_destroy(vl);
366
vl->data.d_filename->filehandle=fopen(vl->data.d_filename->filename, "a");
367
if(vl->data.d_filename->filehandle==NULL){
368
perror("__vanessa_logger_set: fopen");
369
__vanessa_logger_destroy(vl);
373
case __vanessa_logger_syslog:
374
if((vl->data.d_syslog=(int *)malloc(sizeof(int)))==NULL){
375
perror("__vanessa_logger_set: malloc 3");
376
__vanessa_logger_destroy(vl);
379
*(vl->data.d_syslog)=*((int *)data);
380
openlog(vl->ident, LOG_PID|option, *(vl->data.d_syslog));
382
case __vanessa_logger_none:
389
vl->max_priority=max_priority;
394
vl->ready=__vanessa_logger_true;
400
/**********************************************************************
401
* __vanessa_logger_reopen
402
* Internal function to reopen a logger
403
* pre: vl: pointer to logger to reopen
404
* post: In the calse of a filename logger the logger is closed
405
* if it was open and then opened regardless of weather it
406
* was originally open or not.
407
* In the case of a none, syslog or filehandle logger or if vl is NULL
409
* If an error occurs -1 is returned and vl->ready is set to
410
* __vanessa_logger_false
411
* return: 0 on success
413
**********************************************************************/
415
static int __vanessa_logger_reopen(__vanessa_logger_t *vl){
416
if(vl==NULL || vl->type==__vanessa_logger_none){
421
case __vanessa_logger_filename:
422
if(vl->ready==__vanessa_logger_true){
423
vl->ready=__vanessa_logger_false;
424
if(fclose(vl->data.d_filename->filehandle)){
425
perror("__vanessa_logger_reopen: fclose");
429
vl->data.d_filename->filehandle=fopen(vl->data.d_filename->filename, "a");
430
if(vl->data.d_filename->filehandle==NULL){
431
perror("__vanessa_logger_reopen: fopen");
434
vl->ready=__vanessa_logger_true;
444
/**********************************************************************
445
* __vanessa_logger_log
446
* Internal function to log a message
447
* pre: vl: logger to use
448
* priority: priority to log with
449
* Only used if log type is __vanessa_logger_syslog
451
* fmt: format for log message
452
* ap: varargs for format
453
* post: message is logged to appropriate logger
454
* vl->ident[pid]: will be prepended to each log
455
* '\n' will be appended to each log that doesn't already end with
459
**********************************************************************/
461
#define __VANESSA_LOGGER_DO_FH(_vl, _fmt, _fh, _ap) \
472
fprintf(_fh, "__vanessa_logger_log: snprintf: output truncated\n"); \
475
len=strlen(_vl->buffer); \
476
if(*((_vl->buffer)+len-1)!='\n'){ \
477
*((_vl->buffer)+len)='\n'; \
478
*((_vl->buffer)+len+1)='\0'; \
480
vfprintf(_fh, _vl->buffer, _ap); \
483
static void __vanessa_logger_log(
484
__vanessa_logger_t *vl,
489
if(vl==NULL||vl->ready==__vanessa_logger_false||priority>vl->max_priority){
494
case __vanessa_logger_filehandle:
495
__VANESSA_LOGGER_DO_FH(vl, fmt, vl->data.d_filehandle, ap);
497
case __vanessa_logger_filename:
498
__VANESSA_LOGGER_DO_FH(vl, fmt, vl->data.d_filename->filehandle, ap);
500
case __vanessa_logger_syslog:
501
if(vsnprintf(vl->buffer, vl->buffer_len, fmt, ap)<0){
502
syslog(priority, "__vanessa_logger_log: vsnprintf: output truncated");
505
syslog(priority, "%s", vl->buffer);
506
/* syslog(priority, vl->buffer); */
508
case __vanessa_logger_none:
514
/**********************************************************************
515
* __vanessa_logger_get_facility_byname
516
* Given the name of a syslog facility as an ASCII string,
517
* return the facility as an integer.
518
* Relies on facilitynames[] being defined in syslog.h
519
* pre: facility_name: syslog facility as an ASCII string
521
* return: logger as an int
522
* -1 if facility_name cannot be found in facilitynames[],
523
* if facility_name is NULL
525
**********************************************************************/
527
static int __vanessa_logger_get_facility_byname(const char *facility_name){
530
extern CODE facilitynames[];
532
if(facility_name==NULL){
535
"__vanessa_logger_get_facility_byname: facility_name is NULL\n"
540
for(i=0; facilitynames[i].c_name!=NULL; i++){
541
if(!strcmp(facility_name, facilitynames[i].c_name)){
542
return(facilitynames[i].c_val);
548
"__vanessa_logger_get_facility_byname: facility \"%s\" not found\n",
554
/**********************************************************************
555
* vanessa_logger_openlog_syslog
556
* Exported function to open a logger that will log to syslog
557
* pre: facility: facility to log to syslog with
558
* ident: Identity to prepend to each log
559
* max_priority: Maximum priority no to log
560
* Priorities are integers, the levels listed
561
* in syslog(3) should be used for a syslog logger
562
* option: options to pass to the openlog command
563
* Will be logically ored with LOG_PID
564
* post: Logger is opened
565
* return: pointer to logger
567
**********************************************************************/
569
vanessa_logger_t *vanessa_logger_openlog_syslog(
572
const int max_priority,
575
__vanessa_logger_t *vl;
577
if((vl=__vanessa_logger_create())==NULL){
578
fprintf(stderr, "vanessa_logger_openlog_syslog: __vanessa_logger_create\n");
582
if(__vanessa_logger_set(
586
__vanessa_logger_syslog,
590
fprintf(stderr, "vanessa_logger_openlog_syslog: __vanessa_logger_set\n");
594
return((vanessa_logger_t *)vl);
598
/**********************************************************************
599
* vanessa_logger_openlog_syslog_byname
600
* Exported function to open a logger that will log to syslog
601
* pre: facility_name: Name of facility to log to syslog with
602
* ident: Identity to prepend to each log
603
* max_priority: Maximum priority no to log
604
* Priorities are integers, the levels listed
605
* in syslog(3) should be used for a syslog logger
606
* option: options to pass to the openlog command
607
* Will be logically ored with LOG_PID
608
* post: Logger is opened
609
* return: pointer to logger
611
**********************************************************************/
613
vanessa_logger_t *vanessa_logger_openlog_syslog_byname(
614
const char *facility_name,
616
const int max_priority,
619
__vanessa_logger_t *vl;
622
if((facility=__vanessa_logger_get_facility_byname(facility_name))<0){
625
"vanessa_logger_open_syslog_byname: "
626
"__vanessa_logger_get_facility_byname\n"
631
vl=vanessa_logger_openlog_syslog(facility,ident,max_priority,option);
635
"vanessa_logger_openlog_syslog: vanessa_logger_openlog_syslog\n"
640
return((vanessa_logger_t *)vl);
644
/**********************************************************************
645
* vanessa_logger_openlog_filehandle
646
* Exported function to open a logger that will log to a filehandle
647
* pre: filehandle: open filehandle to log to
648
* ident: Identity to prepend to each log
649
* max_priority: Maximum priority number to log
650
* Priorities are integers, the levels listed
651
* in syslog(3) should be used for a syslog logger
653
* post: Logger is opened
654
* return: pointer to logger
656
**********************************************************************/
658
vanessa_logger_t *vanessa_logger_openlog_filehandle(
661
const int max_priority,
664
__vanessa_logger_t *vl;
666
if((vl=__vanessa_logger_create())==NULL){
669
"vanessa_logger_openlog_filehandle: __vanessa_logger_create\n"
674
if(__vanessa_logger_set(
678
__vanessa_logger_filehandle,
682
fprintf(stderr,"vanessa_logger_openlog_filehandle: __vanessa_logger_set\n");
686
return((vanessa_logger_t *)vl);
690
/**********************************************************************
691
* vanessa_logger_openlog_filename
692
* Exported function to open a logger that will log to a filename
693
* that will be opened
694
* pre: filename: filename to log to
695
* ident: Identity to prepend to each log
696
* max_priority: Maximum priority number to log
697
* Priorities are integers, the levels listed
698
* in syslog(3) should be used for a syslog logger
700
* post: Logger is opened
701
* return: pointer to logger
703
**********************************************************************/
705
vanessa_logger_t *vanessa_logger_openlog_filename(
708
const int max_priority,
711
__vanessa_logger_t *vl;
713
if((vl=__vanessa_logger_create())==NULL){
716
"vanessa_logger_openlog_filename: __vanessa_logger_create\n"
721
if(__vanessa_logger_set(
725
__vanessa_logger_filename,
729
fprintf(stderr,"vanessa_logger_openlog_filename: __vanessa_logger_set\n");
733
return((vanessa_logger_t *)vl);
737
/**********************************************************************
738
* vanessa_logger_change_max_priority
739
* Exported function to change the maximum priority that the logger
741
* pre: vl: logger to change the maximum priority of
742
* max_priority: Maximum priority number to log
743
* Priorities are integers, the levels listed
744
* in syslog(3) should be used for a syslog logger
745
* post: maximum priority of logger is changed
746
* nothing if vl is NULL
748
**********************************************************************/
750
void vanessa_logger_change_max_priority(
751
vanessa_logger_t *vl,
752
const int max_priority
758
((__vanessa_logger_t *)vl)->max_priority=max_priority;
762
/**********************************************************************
763
* vanessa_logger_closelog
764
* Exported function to close a logger
765
* pre: vl: pointer to logger to close
766
* post: logger is closed and memory is freed
768
**********************************************************************/
770
void vanessa_logger_closelog(vanessa_logger_t *vl){
771
__vanessa_logger_destroy((__vanessa_logger_t *)vl);
775
/**********************************************************************
777
* Exported function to log a message
778
* pre: vl: pointer to logger to log to
779
* priority: Priority to log with.
780
* If priority is more than max_priority as provided to
781
* vanessa_logger_openlog_filehandle,
782
* vanessa_logger_openlog_filename or
783
* vanessa_logger_openlog_syslog.
784
* Levels described in syslog(3) should be used for
785
* syslog loggers as the priority will be used when
786
* logging to syslog. These priorities may also be
787
* used for filehandle and filename loggers.
788
* Strangely with syslog higher priorities have
789
* _lower_ priority numbers. For this
790
* reason vanessa_logger regards messages with
791
* lower priority numbers as being higher priority
792
* than messages with lower priority. I suggest
793
* just using the syslog priorities to avoid confusion.
794
* fmt: format of message to log as per sprintf(3) for
795
* filename and filehandle loggers and as
796
* per syslog(3) for syslog loggers
798
* post: Message is logged
800
**********************************************************************/
802
void vanessa_logger_log(vanessa_logger_t *vl, int priority, char *fmt, ...){
806
__vanessa_logger_log((__vanessa_logger_t *)vl, priority, fmt, ap);
811
/**********************************************************************
812
* vanessa_logger_logv
813
* Exported function to log a message
814
* Same as vanessa_logger_logv but a va_list is given instead
815
* of a variable number of arguments.
816
**********************************************************************/
818
void vanessa_logger_logv(
819
vanessa_logger_t *vl,
824
__vanessa_logger_log((__vanessa_logger_t *)vl, priority, fmt, ap);
828
/**********************************************************************
829
* vanessa_logger_reopen
830
* Exported function to reopen a logger
831
* pre: vl: pointer to logger to reopen
832
* post: logger is reopened
833
* return: 0 on success
836
* Note: May be used as part of a signal handler to reopen logger
837
* on for instance receiving a SIGHUP
838
**********************************************************************/
840
int vanessa_logger_reopen(vanessa_logger_t *vl){
841
if(__vanessa_logger_reopen((__vanessa_logger_t *)vl)){
842
fprintf(stderr, "vanessa_logger_reopen: __vanessa_logger_reopen\n");