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 
xlog_ops_lookup(xlog_e type)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 */
xlog_create(xlog_e type,const char * id,int flags,...)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 
xlog_link(xlog_s * client,xlog_s * server)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 
xlog_unlink(xlog_s * xp)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 
xlog_flags(xlog_s * xp,xlog_cmd_e cmd,...)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 
xlog_destroy(xlog_h pxlog)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 */
xlog_write(xlog_h pxlog,const char buf[],int len,int flags,...)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 */
xlog_control(xlog_h pxlog,xlog_cmd_e cmd,...)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 			xp->xl_callback_arg = va_arg( ap, void * );
220 			break ;
221 
222 		case XLOG_GETFLAG:
223 		case XLOG_SETFLAG:
224 			xlog_flags( xp, cmd, ap ) ;
225 			break ;
226 
227 		default:
228 			status = XL_CONTROL( xp, cmd, ap ) ;
229 	}
230 
231 	va_end( ap ) ;
232 
233 	return( status ) ;
234 }
235 
236 
xlog_parms(xlog_e type,...)237 int xlog_parms( xlog_e type, ... )
238 {
239 	va_list	ap ;
240 	int		status ;
241 
242 	va_start( ap, type ) ;
243 	switch ( type )
244 	{
245 #ifndef NO_SYSLOG
246 		case XLOG_SYSLOG:
247 			status = (*__xlog_syslog_ops.parms)( type, ap ) ;
248 			break ;
249 #endif
250 		case XLOG_FILELOG:
251 			status = (*__xlog_filelog_ops.parms)( type, ap ) ;
252 			break ;
253 
254 		default:
255 			status = XLOG_ENOERROR ;
256 	}
257 	va_end( ap ) ;
258 	return( status ) ;
259 }
260 
261