Import upstream 2.3.14
[packages/xinetd.git] / libs / src / xlog / xlog.c
1 /*
2  * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
3  * All rights reserved.  The file named COPYRIGHT specifies the terms 
4  * and conditions for redistribution.
5  */
6
7 #include "config.h"
8 #include <stdlib.h>
9 #include <stdarg.h>
10
11 #include "xlog.h"
12 #include "impl.h"
13
14 extern struct xlog_ops __xlog_filelog_ops ;
15 #ifndef NO_SYSLOG
16 extern struct xlog_ops __xlog_syslog_ops ;
17 #endif
18
19 struct lookup_table
20 {
21         struct xlog_ops *ops ;
22         xlog_e          type ;
23 } ;
24
25 static struct lookup_table ops_lookup_table[] =
26 {
27         { &__xlog_filelog_ops,  XLOG_FILELOG },
28 #ifndef NO_SYSLOG
29         { &__xlog_syslog_ops,   XLOG_SYSLOG },
30 #endif
31         { NULL,                 0           }
32 } ;
33
34
35 #define CALLBACK( xp, status )                          \
36         if ( (xp)->xl_callback )                        \
37                 (*(xp)->xl_callback)( (xlog_h)(xp), status, (xp)->xl_callback_arg )
38
39
40 static void xlog_link( xlog_s *client, xlog_s *server ) ;
41 static void xlog_unlink( xlog_s *xp ) ;
42
43
44 static struct xlog_ops *xlog_ops_lookup( xlog_e type )
45 {
46         struct lookup_table *ltp ;
47
48         for ( ltp = &ops_lookup_table[ 0 ] ; ltp->ops ; ltp++ )
49                 if ( ltp->type == type )
50                         break ;
51         return( ltp->ops ) ;
52 }
53
54
55 /* VARARGS3 */
56 xlog_h xlog_create( xlog_e type, const char *id, int flags, ... )
57 {
58         xlog_s                          *xp ;
59         va_list                         ap ;
60         struct xlog_ops *xops ;
61         int                             status ;
62
63         if ( ( xp = NEW( xlog_s ) ) == NULL )
64                 return( NULL ) ;
65         
66         if ( id == NULL || ( xp->xl_id = __xlog_new_string( id ) ) == NULL )
67         {
68                 free( xp ) ;
69                 return( NULL ) ;
70         }
71
72         xops = xlog_ops_lookup( type ) ;
73         
74         if ( xops != NULL )
75         {
76                 va_start( ap, flags ) ;
77                 xp->xl_ops = xops ;
78                 status = XL_INIT( xp, ap ) ;
79                 va_end( ap ) ;
80
81                 if ( status == XLOG_ENOERROR )
82                 {
83                         xp->xl_flags = flags ;
84                         xp->xl_type = type ;
85                         xp->xl_clients = XLOG_NULL ;
86                         xp->xl_use = XLOG_NULL ;
87                         return( (xlog_h) xp ) ;
88                 }
89         }
90
91         free( xp->xl_id ) ;
92         free( xp ) ;
93         return( NULL ) ;
94 }
95
96
97
98 static void xlog_link( xlog_s *client, xlog_s *server )
99 {
100         client->xl_use = server ;
101         if ( server == NULL )
102                 return ;
103
104         if ( server->xl_clients == XLOG_NULL )
105         {
106                 INIT_LINKS( client, xl_other_users ) ;
107                 server->xl_clients = client ;
108         }
109         else
110                 LINK( server, client, xl_other_users ) ;
111 }
112
113
114 static void xlog_unlink( xlog_s *xp )
115 {
116         xlog_s *server = xp->xl_use ;
117
118         /*
119          * Step 1: remove from server chain
120          */
121         if ( server != XLOG_NULL )
122         {
123                 if ( server->xl_clients == xp )
124                         if ( NEXT( xp, xl_other_users ) == xp )
125                                 server->xl_clients = XLOG_NULL ;
126                         else
127                                 server->xl_clients = NEXT( xp, xl_other_users ) ;
128                 else
129                         UNLINK( xp, xl_other_users ) ;
130         }
131
132         /*
133          * Step 2: If we have users, clear their link to us.
134          */
135         if ( xp->xl_clients != NULL )
136         {
137                 xlog_s *xp2 = xp->xl_clients ;
138
139                 do
140                 {
141                         xp2->xl_use = XLOG_NULL ;
142                         xp2 = NEXT( xp2, xl_other_users ) ;
143                 }
144                 while ( xp2 != xp->xl_clients ) ;
145         }
146 }
147
148
149 static void xlog_flags( xlog_s *xp, xlog_cmd_e cmd, ... )
150 {
151         va_list ap;
152         int     flag;
153         int     old_value;
154         int     *valp;
155
156         va_start(ap, cmd);
157         flag = va_arg( ap, int );
158         old_value = ((xp->xl_flags & flag) != 0);
159         valp = va_arg( ap, int * );
160         va_end(ap);
161         if ( cmd == XLOG_SETFLAG ) {
162                 if ( *valp )
163                         xp->xl_flags |= flag ;
164                 else
165                         xp->xl_flags &= ~flag ;
166         }
167         *valp = old_value ;
168 }
169
170
171 void xlog_destroy( xlog_h pxlog )
172 {
173         xlog_s *xp = XP( pxlog ) ;
174
175         xlog_unlink( xp ) ;
176         XL_FINI( xp ) ;
177         free( xp->xl_id ) ;
178         free( xp ) ;
179 }
180
181
182 /* VARARGS4 */
183 void xlog_write( xlog_h pxlog, const char buf[], int len, int flags, ... )
184 {
185         xlog_s  *xp = XP( pxlog ) ;
186         va_list ap ;
187         int             status ;
188
189         va_start( ap, flags ) ;
190         status = XL_WRITE( xp, buf, len, flags, ap ) ;
191         va_end( ap ) ;
192
193         if ( status != XLOG_ENOERROR )
194         {
195                 CALLBACK( xp, status ) ;
196         }
197 }
198
199
200 /* VARARGS2 */
201 int xlog_control( xlog_h pxlog, xlog_cmd_e cmd, ... )
202 {
203         va_list ap ;
204         xlog_s  *xp             = XP( pxlog ) ;
205         int             status  = XLOG_ENOERROR ;
206
207         va_start( ap, cmd ) ;
208
209         switch ( cmd )
210         {
211                 case XLOG_LINK:
212                         xlog_unlink( xp ) ;
213                         xlog_link( xp, va_arg( ap, xlog_s * ) ) ;
214                         xp->xl_callback_arg = va_arg( ap, void * ) ;
215                         break ;
216                 
217                 case XLOG_CALLBACK:
218                         xp->xl_callback = va_arg( ap, voidfunc ) ;
219                         break ;
220                         
221                 case XLOG_GETFLAG:
222                 case XLOG_SETFLAG:
223                         xlog_flags( xp, cmd, ap ) ;
224                         break ;
225
226                 default:
227                         status = XL_CONTROL( xp, cmd, ap ) ;
228         }
229
230         va_end( ap ) ;
231
232         return( status ) ;
233 }
234
235
236 int xlog_parms( xlog_e type, ... )
237 {
238         va_list ap ;
239         int             status ;
240
241         va_start( ap, type ) ;
242         switch ( type )
243         {
244 #ifndef NO_SYSLOG
245                 case XLOG_SYSLOG:
246                         status = (*__xlog_syslog_ops.parms)( type, ap ) ;
247                         break ;
248 #endif
249                 case XLOG_FILELOG:
250                         status = (*__xlog_filelog_ops.parms)( type, ap ) ;
251                         break ;
252                 
253                 default:
254                         status = XLOG_ENOERROR ;
255         }
256         va_end( ap ) ;
257         return( status ) ;
258 }
259