1 /*
2 *
3 *
4 * RCS Modification History:
5 * $Log: ma_intfc.c,v $
6 * Revision 6.0 1997/08/25 18:36:18 madden
7 * Revision changed to 6.0
8 *
9 * Revision 1.2 1995/05/17 17:54:55 epstein
10 * add RCS log revision history
11 *
12 */
13
14 #include <stdlib.h>
15 #include "xalloc.h"
16 #include "ma_intfc.h"
17
18 extern ma_Obj mfmt_ASN1_text, mfmt_ASN1_binary;
19
20 typedef struct ma_Hand {
21 char *cmd_flag;
22 char *handler_name;
23 char *load_path;
24 char *loadob_sym;
25 ma_Obj *object;
26 void *handle;
27 void *data;
28 int unusable;
29 } ma_Hand;
30
31 ma_Hand default_handler_table[] = {
32
33 { /* Handle the ASN1 text interface */
34 "asn1",
35 "ASN1 Text",
36 NULL,
37 "_mfmt_ASN1_text",
38 &mfmt_ASN1_text,
39 (void *) NULL,
40 (void *) NULL,
41 FALSE
42 },
43
44 { /* Handle the ASN1 binary interface */
45 "asn1b",
46 "ASN1 Binary",
47 NULL,
48 "_mfmt_ASN1_binary",
49 &mfmt_ASN1_binary,
50 (void *) NULL,
51 (void *) NULL,
52 FALSE
53 }
54 };
55 static int n_default_handlers =
56 sizeof(default_handler_table)/sizeof(ma_Hand);
57
58
59 static
60 ma_Hand handler_table[ MAX_FORMAT_HANDLERS ];
61 static int n_handlers = 0;
62
63
64 static
strdup(char * s)65 char *strdup( char *s ) {
66 char *r;
67
68 if( s == NULL ) return( NULL );
69
70 r = xalloc( strlen(s) + 1 );
71 strcpy(r, s );
72 return( r );
73 }
74
75 static
install_format(char * file_name,char * cmd_flag,char * load_path,ma_Obj * object,char * load_symbol,char * handler_name)76 int install_format( char *file_name, char *cmd_flag, char *load_path,
77 ma_Obj *object, char *load_symbol, char *handler_name )
78 {
79 char *config_file;
80
81 /* Check the arguments */
82
83 config_file = (file_name == NULL) ? "built-in's" : file_name;
84 if( cmd_flag != NULL && handler_name == NULL ) handler_name = cmd_flag;
85 if( handler_name == NULL ) handler_name = "<<Unknown handler>>";
86 if( cmd_flag == NULL ) {
87 fprintf(stderr, "%s: No format name flag specified for %s handler\n",
88 config_file, handler_name );
89 return( FALSE );
90 }
91 if( load_path == NULL && file_name != NULL ) {
92 fprintf(stderr, "%s: No load path given for %s handler\n",
93 config_file, handler_name );
94 return( FALSE );
95 }
96 if( load_symbol == NULL ) {
97 fprintf(stderr, "%s: No load symbol given for %s handler\n",
98 config_file, handler_name );
99 return( FALSE );
100 }
101
102 /* Install the entry */
103
104 if( n_handlers >= MAX_FORMAT_HANDLERS ) {
105 fprintf(stderr, "%s: Too many handlers at handler %s (%d MAX)\n",
106 config_file, handler_name, MAX_FORMAT_HANDLERS );
107 return( FALSE );
108 }
109 handler_table[n_handlers].cmd_flag = cmd_flag;
110 handler_table[n_handlers].handler_name = handler_name;
111 handler_table[n_handlers].load_path = load_path;
112 handler_table[n_handlers].object = object;
113 handler_table[n_handlers].loadob_sym = load_symbol;
114 n_handlers++;
115
116 return( TRUE );
117 }
118
119 typedef enum { begin_scan, in_token, quoted_char, quoted_string, end_scan }
120 State;
121
122 static
get_token(char * s,char ** next)123 char *get_token( char *s, char **next )
124 {
125 static char token[MAX_TOKEN_SIZE];
126 char *t = &token[0];
127 State state, old_state;
128 char mark;
129
130 /* Scan out the token */
131
132 if( s != NULL ) {
133 for( state = begin_scan; state != end_scan; ) {
134
135 /* White space is all equivalent */
136
137 if( isspace( *s ) || *s == '\r' || *s == '\n' )
138 *s = ' ';
139
140 switch( state ) {
141 case begin_scan:
142 switch( *s ) {
143 case '"':
144 case '\'': /* Quoted strings */
145 mark = *s;
146 state = quoted_string;
147 break;
148 case 0: /* End of string */
149 state = end_scan;
150 /* DROP THROUGH */
151 case ' ': /* Spaces - ignore */
152 break;
153 default: /* Standard token */
154 state = in_token;
155 continue; /* We'll retest this char */
156 }
157 break;
158 case in_token: /* Standard token */
159 switch( *s ) {
160 case ' ': /* Space - terminate the token */
161 case 0: /* End of input */
162 state = end_scan;
163 break;
164 case '\\': /* Quoted character? */
165 old_state = state;
166 state = quoted_char;
167 break;
168 default:
169 *t++ = *s;
170 break; /* Continue collecting */
171 }
172 break;
173 case quoted_string: /* String inside quotes */
174 if( *s == 0 )
175 state == end_scan;
176 else if( *s == mark ) {
177 state = old_state;
178 break;
179 } else if( *s == '\\' ) {
180 old_state = state;
181 state = quoted_char;
182 } else {
183 *t++ = *s;
184 }
185 break;
186 case quoted_char: /* Quoted char (\x) */
187 if( *s == 0 )
188 state = end_scan;
189 else {
190 state = old_state;
191 *t++ = *s;
192 }
193 break;
194 }
195 if( *s != (char) 0 ) s++;
196 }
197 }
198 *t++ = (char) 0; /* Terminate token */
199
200 /* Figure out where the next token is */
201
202 if( next != (char **) NULL ) {
203 *next = ( s == NULL || *s == (char) 0 ) ? NULL : s;
204 }
205
206 /* Done */
207
208 return( (*token == (char) 0) ? NULL : token );
209 }
210
211
212 static
get_handlers(char * file_name)213 int get_handlers( char *file_name )
214 {
215 FILE *fd;
216 char buffer[MAX_FORMAT_LINE];
217 int rv = TRUE;
218 char *token;
219
220 /* Open the configuration file */
221
222 fd = fopen( file_name, "r" );
223 if( fd == NULL ) {
224 perror( file_name );
225 return( FALSE );
226 }
227
228 /* Read the file and extract the handler lines */
229
230 while( fgets( buffer, sizeof(buffer), fd ) != NULL ) {
231 char *next;
232 char *label = get_token( buffer, &next );
233 if( label == NULL || *label == '#' )
234 continue; /* Ignore me type lines */
235 if( strcmp( label, "format" ) == 0 ) {
236 char *cmd_flag, *load_path, *load_symbol, *handler_name;
237
238 cmd_flag = strdup( get_token( next, &next ) );
239 load_path = strdup( get_token( next, &next ) );
240 load_symbol = strdup( get_token( next, &next ) );
241 handler_name = strdup( get_token( next, &next ) );
242 rv &= install_format( file_name, cmd_flag, load_path,
243 (ma_Obj *) NULL, load_symbol, handler_name);
244
245 } else if( strcmp( label, "include" ) == 0 ) {
246 while( (token = get_token( next, &next )) != NULL ) {
247 char file_name[MAX_TOKEN_SIZE];
248
249 strcpy( file_name, token );
250 rv &= get_handlers( file_name );
251 }
252 }
253 }
254
255 /* Return the status */
256
257 return( rv );
258 }
259
260
261 /*ARGSUSED*/
ma_GetHandlers(char * file_name)262 int ma_GetHandlers( char *file_name )
263 {
264 #ifdef DEBUG
265 /* DEBUG VERSION - Uses hard coded table */
266
267 n_handlers = sizeof(handler_table)/sizeof(ma_Hand);
268 return( TRUE );
269 #else
270 int rv = TRUE; /* Assume everything OK */
271 int i;
272
273 /* Open the configuration file and read the data */
274
275 if( file_name != NULL ) rv = get_handlers( file_name );
276
277 /* Install the default handlers */
278
279 for( i = 0; i < n_default_handlers; i++ ) {
280 ma_Hand *h = &default_handler_table[i];
281 rv &= install_format( NULL, h->cmd_flag, h->load_path,
282 h->object, h->loadob_sym, h->handler_name );
283 }
284 #endif
285 }
286
287
ma_ValidHandler(char * cmd_flag)288 void *ma_ValidHandler( char *cmd_flag )
289 {
290 register int i;
291
292 /* Search the handler table for a key. Only one file can be open
293 on a channel, so we'll look only at closed channels */
294
295 for( i = 0; i < n_handlers; i++ )
296 if( handler_table[i].data == NULL &&
297 strcmp( handler_table[i].cmd_flag, cmd_flag ) == 0 )
298 return( &handler_table[i] );
299
300 /* If we didn't find one - we didn't have a slot for it. */
301
302 return( NULL );
303 }
304
305
ma_OpenHandler(void * x_handler,char * file_name,FILE * fd)306 int ma_OpenHandler( void *x_handler, char *file_name, FILE *fd )
307 {
308 ma_Hand *handler = x_handler;
309 int rv;
310
311 /* Open the library */
312
313 if( handler->load_path != NULL ) {
314 handler->handle = dlopen( handler->load_path, RTLD_LAZY );
315 if( handler->handle == NULL ) goto err;
316
317 /* Get the object from the module */
318
319 handler->object = dlsym( handler->handle, handler->loadob_sym );
320 }
321 if( handler->object == NULL )
322 goto err;
323
324 /* Initialize the channel */
325
326 handler->data = handler->object->initialize( handler->handler_name,
327 handler->object->data );
328 if( handler->data == NULL )
329 goto err;
330
331 /* If the file pointer is NULL - we'll open it; otherwise, we assume
332 that the file is already open (usually stdout) */
333
334 if( fd != NULL)
335 rv = handler->object->setup_file( handler->data, file_name, fd );
336 else
337 rv = handler->object->open_file( handler->data, file_name );
338
339 /* Successful exit */
340
341 if( rv ) return( True );
342
343 /* Come here on an error */
344 err:
345 handler->unusable = TRUE;
346 return( FALSE );
347 }
348
349
ma_WriteArticle(void * x_handler,MedArt * article)350 int ma_WriteArticle( void *x_handler, MedArt *article )
351 {
352 ma_Hand *handler = x_handler;
353 /* If the handler is usable - use it */
354
355 if( handler->unusable )
356 return( FALSE );
357
358 return( handler->object->process( handler->data, article ) );
359 }
360
361
ma_CloseHandler(void * x_handler)362 int ma_CloseHandler( void *x_handler )
363 {
364 ma_Hand *handler = x_handler;
365
366 /* We don't have to do anything if it was never opened */
367
368 if( handler->object != NULL && handler->data != NULL ) {
369 (void) handler->object->close( handler->data );
370 handler->data = NULL;
371 }
372
373 /* Close the object module */
374
375 if( handler->handle != NULL ) {
376 dlclose( handler->handle );
377 handler->handle = NULL;
378 handler->object = NULL;
379 }
380
381 /* Finished */
382
383 return( TRUE );
384 }
385
386
ma_GetErrorString(void * x_handler)387 char *ma_GetErrorString( void *x_handler )
388 {
389 ma_Hand *handler = x_handler;
390
391 /* Make sure that the handler is open */
392
393 if( handler->handle == NULL || handler->object == NULL ||
394 handler->data == NULL )
395 {
396 static char message[512];
397 sprintf( message, "MEDLINE %s output handler is not open",
398 handler->handler_name );
399 return( message );
400 }
401
402 /* We have the handler - get the error string */
403
404 return( handler->object->get_error( handler->data ) );
405 }
406