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