Main Page | Modules | Data Structures | File List | Data Fields | Globals

conf.c

Go to the documentation of this file.
00001 
00012 /* $Progeny: conf.c 3839 2003-11-17 04:25:01Z dsp $
00013  *
00014  * Copyright 2002 Progeny Linux Systems, Inc.
00015  * Copyright 2002 Hewlett-Packard Company
00016  *
00017  * Permission is hereby granted, free of charge, to any person obtaining a
00018  * copy of this software and associated documentation files (the "Software"),
00019  * to deal in the Software without restriction, including without limitation
00020  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00021  * and/or sell copies of the Software, and to permit persons to whom the
00022  * Software is furnished to do so, subject to the following conditions:
00023  *
00024  * The above copyright notice and this permission notice shall be included in
00025  * all copies or substantial portions of the Software.
00026  *
00027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00030  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00031  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00032  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00033  * DEALINGS IN THE SOFTWARE.
00034  */
00035 
00036 #include <config.h>
00037 
00038 #include <assert.h>
00039 
00040 #include <expat.h>
00041 
00042 #include <discover.h>
00043 #include <discover-conf.h>
00044 #include <discover-xml.h>
00045 
00046 #include "load-url.h"
00047 #include "url-xml.h"
00048 #include "utils.h"
00049 
00050 /*Busmaps we understand
00051  */
00052 static discover_bus_map_t bus_map[] = {
00053     { "ata", 0, 0, NULL },
00054     { "pci", 0, 0, NULL },
00055     { "pcmcia", 0, 0, NULL },
00056     { "scsi", 0, 0, NULL },
00057     { "usb", 0, 0, NULL },
00058     { NULL }
00059 };
00060 
00061 static char * filetype_map[] = {
00062     "vendor", "busclass", "device"
00063 };
00064 
00065 static int conf_loaded = 0;
00066 
00067 static discover_xml_url_t *pre_urls = NULL;
00068 static discover_xml_url_t *post_urls = NULL;
00069 static discover_xml_url_t *urls = NULL;
00070 
00072 enum state { START, BUSSCAN, DATA_SOURCES };
00073 
00075 enum scan_flag { SCAN_NEVER, SCAN_DEFAULT };
00076 
00077 struct context {
00078     enum state state;
00079     enum scan_flag scan;
00080     discover_error_t *status;
00081 
00082     int unknown_level; 
00083 };
00084 
00085 static char *known_conf_elements[] = {
00086     "bus",
00087     "data-source",
00088     "busscan",
00089     "data-sources",
00090     "conffile",
00091     NULL
00092 };
00093 
00094 
00095 static bool
00096 unknown_conf_element(const XML_Char * const tag)
00097 {
00098     int i;
00099     for (i = 0; known_conf_elements[i] != NULL; i++) {
00100         if (strcmp(tag, known_conf_elements[i]) == 0)
00101             return false;
00102     }
00103     return true;
00104 }
00105 
00106 static enum scan_flag
00107 get_scan_flag(const XML_Char *attrs[])
00108 {
00109     int i;
00110     char *scan;
00111 
00112     assert(attrs != NULL);
00113 
00114     scan = NULL;
00115     for (i = 0; attrs[i]; i+= 2) {
00116         if (strcmp(attrs[i], "scan") == 0) {
00117             scan = (char *)attrs[i + 1];
00118         }
00119     }
00120 
00121     assert(scan != NULL);
00122 
00123     if (strcmp(scan, "default") == 0) {
00124         return SCAN_DEFAULT;
00125     } else {
00126         return SCAN_NEVER;
00127     }
00128 }
00129 
00135 discover_bus_map_t *
00136 _real_discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00137 {
00138     assert(status != NULL);
00139     assert(bus >= 0);
00140 
00141     if (bus >= BUS_COUNT) {
00142         status->code = DISCOVER_EBUSNOTFOUND;
00143     }
00144 
00145     return (discover_bus_map_t *)(bus_map + bus);
00146 }
00147 
00149 discover_bus_map_t *
00150 _real_discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00151 {
00152     discover_bus_t bus;
00153 
00154     assert(status != NULL);
00155 
00156     bus = discover_conf_name_to_bus(name, status);
00157 
00158     if (status->code != 0) {
00159         return NULL;
00160     }
00161 
00162     return _real_discover_conf_get_bus_map(bus, status);
00163 }
00164 
00165 static void
00166 _real_discover_conf_append_url(char *url, discover_error_t *status)
00167 {
00168     discover_xml_url_t *new;
00169 
00170     assert(url != NULL);
00171     assert(status != NULL);
00172 
00173     status->code = 0;
00174 
00175     new = discover_xml_url_new();
00176     new->url = _discover_xstrdup(url);
00177 
00178     if (post_urls) {
00179         if (post_urls->last) {
00180             post_urls->last->next = new;
00181         } else {
00182             post_urls->next = new;
00183         }
00184         post_urls->last = new;
00185     } else {
00186         post_urls = new;
00187         post_urls->next = NULL;
00188         post_urls->last = NULL;
00189     }
00190 }
00191 
00192 static void
00193 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00194 {
00195     struct context *context = ctx;
00196     discover_bus_map_t *busmap;
00197     discover_error_t *status;
00198     char *busname;
00199     int i;
00200 
00201     assert(context != NULL);
00202     assert(name != NULL);
00203 
00204     if (unknown_conf_element(name)) {
00205         context->unknown_level++;
00206         return;
00207     }
00208 
00209     if (context->unknown_level > 0) {
00210         return;
00211     }
00212 
00213     status = context->status;
00214 
00215     switch (context->state) {
00216     case START:
00217         if (strcmp(name, "busscan") == 0) {
00218             context->state = BUSSCAN;
00219             context->scan = get_scan_flag(attrs);
00220         } else if (strcmp(name, "data-sources") == 0) {
00221             context->state = DATA_SOURCES;
00222         }
00223         break;
00224 
00225     case BUSSCAN:
00226         if (strcmp(name, "bus") == 0) {
00227             assert(attrs != NULL);
00228 
00229             for (i = 0; attrs[i]; i += 2) {
00230                 if (strcmp(attrs[i], "name") == 0) {
00231                     busname = (char *)attrs[i + 1];
00232                     busmap = _real_discover_conf_get_bus_map_by_name(busname, status);
00233                     if (status->code != 0) {
00234                         return;
00235                     }
00236                     if (context->scan == SCAN_DEFAULT) {
00237                         busmap->scan_default = 1;
00238                     } else {
00239                         busmap->scan_never = 1;
00240                     }
00241                 }
00242             }
00243         }
00244         break;
00245 
00246     case DATA_SOURCES:
00247         if (strcmp(name, "data-source") == 0) {
00248             for (i = 0; attrs[i]; i += 2) {
00249                 if (strcmp(attrs[i], "url") == 0) {
00250                     _real_discover_conf_append_url((char *)attrs[i + 1],
00251                                                    status);
00252                     if (status->code != 0) {
00253                         return;
00254                     }
00255                 }
00256             }
00257         }
00258         break;
00259     }
00260 }
00261 
00262 static void
00263 end_element(void *ctx, const XML_Char *name)
00264 {
00265     struct context *context = ctx;
00266 
00267     assert(context != NULL);
00268     assert(name != NULL);
00269 
00270     if (unknown_conf_element(name)) {
00271         context->unknown_level--;
00272         return;
00273     }
00274 
00275     if (context->unknown_level > 0) {
00276         return;
00277     }
00278 
00279     switch (context->state) {
00280     case START:
00281     break;
00282 
00283     case BUSSCAN:
00284         if (strcmp(name, "busscan") == 0) {
00285             context->state = START;
00286         }
00287     break;
00288 
00289     case DATA_SOURCES:
00290         if (strcmp(name, "data-sources") == 0) {
00291             context->state = START;
00292         }
00293     break;
00294     }
00295 }
00296 
00318 void
00319 discover_conf_load(discover_error_t *status)
00320 {
00321     XML_Parser parser;
00322     struct context context;
00323     int load_url_status;
00324 
00325     assert(status != NULL);
00326 
00327     status->code = 0;
00328 
00329     if (conf_loaded) {
00330         return;
00331     }
00332 
00333     context.state = START;
00334     context.status = status;
00335     context.unknown_level = 0;
00336 
00337     parser = XML_ParserCreate(NULL);
00338     XML_SetElementHandler(parser, start_element, end_element);
00339     XML_SetUserData(parser, &context);
00340 
00341     load_url_status = _discover_load_url("file:///" SYSCONFDIR "/discover.conf",
00342                                          parser);
00343 
00344     /* start_element may change status. */
00345     if (status->code != 0) {
00346         char *message = _discover_xmalloc(256);
00347         snprintf(message, 256, "Error parsing configuration file %s",
00348                 "file:///" SYSCONFDIR "/discover.conf");
00349         status->create_message(&status, message);
00350         XML_ParserFree(parser);
00351         return;
00352     }
00353 
00354     /* Ignore URL load errors because the conf file is not mandatory. */
00355     if (!load_url_status) {
00356         char *message = _discover_xmalloc(256);
00357         snprintf(message, 256, "Failed loading configuration file %s",
00358                 "file:///" SYSCONFDIR "/discover.conf");
00359         status->create_message(&status, message);
00360         XML_ParserFree(parser);
00361         conf_loaded = 1;        /* See docstring. */
00362 
00363         return;
00364     }
00365 
00366     if (!XML_Parse(parser, "", 0, 1)) {
00367         char *message = _discover_xmalloc(256);
00368         snprintf(message, 256, "Error parsing configuration file %s",
00369                 "file:///" SYSCONFDIR "/discover.conf");
00370         status->create_message(&status, message);
00371         status->code = DISCOVER_EXML;
00372         XML_ParserFree(parser);
00373         return;
00374     }
00375 
00376     XML_ParserFree(parser);
00377 
00378     conf_loaded = 1;
00379 
00380     return;
00381 }
00382 
00389 int
00390 discover_conf_name_to_bus(char *name, discover_error_t *status)
00391 {
00392     int i;
00393     for (i = 0; bus_map[i].name; i++) {
00394         if (strcmp(bus_map[i].name, name) == 0) {
00395             return i;
00396         }
00397     }
00398 
00399     status->code = DISCOVER_EBUSNOTFOUND;
00400     return -1;
00401 }
00402 
00408 discover_bus_map_t *
00409 discover_conf_get_full_bus_map(discover_error_t *status)
00410 {
00411     discover_conf_load(status);
00412     return bus_map;
00413 }
00414 
00421 discover_bus_map_t *
00422 discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00423 {
00424     assert(status != NULL);
00425 
00426     discover_conf_load(status);
00427     if (status->code != 0) {
00428         return NULL;
00429     }
00430 
00431     /*
00432      * The "real" one won't call conf_load(), which will be useful
00433      * elsewhere.
00434      */
00435     return _real_discover_conf_get_bus_map_by_name(name, status);
00436 }
00437 
00444 discover_bus_map_t *
00445 discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00446 {
00447     assert(status != NULL);
00448     assert(bus >= 0);
00449 
00450     if (bus >= BUS_COUNT) {
00451         status->code = DISCOVER_EBUSNOTFOUND;
00452     }
00453 
00454     discover_conf_load(status);
00455     if (status->code != 0) {
00456         return NULL;
00457     }
00458 
00459     return (discover_bus_map_t *)(bus_map + bus);
00460 }
00461 
00469 void
00470 discover_conf_insert_url(char *url, discover_error_t *status)
00471 {
00472     discover_xml_url_t *new;
00473 
00474     assert(url != NULL);
00475     assert(status != NULL);
00476 
00477     status->code = 0;
00478 
00479     discover_conf_load(status);
00480     if (status->code != 0) {
00481         return;
00482     }
00483 
00484     new = discover_xml_url_new();
00485     new->url = _discover_xstrdup(url);
00486 
00487     new->next = pre_urls;
00488     if (pre_urls) {
00489         if (pre_urls->last) {
00490             new->last = pre_urls->last;
00491         } else {
00492             new->last = pre_urls;
00493         }
00494     } else {
00495         new->last = NULL;
00496     }
00497 
00498     pre_urls = new;
00499 }
00500 
00508 void
00509 discover_conf_append_url(char *url, discover_error_t *status)
00510 {
00511     assert(status != NULL);
00512 
00513     discover_conf_load(status);
00514     if (status->code != 0) {
00515         return;
00516     }
00517 
00518     _real_discover_conf_append_url(url, status);
00519 
00520     return;
00521 }
00522 
00528 discover_xml_url_t *
00529 discover_conf_get_urls(discover_error_t *status)
00530 {
00531     discover_xml_url_t *new;
00532 
00533     assert(status != NULL);
00534 
00535     status->code = 0;
00536 
00537     if (!urls) {
00538         discover_conf_load(status);
00539 
00540         new = discover_xml_url_new();
00541         new->url = _discover_xstrdup(DISCOVER_DEFAULT_URL);
00542 
00543         if (pre_urls) {
00544             urls = pre_urls;
00545             if (urls->last) {
00546                 urls->last->next = new;
00547             } else {
00548                 urls->next = new;
00549             }
00550             urls->last = new;
00551         } else {
00552             urls = new;
00553         }
00554 
00555         if (post_urls) {
00556             if (urls->last) {
00557                 urls->last->next = post_urls;
00558             } else {
00559                 urls->next = post_urls;
00560             }
00561 
00562             if (post_urls->last) {
00563                 urls->last = post_urls->last;
00564             } else {
00565                 urls->last = post_urls;
00566             }
00567         }
00568 
00569         post_urls = pre_urls = NULL;
00570     }
00571 
00572     return urls;
00573 }
00574 
00579 void
00580 discover_conf_free(void)
00581 {
00582     conf_loaded = 0;
00583 
00584     if (urls) {
00585         discover_xml_url_free(urls);
00586         urls = NULL;
00587     }
00588 }
00589 
00595 char *
00596 discover_conf_get_bus_name(discover_bus_t bus)
00597 {
00598     assert(bus >= 0);
00599     if (bus >= BUS_COUNT) {
00600         return NULL;
00601     }
00602 
00603     return bus_map[bus].name;
00604 }
00605 
00611 char *
00612 discover_conf_get_filetype_name(discover_filetype_t filetype)
00613 {
00614     if (filetype >= 3) {
00615         return NULL;
00616     }
00617 
00618     return filetype_map[filetype];
00619 }
00620 
00623 /*
00624  * Local variables:
00625  * c-file-style: "progeny"
00626  * indent-tabs-mode: nil
00627  * End:
00628  */
00629 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */

Generated on Sat Jan 31 14:39:17 2004 for discover by doxygen 1.3.4