Upgraded to follow CVS-20040525 - upgraded psmisc to 21.5
[automated_linux_from_scratch.git] / nALFS / src / handlers.c
blobc338fe9b30c0cc63af34491349d43f2c6921802d
1 /*
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
23 #include <sys/stat.h>
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include "parser.h"
30 #include "utility.h"
31 #include "win.h"
32 #include "nalfs-core.h"
33 #include "options.h"
35 #include "handlers.h"
36 #include "ltdl/ltdl.h"
39 static struct handlers {
40 int cnt;
41 handler_s **list;
42 } handlers = { 0, NULL };
44 /* Embedded "handlers" for the profile and comment elements. */
46 enum {
47 PROFILE_PATH
50 struct profile_data {
51 char *path;
54 static const struct handler_attribute profile_attributes[] = {
55 { .name = "path", .private = PROFILE_PATH },
56 { .name = NULL }
59 static int profile_setup(element_s * const element)
61 struct profile_data *data;
63 if ((data = xmalloc(sizeof(struct profile_data))) == NULL)
64 return 1;
66 data->path = NULL;
67 element->handler_data = data;
69 return 0;
72 static void profile_free(const element_s * const element)
74 struct profile_data *data = (struct profile_data *) element->handler_data;
76 xfree(data->path);
77 xfree(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) {
87 case PROFILE_PATH:
88 /* will never be called by parser more than once */
89 data->path = xstrdup(value);
90 return 0;
91 default:
92 return 1;
96 static int profile_valid_child(const element_s * const element,
97 const element_s * const child)
99 (void) element;
100 (void) child;
101 return 1;
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:
114 char *tmp;
116 /* display only the file name, not the whole path */
117 if ((tmp = strrchr(data->path, '/'))) {
118 return xstrdup(++tmp);
119 } else {
120 return xstrdup(data->path);
123 default:
124 break;
127 return NULL;
130 static int profile_main(const element_s * const el)
132 (void) el;
134 return 0;
137 struct comment_data {
138 char *content;
141 static int comment_setup(element_s * const element)
143 struct comment_data *data;
145 if ((data = xmalloc(sizeof(struct comment_data))) == NULL)
146 return 1;
148 data->content = NULL;
149 element->handler_data = data;
151 return 0;
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);
159 xfree(data);
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;
167 if (strlen(content))
168 data->content = xstrdup(content);
170 return 0;
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");
182 } else {
183 return xstrdup(data->content);
185 default:
186 break;
189 return NULL;
192 static int comment_main(const element_s * const el)
194 (void) el;
196 return 0;
199 static handler_info_s embedded_handlers_info[] = {
201 .name = "__profile",
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,
215 .name = "__comment",
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,
227 .name = NULL
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)
237 int i;
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) {
244 return h;
248 return NULL;
251 static INLINE lt_ptr lookup_symbol(lt_dlhandle handle, const char *symbol_name)
253 lt_ptr result;
255 if ((result = lt_dlsym(handle, symbol_name)) == NULL)
256 Nprint_err("%s: %s", symbol_name, lt_dlerror());
257 return result;
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);
265 handler->info = hi;
266 handler->handle = handle;
268 /* Add to handlers. */
270 ++handlers.cnt;
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,
280 lt_dlhandle handle)
282 existing->info = hi;
283 existing->handle = handle;
286 static int parse_handler_info(handler_info_s * handler_info,
287 lt_dlhandle handle)
289 int i;
291 for (i = 0; (handler_info[i].name); ++i) {
292 handler_info_s *hi = &handler_info[i];
293 handler_s *found;
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);
300 } else {
301 Nprint("Replacing handler %s (%s) "
302 "priority %d",
303 found->info->name,
304 found->info->syntax_version,
305 found->info->priority);
306 Nprint("with %s (%s) priority %d",
307 hi->name,
308 hi->syntax_version,
309 hi->priority);
310 replace_handler(found, hi, handle);
313 else
314 create_new_handler(hi, handle);
317 return 0;
320 static int load_handler(lt_dlhandle handle, lt_ptr data)
322 handler_info_s *handler_info;
324 (void) data;
326 handler_info = (handler_info_s *) lookup_symbol(handle, "handler_info");
328 if (handler_info == NULL) {
329 return 0;
332 return parse_handler_info(handler_info, handle);
335 #ifndef STATIC_BUILD
336 static int foreachfile_callback(const char *filename, lt_ptr data)
338 lt_dlhandle handle;
340 (void) data;
342 if ((handle = lt_dlopenext(filename)) == NULL) {
343 Nprint_err("%s", lt_dlerror());
345 return 0;
347 #endif
349 int load_all_handlers(void)
351 #ifdef STATIC_BUILD
352 LTDL_SET_PRELOADED_SYMBOLS();
353 #endif
355 if (lt_dlinit() != 0) {
356 Nprint_err("%s", lt_dlerror());
357 return -1;
360 #ifdef STATIC_BUILD
361 if (lt_dlopen_preloaded() != 0)
362 Nprint_err("unable to open all preloaded handlers");
363 #else
364 Nprint("Loading handlers from %s.", HANDLERS_DIRECTORY);
365 lt_dlforeachfile(HANDLERS_DIRECTORY, &foreachfile_callback, NULL);
366 #endif
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);
373 return 0;
376 unsigned int get_handler_count(void)
378 return handlers.cnt;
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)
397 char *str = NULL;
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);
407 xfree(name);
408 xfree(version);
410 return str;
413 int package_has_name_and_version(element_s *el)
415 int s = 0;
416 char *name = alloc_package_name(el);
417 char *version = alloc_package_version(el);
420 if (name && version) {
421 s = 1;
424 xfree(name);
425 xfree(version);
427 return s;
430 const char *find_handler_data(const element_s * const element,
431 const handler_data_e data_requested)
433 const element_s *s;
434 char *data;
436 for (s = element; s; s = s->parent) {
437 if (!s->handler)
438 continue;
439 if ((s->handler->data & data_requested) == 0)
440 continue;
442 data = s->handler->alloc_data(s, data_requested);
443 if (data)
444 return data;
447 return NULL;
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)
459 const char *dir;
460 int result;
462 if (local_base)
463 return change_current_dir(local_base);
465 if ((dir = alloc_base_dir(element)) != NULL) {
466 result = change_current_dir(dir);
467 xfree(dir);
468 return result;
471 if (default_root) {
472 return change_current_dir("/");
473 } else {
474 return -1;
478 const char *alloc_stage_shell(const element_s * const el)
480 const char *dir;
482 dir = find_handler_data(el->parent, HDATA_SHELL);
484 if (dir)
485 return dir;
487 return xstrdup("sh");
490 int option_in_string(const char * const option, const char * const string)
492 char *tmp;
493 const char *tok;
495 tmp = xstrdup(string);
496 for (tok = strtok(tmp, WHITE_SPACE); tok; tok = strtok(NULL, WHITE_SPACE)) {
497 if (strcmp(option, tok) == 0)
498 break;
500 xfree(tmp);
501 return tok ? 1 : 0;
504 const struct handler_attribute *find_handler_attribute(const handler_info_s *handler,
505 const char *name)
507 int i;
508 const struct handler_attribute *attr;
510 if (!handler->attributes)
511 return NULL;
513 for (i = 0; (handler->attributes[i].name); ++i) {
514 attr = &handler->attributes[i];
515 if (strcmp(attr->name, name) == 0)
516 return attr;
519 return NULL;
522 const struct handler_parameter *find_handler_parameter(const handler_info_s *handler,
523 const char *name)
525 int i;
526 const struct handler_parameter *param;
528 if (!handler->parameters)
529 return NULL;
531 for (i = 0; (handler->parameters[i].name); ++i) {
532 param = &handler->parameters[i];
533 if (strcmp(param->name, name) == 0)
534 return param;
537 return NULL;