]> Zhao Yanbai Git Server - minix.git/commitdiff
Add support in devmand for using config dirs.
authorKees Jongenburger <kees.jongenburger@gmail.com>
Mon, 4 Jun 2012 09:34:04 +0000 (09:34 +0000)
committerKees Jongenburger <kees.jongenburger@gmail.com>
Mon, 18 Jun 2012 07:29:53 +0000 (09:29 +0200)
Add support in devmand for using configuration directories to
allow 3rd party packages to add configuration items.

commands/devmand/main.c
servers/devman/device.c

index baa24a68d2d1f5f4ba630bebe550a2c955b9bb6f..6359cd03e28547adf30314b60f37054f6b126ef9 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <lib.h>
 #include <sys/stat.h>
+#include <dirent.h>
 #include <assert.h>
 #include <signal.h>
 #include "usb_driver.h"
@@ -17,6 +18,7 @@
 #define DEVMAN_TYPE_NAME "dev_type"
 #define PATH_LEN 256
 #define INVAL_MAJOR -1
+#define MAX_CONFIG_DIRS 4
 
 static void main_loop();
 static void handle_event();
@@ -42,11 +44,12 @@ static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
 
 static int _run = 1;
 struct global_args {
-       int deamonize;
        char *path;
-       char *config;
+       char *config_dirs[MAX_CONFIG_DIRS];
+       int config_dir_count ;
        int major_offset;
        int verbose;
+       int check_config;
 };
 
 enum dev_type {
@@ -57,14 +60,20 @@ enum dev_type {
 
 extern FILE *yyin;
 
-static struct global_args args = {0,NULL,NULL,25, 0};
+static struct global_args args = {
+       .path = NULL,
+       .config_dirs = {NULL,NULL,NULL,NULL},
+       .config_dir_count = 0,
+       .major_offset = 25, 
+       .verbose = 0,
+       .check_config = 0};
 
 static struct option options[] =
 {
-       {"deamonize", no_argument,       NULL, 'd'},
+       {"dir"   ,    required_argument, NULL, 'd'},
        {"path",      required_argument, NULL, 'p'},
-       {"config",    required_argument, NULL, 'c'},
        {"verbose",    required_argument, NULL, 'v'},
+       {"check-config", no_argument,       NULL, 'x'},
        {0,0,0,0} /* terminating entry */
 };
 
@@ -303,16 +312,72 @@ add_usb_match_id
  *===========================================================================*/
 static void parse_config()
 {
-       yyin = fopen(args.config, "r");
+       int i, status, error;
+       struct stat stats;
+       char * dirname;
+
+       DIR * dir;
+       struct dirent entry;
+       struct dirent *result;
+       char config_file[PATH_MAX];
+
+       dbg("Parsing configuration directories... ");
+       /* Next parse the configuration directories */
+       for(i=0; i < args.config_dir_count; i++){
+               dirname = args.config_dirs[i];
+               dbg("Parsing config dir %s ", dirname);
+               status = stat(dirname,&stats);
+               if (status == -1){
+                       error = errno;
+                       fprintf(stderr,"Failed to read directory '%s':%s"
+                               " (skipping) \n", dirname,strerror(error));
+                       continue;
+               }
+               if (!S_ISDIR(stats.st_mode)){
+                       fprintf(stderr,"Parse configuration skipping %s" 
+                               " (not a directory) \n",dirname);
+                       continue;
+               }
+               dir = opendir(dirname);
+               if (dir == NULL){
+                       error = errno;
+                       fprintf(stderr,"Parse configuration failed to read" 
+                               " dir '%s' (skipping) :%s\n",dirname, 
+                               strerror(error));
+                       continue;
+               }
+               while( (status = readdir_r(dir,&entry,&result)) == 0 ){
+                       if (result == NULL){ /* last entry */ 
+                               closedir(dir);
+                               break;
+                       }
 
-       if (yyin < 0) {
-               printf("Can not open config file: %d.\n", errno);
+                       /* concatenate dir and file name to open it */
+                       snprintf(config_file,PATH_MAX, "%s/%s",
+                                dirname,entry.d_name);
+                       status = stat(config_file, &stats);
+                       if (status == -1){ 
+                               error = errno;
+                               fprintf(stderr,"Parse configuration Failed to stat" 
+                                       " file '%s': %s (skipping)\n",
+                                             config_file,strerror(error));
+                       }
+                       if (S_ISREG(stats.st_mode)){
+                               dbg("Parsing file %s",config_file);
+                               yyin = fopen(config_file, "r");
+
+                               if (yyin < 0) {
+                                       printf("Can not open config file:" 
+                                              " %d.\n", errno);
+                               }
+                               yyparse();
+                               dbg("Done.");
+                               fclose(yyin);
+                       }
+               }
        }
-       dbg("Parsing configfile... ");
-       yyparse();
-       dbg("Done.");
+       dbg("Parsing configuration directories done... ");
 
-       fclose(yyin);
 }
 
 /*===========================================================================*
@@ -369,44 +434,60 @@ int main(int argc, char *argv[])
        int opt, optindex, res;
        struct devmand_usb_driver *driver;
 
-       create_pid_file();
 
        /* get command line arguments */
-       while ((opt = getopt_long(argc, argv, "vdc:p:h?", options, &optindex))
+       while ((opt = getopt_long(argc, argv, "d:p:vxh?", options, &optindex))
                        != -1) {
                switch (opt) {
-                       case 'd':
-                               args.deamonize = 1;
+                       case 'd':/* config directory */
+                               if (args.config_dir_count >= MAX_CONFIG_DIRS){
+                                       fprintf(stderr,"Parse arguments: Maximum" 
+                                               " of %i configuration directories"
+                                               " reached skipping directory '%s'\n" 
+                                               , MAX_CONFIG_DIRS, optarg);
+                                       break;
+                               }
+                               args.config_dirs[args.config_dir_count] = optarg;
+                               args.config_dir_count++;
                                break;
-                       case 'p':
+                       case 'p': /* sysfs path */
                                args.path = optarg;
                                break;
-                       case 'c':
-                               args.config = optarg;
-                               break;
-                       case 'v':
+                       case 'v': /* verbose */
                                args.verbose = 1;
                                break;
-                       case 'h':
-                       case '?':
+                       case 'x': /* check config */
+                               args.check_config = 1;
+                               break;
+                       case 'h': /* help */
+                       case '?': /* help */
                        default:
                                display_usage(argv[0]);
                                return 0;
                }
        }
 
+
        /* is path set? */
        if (args.path == NULL) {
                args.path = "/sys/";
        }
 
-       /* is path set? */
-       if (args.config == NULL) {
-               args.config = "/etc/devmand/devmand.cfg";
+       /* is the configuration directory set? */
+       if (args.config_dir_count == 0) {
+               dbg("Using default configuration directory");
+               args.config_dirs[0] = "/etc/devmand";
+               args.config_dir_count = 1;
+       }
+
+       /* If we only check the configuration run and exit imediately */
+       if (args.check_config == 1){
+               fprintf(stdout, "Only parsing configuration\n");
+               parse_config();
+               exit(0);
        }
 
-       dbg("Options:  deamonize: %s,  path: %s",
-          args.deamonize?"true":"false", args.path);
+       create_pid_file();
 
        /* create control socket if not exists */
        res = mkfifo(CONTROL_FIFO_PATH, S_IWRITE);
@@ -421,7 +502,7 @@ int main(int argc, char *argv[])
                run_cleanscript(driver);
        }
 
-    signal(SIGINT, sig_int);
+       signal(SIGINT, sig_int);
 
        main_loop();
 
@@ -841,7 +922,8 @@ static void main_loop()
  *===========================================================================*/
 static void display_usage(const char *name)
 {
-       printf("Usage: %s [-d|--deamonize] [{-p|--pathname} PATH_TO_SYS}"
-              " [{-c|--config} CONFIG_FILE]\n", name);
+       printf("Usage: %s [{-p|--pathname} PATH_TO_SYS}"
+              " [{-d|--config-dir} CONFIG_DIR] [-v|--verbose]" 
+              " [[x||--check-config]\n", name);
 }
 
index 6f9b525eeb7d2db26212338aa8cd3e4be0043b72..37cb5c238273912d671fff254daa67f89e974a74 100644 (file)
@@ -86,7 +86,7 @@ devman_device_add_event(struct devman_device* dev)
 
        memset(event, 0, sizeof(*event));
 
-       strcat(event->data, ADD_STRING);
+       strncpy(event->data, ADD_STRING, DEVMAN_STRING_LEN - 1);
 
        res = devman_generate_path(event->data, DEVMAN_STRING_LEN - 11 , dev);
                
@@ -119,7 +119,7 @@ devman_device_remove_event(struct devman_device* dev)
 
        memset(event, 0, sizeof(*event));
 
-       strcat(event->data, REMOVE_STRING);
+       strncpy(event->data, REMOVE_STRING, DEVMAN_STRING_LEN - 1);
 
        res = devman_generate_path(event->data, DEVMAN_STRING_LEN-11, dev);
        
@@ -262,7 +262,6 @@ int do_add_device(message *msg)
        }
 
        dev = devman_dev_add_child(parent, devinf);
-       dev->state = DEVMAN_DEVICE_UNBOUND;
 
        if (dev == NULL) {
                res = ENODEV;
@@ -270,6 +269,8 @@ int do_add_device(message *msg)
                do_reply(msg, res);
                return 0;
        }
+
+       dev->state = DEVMAN_DEVICE_UNBOUND;
        
        dev->owner = msg->m_source;
 
@@ -355,10 +356,16 @@ devman_dev_add_child
        char * buffer = (char *) (devinf);
        char tmp_buf[128];
        struct devman_device_info_entry *entries;
+
        /* create device */
        struct devman_device * dev = malloc(sizeof(struct devman_device));
+       if (dev == NULL) {
+               panic("devman_dev_add_child: out of memory\n");
+       }
+
 
        if (parent == NULL) {
+               free(dev);
                return NULL;
        }