2 * handlers.c - Handlers' functions.
4 * Copyright (C) 2001-2003
6 * Neven Has <haski@sezampro.yu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "nalfs-core.h"
36 #include "ltdl/ltdl.h"
39 static struct handlers
{
42 } handlers
= { 0, NULL
};
44 /* Embedded "handlers" for the profile and comment elements. */
54 static const struct handler_attribute profile_attributes
[] = {
55 { .name
= "path", .private = PROFILE_PATH
},
59 static int profile_setup(element_s
* const element
)
61 struct profile_data
*data
;
63 if ((data
= xmalloc(sizeof(struct profile_data
))) == NULL
)
67 element
->handler_data
= data
;
72 static void profile_free(const element_s
* const element
)
74 struct profile_data
*data
= (struct profile_data
*) element
->handler_data
;
80 static int profile_attribute(const element_s
* const element
,
81 const struct handler_attribute
* const attr
,
82 const char * const value
)
84 struct profile_data
*data
= (struct profile_data
*) element
->handler_data
;
86 switch (attr
->private) {
88 /* will never be called by parser more than once */
89 data
->path
= xstrdup(value
);
96 static int profile_valid_child(const element_s
* const element
,
97 const element_s
* const child
)
104 static char *profile_data(const element_s
* const element
,
105 const handler_data_e data_requested
)
107 struct profile_data
*data
= (struct profile_data
*) element
->handler_data
;
109 switch (data_requested
) {
110 case HDATA_SYNTAX_VERSION
:
111 return xstrdup(*opt_default_syntax
);
112 case HDATA_DISPLAY_NAME
:
116 /* display only the file name, not the whole path */
117 if ((tmp
= strrchr(data
->path
, '/'))) {
118 return xstrdup(++tmp
);
120 return xstrdup(data
->path
);
130 static int profile_main(const element_s
* const el
)
137 struct comment_data
{
141 static int comment_setup(element_s
* const element
)
143 struct comment_data
*data
;
145 if ((data
= xmalloc(sizeof(struct comment_data
))) == NULL
)
148 data
->content
= NULL
;
149 element
->handler_data
= data
;
154 static void comment_free(const element_s
* const element
)
156 struct comment_data
*data
= (struct comment_data
*) element
->handler_data
;
158 xfree(data
->content
);
162 static int comment_content(const element_s
* const element
,
163 const char * const content
)
165 struct comment_data
*data
= (struct comment_data
*) element
->handler_data
;
168 data
->content
= xstrdup(content
);
173 static char *comment_data(const element_s
* const element
,
174 const handler_data_e data_requested
)
176 struct comment_data
*data
= (struct comment_data
*) element
->handler_data
;
178 switch (data_requested
) {
179 case HDATA_DISPLAY_NAME
:
180 if (strchr(data
->content
, '\n')) {
181 return xstrdup("comment block");
183 return xstrdup(data
->content
);
192 static int comment_main(const element_s
* const el
)
199 static handler_info_s embedded_handlers_info
[] = {
202 .description
= "profile",
203 .syntax_version
= "all",
204 .main
= profile_main
,
205 .type
= HTYPE_NORMAL
,
206 .valid_child
= profile_valid_child
,
207 .data
= HDATA_SYNTAX_VERSION
| HDATA_DISPLAY_NAME
,
208 .alloc_data
= profile_data
,
209 .attributes
= profile_attributes
,
210 .attribute
= profile_attribute
,
211 .setup
= profile_setup
,
212 .free
= profile_free
,
216 .description
= "comment",
217 .syntax_version
= "all",
218 .main
= comment_main
,
219 .type
= HTYPE_COMMENT
,
220 .setup
= comment_setup
,
221 .free
= comment_free
,
222 .content
= comment_content
,
223 .data
= HDATA_DISPLAY_NAME
,
224 .alloc_data
= comment_data
,
232 * Returns a pointer to handler_s if element (name/version) has a handler,
233 * or NULL if it doesn't.
235 handler_s
*find_handler(const char *name
, const char *syntax_version
)
239 for (i
= 0; i
< handlers
.cnt
; ++i
) {
240 handler_s
*h
= handlers
.list
[i
];
242 if (strcmp(name
, h
->info
->name
) == 0
243 && strcmp(syntax_version
, h
->info
->syntax_version
) == 0) {
251 static INLINE lt_ptr
lookup_symbol(lt_dlhandle handle
, const char *symbol_name
)
255 if ((result
= lt_dlsym(handle
, symbol_name
)) == NULL
)
256 Nprint_err("%s: %s", symbol_name
, lt_dlerror());
260 /* Creates new handler and puts it in handlers. */
261 static INLINE
void create_new_handler(handler_info_s
*hi
, lt_dlhandle handle
)
263 handler_s
*handler
= xmalloc(sizeof *handler
);
266 handler
->handle
= handle
;
268 /* Add to handlers. */
272 handlers
.list
= xrealloc(handlers
.list
,
273 (handlers
.cnt
) * sizeof *handlers
.list
);
275 handlers
.list
[handlers
.cnt
-1] = handler
;
278 /* Replaces an existing handler with a new one. */
279 static INLINE
void replace_handler(handler_s
*existing
, handler_info_s
*hi
,
283 existing
->handle
= handle
;
286 static int parse_handler_info(handler_info_s
* handler_info
,
291 for (i
= 0; (handler_info
[i
].name
); ++i
) {
292 handler_info_s
*hi
= &handler_info
[i
];
295 if ((found
= find_handler(hi
->name
, hi
->syntax_version
))) {
296 if (found
->info
->priority
>= hi
->priority
) {
297 Nprint_warn("The handler already exists, "
298 "skipping it: %s (%s)",
299 hi
->name
, hi
->syntax_version
);
301 Nprint("Replacing handler %s (%s) "
304 found
->info
->syntax_version
,
305 found
->info
->priority
);
306 Nprint("with %s (%s) priority %d",
310 replace_handler(found
, hi
, handle
);
314 create_new_handler(hi
, handle
);
320 static int load_handler(lt_dlhandle handle
, lt_ptr data
)
322 handler_info_s
*handler_info
;
326 handler_info
= (handler_info_s
*) lookup_symbol(handle
, "handler_info");
328 if (handler_info
== NULL
) {
332 return parse_handler_info(handler_info
, handle
);
336 static int foreachfile_callback(const char *filename
, lt_ptr data
)
342 if ((handle
= lt_dlopenext(filename
)) == NULL
) {
343 Nprint_err("%s", lt_dlerror());
349 int load_all_handlers(void)
352 LTDL_SET_PRELOADED_SYMBOLS();
355 if (lt_dlinit() != 0) {
356 Nprint_err("%s", lt_dlerror());
361 if (lt_dlopen_preloaded() != 0)
362 Nprint_err("unable to open all preloaded handlers");
364 Nprint("Loading handlers from %s.", HANDLERS_DIRECTORY
);
365 lt_dlforeachfile(HANDLERS_DIRECTORY
, &foreachfile_callback
, NULL
);
368 /* Load the embedded handlers first, then the loaded ones. */
369 (void) parse_handler_info(embedded_handlers_info
, NULL
);
371 lt_dlforeach(&load_handler
, NULL
);
376 unsigned int get_handler_count(void)
382 * Utility functions tied to handlers in some way.
385 char *alloc_package_name(element_s
*el
)
387 return el
->handler
->alloc_data(el
, HDATA_NAME
);
390 char *alloc_package_version(element_s
*el
)
392 return el
->handler
->alloc_data(el
, HDATA_VERSION
);
395 char *alloc_package_string(element_s
*el
)
398 char *name
= alloc_package_name(el
);
399 char *version
= alloc_package_version(el
);
402 if (name
&& version
) {
403 str
= xmalloc(strlen(name
) + strlen(version
) + 2);
404 sprintf(str
, "%s-%s", name
, version
);
413 int package_has_name_and_version(element_s
*el
)
416 char *name
= alloc_package_name(el
);
417 char *version
= alloc_package_version(el
);
420 if (name
&& version
) {
430 const char *find_handler_data(const element_s
* const element
,
431 const handler_data_e data_requested
)
436 for (s
= element
; s
; s
= s
->parent
) {
439 if ((s
->handler
->data
& data_requested
) == 0)
442 data
= s
->handler
->alloc_data(s
, data_requested
);
450 const char *alloc_base_dir(const element_s
* const element
)
452 return find_handler_data(element
->parent
, HDATA_BASE
);
455 int change_to_base_dir(const element_s
* const element
,
456 const char * const local_base
,
457 const int default_root
)
463 return change_current_dir(local_base
);
465 if ((dir
= alloc_base_dir(element
)) != NULL
) {
466 result
= change_current_dir(dir
);
472 return change_current_dir("/");
478 const char *alloc_stage_shell(const element_s
* const el
)
482 dir
= find_handler_data(el
->parent
, HDATA_SHELL
);
487 return xstrdup("sh");
490 int option_in_string(const char * const option
, const char * const string
)
495 tmp
= xstrdup(string
);
496 for (tok
= strtok(tmp
, WHITE_SPACE
); tok
; tok
= strtok(NULL
, WHITE_SPACE
)) {
497 if (strcmp(option
, tok
) == 0)
504 const struct handler_attribute
*find_handler_attribute(const handler_info_s
*handler
,
508 const struct handler_attribute
*attr
;
510 if (!handler
->attributes
)
513 for (i
= 0; (handler
->attributes
[i
].name
); ++i
) {
514 attr
= &handler
->attributes
[i
];
515 if (strcmp(attr
->name
, name
) == 0)
522 const struct handler_parameter
*find_handler_parameter(const handler_info_s
*handler
,
526 const struct handler_parameter
*param
;
528 if (!handler
->parameters
)
531 for (i
= 0; (handler
->parameters
[i
].name
); ++i
) {
532 param
= &handler
->parameters
[i
];
533 if (strcmp(param
->name
, name
) == 0)