1 /* LOGMSG.C (c) Copyright Ivan Warren, 2003-2006 */
2 /* logmsg frontend routing */
3
4 #include "hstdinc.h"
5
6 #define _HUTIL_DLL_
7 #define _LOGMSG_C_
8
9 #include "hercules.h"
10
11 #define BFR_CHUNKSIZE (256)
12
13 /******************************************/
14 /* UTILITY MACRO BFR_VSNPRINTF */
15 /* Original design by Fish */
16 /* Modified by Jay Maynard */
17 /* Further modification by Ivan Warren */
18 /* */
19 /* Purpose : set 'bfr' to contain */
20 /* a C string based on a message format */
21 /* and a va_list of args. */
22 /* bfr must be free()d when over with */
23 /* this macro can ONLY be used from the */
24 /* topmost variable arg function */
25 /* that is the va_list cannot be passed */
26 /* as a parameter from another function */
27 /* since va_xxx functions behavio(u)r */
28 /* seems to be undefined in those cases */
29 /* char *bfr; must be originally defined */
30 /* int siz; must be defined and cont- */
31 /* ain a start size */
32 /* va_list vl; must be defined and init- */
33 /* ialised with va_start */
34 /* char *msg; is the message format */
35 /* int rc; to contain final size */
36 /******************************************/
37
38 #define BFR_VSNPRINTF() \
39 bfr=malloc(siz); \
40 rc=-1; \
41 while(bfr&&rc<0) \
42 { \
43 va_start(vl,msg); \
44 rc=vsnprintf(bfr,siz,msg,vl); \
45 va_end(vl); \
46 if(rc>=0 && rc<siz) \
47 break; \
48 rc=-1; \
49 siz+=BFR_CHUNKSIZE; \
50 bfr=realloc(bfr,siz); \
51 }
52
53 static LOCK log_route_lock;
54
55 #define MAX_LOG_ROUTES 16
56 typedef struct _LOG_ROUTES
57 {
58 TID t;
59 LOG_WRITER *w;
60 LOG_CLOSER *c;
61 void *u;
62 } LOG_ROUTES;
63
64 LOG_ROUTES log_routes[MAX_LOG_ROUTES];
65
66 static int log_route_inited=0;
67
log_route_init(void)68 static void log_route_init(void)
69 {
70 int i;
71 if(log_route_inited)
72 {
73 return;
74 }
75 initialize_lock(&log_route_lock);
76 for(i=0;i<MAX_LOG_ROUTES;i++)
77 {
78 log_routes[i].t=0;
79 log_routes[i].w=NULL;
80 log_routes[i].c=NULL;
81 log_routes[i].u=NULL;
82 }
83 log_route_inited=1;
84 return;
85 }
86 /* LOG Routing functions */
log_route_search(TID t)87 static int log_route_search(TID t)
88 {
89 int i;
90 for(i=0;i<MAX_LOG_ROUTES;i++)
91 {
92 if(log_routes[i].t==t)
93 {
94 if(t==0)
95 {
96 log_routes[i].t=(TID)1;
97 }
98 return(i);
99 }
100 }
101 return(-1);
102 }
103
104 /* Open a log redirection Driver route on a per-thread basis */
105 /* Up to 16 concurent threads may have an alternate logging route */
106 /* opened */
log_open(LOG_WRITER * lw,LOG_CLOSER * lc,void * uw)107 DLL_EXPORT int log_open(LOG_WRITER *lw,LOG_CLOSER *lc,void *uw)
108 {
109 int slot;
110 log_route_init();
111 obtain_lock(&log_route_lock);
112 slot=log_route_search((TID)0);
113 if(slot<0)
114 {
115 release_lock(&log_route_lock);
116 return(-1);
117 }
118 log_routes[slot].t=thread_id();
119 log_routes[slot].w=lw;
120 log_routes[slot].c=lc;
121 log_routes[slot].u=uw;
122 release_lock(&log_route_lock);
123 return(0);
124 }
125
log_close(void)126 DLL_EXPORT void log_close(void)
127 {
128 int slot;
129 log_route_init();
130 obtain_lock(&log_route_lock);
131 slot=log_route_search(thread_id());
132 if(slot<0)
133 {
134 release_lock(&log_route_lock);
135 return;
136 }
137 log_routes[slot].c(log_routes[slot].u);
138 log_routes[slot].t=0;
139 log_routes[slot].w=NULL;
140 log_routes[slot].c=NULL;
141 log_routes[slot].u=NULL;
142 release_lock(&log_route_lock);
143 return;
144 }
145
146 /*-------------------------------------------------------------------*/
147 /* Log message: Normal routing (panel or buffer, as appropriate) */
148 /*-------------------------------------------------------------------*/
logmsg(char * msg,...)149 DLL_EXPORT void logmsg(char *msg,...)
150 {
151 char *bfr=NULL;
152 int rc;
153 int siz=1024;
154 va_list vl;
155 #ifdef NEED_LOGMSG_FFLUSH
156 fflush(stdout);
157 #endif
158 BFR_VSNPRINTF();
159 if(bfr)
160 log_write(0,bfr);
161 #ifdef NEED_LOGMSG_FFLUSH
162 fflush(stdout);
163 #endif
164 if(bfr)
165 {
166 free(bfr);
167 }
168 }
169
170 /*-------------------------------------------------------------------*/
171 /* Log message: Panel only (no logmsg routing) */
172 /*-------------------------------------------------------------------*/
logmsgp(char * msg,...)173 DLL_EXPORT void logmsgp(char *msg,...)
174 {
175 char *bfr=NULL;
176 int rc;
177 int siz=1024;
178 va_list vl;
179 #ifdef NEED_LOGMSG_FFLUSH
180 fflush(stdout);
181 #endif
182 BFR_VSNPRINTF();
183 if(bfr)
184 log_write(1,bfr);
185 #ifdef NEED_LOGMSG_FFLUSH
186 fflush(stdout);
187 #endif
188 if(bfr)
189 {
190 free(bfr);
191 }
192 }
193
194 /*-------------------------------------------------------------------*/
195 /* Log message: Both panel and logmsg routing */
196 /*-------------------------------------------------------------------*/
logmsgb(char * msg,...)197 DLL_EXPORT void logmsgb(char *msg,...)
198 {
199 char *bfr=NULL;
200 int rc;
201 int siz=1024;
202 va_list vl;
203 #ifdef NEED_LOGMSG_FFLUSH
204 fflush(stdout);
205 #endif
206 BFR_VSNPRINTF();
207 if(bfr)
208 log_write(2,bfr);
209 #ifdef NEED_LOGMSG_FFLUSH
210 fflush(stdout);
211 #endif
212 if(bfr)
213 {
214 free(bfr);
215 }
216 }
217
218 /*-------------------------------------------------------------------*/
219 /* Log message: Device trace */
220 /*-------------------------------------------------------------------*/
logdevtr(DEVBLK * dev,char * msg,...)221 DLL_EXPORT void logdevtr(DEVBLK *dev,char *msg,...)
222 {
223 char *bfr=NULL;
224 int rc;
225 int siz=1024;
226 va_list vl;
227 #ifdef NEED_LOGMSG_FFLUSH
228 fflush(stdout);
229 #endif
230 if(dev->ccwtrace||dev->ccwstep)
231 {
232 logmsg("%4.4X:",dev->devnum);
233 BFR_VSNPRINTF();
234 if(bfr)
235 log_write(2,bfr);
236 }
237 #ifdef NEED_LOGMSG_FFLUSH
238 fflush(stdout);
239 #endif
240 if(bfr)
241 {
242 free(bfr);
243 }
244 } /* end function logdevtr */
245
246 /* panel : 0 - No, 1 - Only, 2 - Also */
log_write(int panel,char * msg)247 DLL_EXPORT void log_write(int panel,char *msg)
248 {
249
250 /* (log_write function proper starts here) */
251 int slot;
252 log_route_init();
253 if(panel==1)
254 {
255 write_pipe( logger_syslogfd[LOG_WRITE], msg, strlen(msg) );
256 return;
257 }
258 obtain_lock(&log_route_lock);
259 slot=log_route_search(thread_id());
260 release_lock(&log_route_lock);
261 if(slot<0 || panel>0)
262 {
263 write_pipe( logger_syslogfd[LOG_WRITE], msg, strlen(msg) );
264 if(slot<0)
265 return;
266 }
267 log_routes[slot].w(log_routes[slot].u,msg);
268 return;
269 }
270
271 /* capture log output routine series */
272 /* log_capture is a sample of how to */
273 /* use log rerouting. */
274 /* log_capture takes 2 args : */
275 /* a ptr to a function taking 1 parm */
276 /* the function parm */
277 struct log_capture_data
278 {
279 char *obfr;
280 size_t sz;
281 };
282
log_capture_writer(void * vcd,char * msg)283 DLL_EXPORT void log_capture_writer(void *vcd,char *msg)
284 {
285 struct log_capture_data *cd;
286 if(!vcd||!msg)return;
287 cd=(struct log_capture_data *)vcd;
288 if(cd->sz==0)
289 {
290 cd->sz=strlen(msg)+1;
291 cd->obfr=malloc(cd->sz);
292 cd->obfr[0]=0;
293 }
294 else
295 {
296 cd->sz+=strlen(msg);
297 cd->obfr=realloc(cd->obfr,cd->sz);
298 }
299 strcat(cd->obfr,msg);
300 return;
301 }
log_capture_closer(void * vcd)302 DLL_EXPORT void log_capture_closer(void *vcd)
303 {
304 UNREFERENCED(vcd);
305 return;
306 }
307
log_capture(void * (* fun)(void *),void * p)308 DLL_EXPORT char *log_capture(void *(*fun)(void *),void *p)
309 {
310 struct log_capture_data cd;
311 cd.obfr=NULL;
312 cd.sz=0;
313 log_open(log_capture_writer,log_capture_closer,&cd);
314 fun(p);
315 log_close();
316 return(cd.obfr);
317 }
318