]> www.wagner.pp.ru Git - oss/tclsyslog.git/blob - tclsyslog.c
reapplyed 2.0 changes
[oss/tclsyslog.git] / tclsyslog.c
1 /* Syslog interface for tcl
2
3 */
4 #include <tcl.h>
5 #include <syslog.h>
6 #include <string.h>
7 typedef struct {
8                 int logOpened;
9                 int facility,options;
10                 char ident[32];
11                 Tcl_HashTable *priorities;
12                 Tcl_HashTable *facilities;
13                } SyslogInfo;
14
15 void Syslog_ListHash(Tcl_Interp *interp,Tcl_HashTable *table);         
16 /* SyslogHelp - puts usage message into interp->result
17  * 
18  *
19  */
20
21 void SyslogHelp(Tcl_Interp *interp,char *cmdname)
22 {  Tcl_AppendResult(interp,"Wrong # of args. should be ",cmdname, 
23            " ?option value? priority message",NULL);
24 }
25
26 /* Syslog_Log -
27  * implements syslog tcl command. General format: syslog ?options? level text
28  * options -facility -ident -options
29  * 
30  */
31
32
33 int Syslog_Log(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST  objv[])
34 {    SyslogInfo *info=(SyslogInfo *)data;
35     Tcl_DString *message = NULL;
36     int priority;
37     int i=1;
38     if (objc<=1) {
39         SyslogHelp(interp,Tcl_GetString(objv[0]));
40         return TCL_ERROR;
41     }
42   while (i<objc-1) {
43     if (!strncmp(Tcl_GetString(objv[i]),"-facility",10)) {
44         char *facility_name = Tcl_GetString(objv[i+1]);
45         Tcl_HashEntry * entry=Tcl_FindHashEntry(info->facilities,facility_name);
46         if (!entry) {
47            Tcl_AppendResult(interp,"Invalid facility name: \"",Tcl_GetString(objv[i+1]),"\"",
48                 " available facilities: ",
49                    NULL);
50            Syslog_ListHash(interp,info->facilities);
51            return TCL_ERROR;
52         }
53         info->facility=(int)Tcl_GetHashValue(entry);
54         if (info-> logOpened) {
55             closelog();
56             info-> logOpened=0;
57         }
58      } else if (!strncmp(Tcl_GetString(objv[i]),"-options",9)) {
59          long tmp;
60         if (Tcl_GetLongFromObj(interp,objv[i+1],&tmp)==TCL_ERROR)
61              return TCL_ERROR;
62         info->options=tmp;
63         if (info->logOpened) {
64             closelog();
65             info->logOpened=0;
66         }
67      } else if (!strncmp(Tcl_GetStringFromObj(objv[i],NULL),"-ident",7)) {
68         char *ident_name=Tcl_GetString(objv[i+1]);
69         Tcl_DString *dstring=(Tcl_DString *)Tcl_Alloc(sizeof(Tcl_DString));
70         Tcl_DStringInit(dstring);
71         Tcl_UtfToExternalDString(NULL,ident_name,strlen(ident_name),
72           dstring);              
73          strncpy(info->ident,Tcl_DStringValue(dstring),32);
74          Tcl_DStringFree(dstring);
75          Tcl_Free((char *)dstring);
76         info->ident[31]=0;
77         if (info->logOpened) {
78             closelog();
79             info->logOpened=0;
80         }
81      } else {
82          char *messageutf;
83        Tcl_HashEntry *entry=Tcl_FindHashEntry(info->priorities,Tcl_GetString(objv[i]));
84        if (!entry) {
85           Tcl_AppendResult(interp,"Invalid syslog level \"",Tcl_GetString(objv[i]),"\"",
86                   " available levels: ",
87                NULL);
88           Syslog_ListHash(interp,info->priorities); 
89           return TCL_ERROR;
90        }
91        priority=(int)Tcl_GetHashValue(entry);
92        message=(Tcl_DString *)Tcl_Alloc(sizeof(Tcl_DString));
93        Tcl_DStringInit(message);
94        messageutf=Tcl_GetString(objv[i+1]);
95        Tcl_UtfToExternalDString(NULL,messageutf,strlen(messageutf),
96                 message);
97       
98        i+=2;
99        if (i<objc-1) {
100            SyslogHelp(interp,Tcl_GetString(objv[0]));
101            return TCL_ERROR;
102        }
103      }
104      i+=2;
105   }
106   if (i<objc-1) {
107      SyslogHelp(interp,Tcl_GetString(objv[0]));
108      return TCL_ERROR;
109   }
110   if (message) {
111       if (!info->logOpened) {
112           openlog(info->ident,info->options,info->facility);
113           info->logOpened=1;
114       }
115       syslog(priority,"%s",Tcl_DStringValue(message));
116       Tcl_DStringFree(message);
117       Tcl_Free((char *)message);
118   }
119   return TCL_OK;
120 }
121 /* 
122  *  Syslog_Delete - Tcl_CmdDeleteProc for syslog command.
123  *  Frees all hash tables and closes log if it was opened.
124  */
125 void Syslog_Delete(ClientData data)
126 { SyslogInfo *info=(SyslogInfo *)data;
127   Tcl_DeleteHashTable(info->facilities);
128   Tcl_Free((char *)info->facilities);
129   Tcl_DeleteHashTable(info->priorities);
130   Tcl_Free((char *)info->priorities);
131   if (info->logOpened) {
132      closelog();
133   }
134   Tcl_Free((char *)info);
135 }
136
137 /*
138  * Syslog_ListHash - appends to interp result all the values of given
139  * hash table
140  */
141 void Syslog_ListHash(Tcl_Interp *interp,Tcl_HashTable *table) 
142 {
143     Tcl_HashSearch *searchPtr=(Tcl_HashSearch *)
144           Tcl_Alloc(sizeof(Tcl_HashSearch));
145     Tcl_HashEntry *entry;
146     char separator[3]={' ',' ',0};   
147     entry=Tcl_FirstHashEntry(table,searchPtr);
148     while (entry) {
149         Tcl_AppendResult(interp,separator,Tcl_GetHashKey(table,entry),NULL);
150         separator[0]=',';
151         entry=Tcl_NextHashEntry(searchPtr);
152     }   
153     Tcl_Free((char *)searchPtr);
154
155 /*
156  * My simplified wrapper for add values into hash
157  *
158  */
159 void AddEntry(Tcl_HashTable *table,char *key,int value)
160 { int new;
161   Tcl_HashEntry *entry=Tcl_CreateHashEntry(table,key,&new);
162   Tcl_SetHashValue(entry,(ClientData)value);
163 }
164 /*
165  * Syslog_Init 
166  * Package initialization procedure for Syslog package. 
167  * Creates command 'syslog', fills hash tables to map symbolic prioriry 
168  * and facility names to system constants.
169  */
170 int Syslog_Init(Tcl_Interp *interp)
171 {  char *argv0;
172     SyslogInfo *info;
173    if (Tcl_InitStubs(interp,"8.1",0)==NULL) {
174       return TCL_ERROR;
175    }     
176    info=(SyslogInfo *)Tcl_Alloc(sizeof(SyslogInfo));
177    info->logOpened=0;
178    info->options=0;
179    info->facility=LOG_USER;
180    argv0=Tcl_GetVar(interp,"argv0",TCL_GLOBAL_ONLY);
181    if (argv0) {
182        strncpy(info->ident,argv0,32);
183    } else {
184        strcpy(info->ident,"Tcl script");
185    }
186    info->ident[31]=0;
187    info->facilities =(Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
188    Tcl_InitHashTable(info->facilities,TCL_STRING_KEYS);
189    AddEntry(info->facilities,"auth",LOG_AUTH);  
190 #ifndef LOG_AUTHPRIV
191 # define LOG_AUTHPRIV LOG_AUTH
192 #endif
193    AddEntry(info->facilities,"authpriv",LOG_AUTHPRIV);  
194    AddEntry(info->facilities,"cron",LOG_CRON);  
195    AddEntry(info->facilities,"daemon",LOG_DAEMON);  
196    AddEntry(info->facilities,"kernel",LOG_KERN);
197    AddEntry(info->facilities,"lpr",LOG_LPR);
198    AddEntry(info->facilities,"mail",LOG_MAIL);
199    AddEntry(info->facilities,"news",LOG_NEWS);
200    AddEntry(info->facilities,"syslog",LOG_SYSLOG);
201    AddEntry(info->facilities,"user",LOG_USER);
202    AddEntry(info->facilities,"uucp",LOG_UUCP);
203    AddEntry(info->facilities,"local0",LOG_LOCAL0);
204    AddEntry(info->facilities,"local1",LOG_LOCAL1);
205    AddEntry(info->facilities,"local2",LOG_LOCAL2);
206    AddEntry(info->facilities,"local3",LOG_LOCAL3);
207    AddEntry(info->facilities,"local4",LOG_LOCAL4);
208    AddEntry(info->facilities,"local5",LOG_LOCAL5);
209    AddEntry(info->facilities,"local6",LOG_LOCAL6);
210    AddEntry(info->facilities,"local7",LOG_LOCAL7);
211    info->priorities = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
212    Tcl_InitHashTable(info->priorities,TCL_STRING_KEYS);
213    AddEntry(info->priorities,"emerg",LOG_EMERG);
214    AddEntry(info->priorities,"alert",LOG_ALERT);
215    AddEntry(info->priorities,"crit",LOG_CRIT);
216    AddEntry(info->priorities,"err",LOG_ERR);
217    AddEntry(info->priorities,"error",LOG_ERR);
218    AddEntry(info->priorities,"warning",LOG_WARNING);
219    AddEntry(info->priorities,"notice",LOG_NOTICE);
220    AddEntry(info->priorities,"info",LOG_INFO);
221    AddEntry(info->priorities,"debug",LOG_DEBUG);
222    Tcl_CreateObjCommand(interp,"syslog",Syslog_Log,(ClientData) info,
223             Syslog_Delete); 
224    return Tcl_PkgProvide(interp,"Syslog",VERSION);
225 }