Changeset 55c564a in rtems-libbsd


Ignore:
Timestamp:
Jun 27, 2016, 3:24:43 AM (3 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
c1e05b9ea378b2971e3d7704779112b4bc4296da, freebsd-9.3, e6acc15bc94ea35f40e50b42692584c456ba9722
Children:
7439724
Parents:
c6713d1
git-author:
Chris Johns <chrisj@…> (06/27/16 03:24:43)
git-committer:
Chris Johns <chrisj@…> (06/27/16 03:32:24)
Message:

Refactor rc.conf processing to be services based.

Files:
1 added
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • rtemsbsd/include/machine/rtems-bsd-rc-conf.h

    rc6713d1 r55c564a  
    2525
    2626/*
    27  * Parse a FreeBSD /etc/rc.conf format file and execute the configuration
    28  * options we want to support.
     27 * FreeBSD /etc/rc.conf initialisation. Initialise the software stack using the
     28 * the configuration options held in your rc.conf file. The file conforms to the
     29 * format defined in the FreeBSD man page rc.conf(5).
     30 *
     31 * The services and configuration present in your rc.conf will only work if the
     32 * services have been configured into your application.
    2933 */
    3034
    31 #ifndef _RTEMS_BSP_RC_CONF_h
    32 #define _RTEMS_BSP_RC_CONF_h
     35#ifndef _RTEMS_BSD_RC_CONF_h
     36#define _RTEMS_BSD_RC_CONF_h
    3337
    3438#include <stdbool.h>
     
    4448
    4549/*
    46  * Directive processing data. This data is opaque externally.
     50 * The rc.conf  data. It is externally opaque.
    4751 */
    4852typedef struct rtems_bsd_rc_conf_ rtems_bsd_rc_conf;
    4953
    5054/*
    51  * A directive is a line in rc.conf and is 'name=value'. The handler is invoked
    52  * if the name matches directive's regular expression.
     55 * Run an rc.conf script loaded into memory.
     56 *
     57 * The timeout can be -1 for no wait, 0 to wait forever or a timeout in seconds.
    5358 */
    54 typedef int (*rtems_bsd_rc_conf_directive)(rtems_bsd_rc_conf* rc_conf,
    55                                            int                argc,
    56                                            const char**       argv);
    57 
    58 /*
    59  * Register a directive handler.
    60  */
    61 extern int rtems_bsd_rc_conf_directive_add(const char*  dir_regex,
    62                                            rtems_bsd_rc_conf_directive handler);
    63 
    64 /*
    65  * Run an rc.conf script loaded into memory.
    66  */
    67 extern int rtems_bsd_run_rc_conf_script(const char* name, const char* text, bool verbose);
     59extern int rtems_bsd_run_rc_conf_script(const char* name,
     60                                        const char* text,
     61                                        int         timeout,
     62                                        bool        verbose);
    6863
    6964/*
    7065 * Run the rc.conf file.
     66 *
     67 * The timeout can be -1 for no wait, 0 to wait forever or a timeout in seconds.
    7168 */
    72 extern int rtems_bsd_run_rc_conf(const char* name, bool verbose);
     69extern int rtems_bsd_run_rc_conf(const char* name, int timeout, bool verbose);
    7370
    7471/*
    7572 * Run /etc/rc.conf.
     73 *
     74 * The timeout can be -1 for no wait, 0 to wait forever or a timeout in seconds.
    7675 */
    77 extern int rtems_bsd_run_etc_rc_conf(bool verbose);
    78 
    79 /*
    80  * Return the name of the file being processed.
    81  */
    82 extern const char* rtems_bsd_rc_conf_name(rtems_bsd_rc_conf* rc_conf);
    83 
    84 /*
    85  * Return the line number being processed.
    86  */
    87 extern int rtems_bsd_rc_conf_line(rtems_bsd_rc_conf* rc_conf);
    88 
    89 /*
    90  * Print the argv list. Helper for verbose modes.
    91  */
    92 extern void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf,
    93                                         const char*        name,
    94                                         int                argc,
    95                                         const char**       argv);
     76extern int rtems_bsd_run_etc_rc_conf(int timeout, bool verbose);
    9677
    9778#ifdef __cplusplus
  • rtemsbsd/rtems/rtems-bsd-rc-conf-net.c

    rc6713d1 r55c564a  
    3939#include <sysexits.h>
    4040
     41#include <ifaddrs.h>
     42
    4143#include <errno.h>
    4244#include <stddef.h>
     
    4951
    5052#include <machine/rtems-bsd-commands.h>
    51 #include <machine/rtems-bsd-rc-conf.h>
     53#include <machine/rtems-bsd-rc-conf-services.h>
     54
     55/*
     56 * Default defaultroute_delay is 30seconds.
     57 */
     58static int defaultroute_delay_secs = 30;
     59
     60/*
     61 * Show a result.
     62 */
     63static void
     64show_result(const char* label, int r)
     65{
     66  if (r < 0)
     67    fprintf(stderr, "error: %s: %s\n", label, strerror(errno));
     68}
    5269
    5370/*
     
    5976 */
    6077static int
    61 cloned_interfaces(rtems_bsd_rc_conf* rc_conf,
    62                   int                argc,
    63                   const char**       argv)
     78cloned_interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
    6479{
    6580  int arg;
    66   for (arg = 1; arg < argc; ++arg) {
     81  int r = 0;
     82
     83  r = rtems_bsd_rc_conf_find(rc_conf, "cloned_interfaces", aa);
     84  if (r < 0) {
     85    if (errno == ENOENT)
     86      r = 0;
     87    return r;
     88  }
     89
     90  for (arg = 1; arg < aa->argc; ++arg) {
    6791    const char* ifconfg_args[] = {
    68       "ifconfig", argv[arg], "create", NULL
     92      "ifconfig", aa->argv[arg], "create", NULL
    6993    };
    70     int r;
    7194    rtems_bsd_rc_conf_print_cmd(rc_conf, "cloning_interfaces", 3, ifconfg_args);
    72     r = rtems_bsd_command_ifconfig(3, (char**) ifconfg_args);
    73     if (r != EX_OK) {
    74       errno = ECANCELED;
    75       return -1;
    76     }
    77   }
     95    rtems_bsd_command_ifconfig(3, (char**) ifconfg_args);
     96  }
     97
    7898  return 0;
    7999}
     
    96116
    97117static int
    98 create_args_(rtems_bsd_rc_conf* rc_conf,
    99              int                argc,
    100              const char**       argv)
    101 {
    102   rtems_chain_node*       node = rtems_chain_first(&create_args_items);
    103   const rtems_chain_node* tail = rtems_chain_tail(&create_args_items);
    104   const char*             label = argv[0] + strlen("create_args_");
    105   create_args_item*       item;
    106   int                     arg;
    107 
    108   while (node != tail) {
    109     item = (create_args_item*) node;
    110     if (strcasecmp(item->label, label) == 0) {
    111       fprintf(stderr, "error: %s:%d: duplicate create args entry: %s\n",
     118load_create_args(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
     119{
     120  int r = 0;
     121
     122  r = rtems_bsd_rc_conf_find(rc_conf, "create_args_.*", aa);
     123
     124  while (r == 0) {
     125    rtems_chain_node* node;
     126    const char*       label;
     127    create_args_item* item;
     128    int               arg;
     129
     130    rtems_bsd_rc_conf_print_cmd(rc_conf, "create_args_", aa->argc, aa->argv);
     131
     132    label = aa->argv[0] + strlen("create_args_");
     133
     134    node = rtems_chain_first(&create_args_items);
     135
     136    while (!rtems_chain_is_tail(&create_args_items, node)) {
     137      item = (create_args_item*) node;
     138      if (strcasecmp(item->label, label) == 0) {
     139        fprintf(stderr, "error: %s:%d: duplicate create args entry: %s\n",
     140                rtems_bsd_rc_conf_name(rc_conf),
     141                rtems_bsd_rc_conf_line(rc_conf),
     142                aa->argv[0]);
     143        errno = EEXIST;
     144        return -1;
     145      }
     146      node = rtems_chain_next(node);
     147    }
     148
     149    item = calloc(1, sizeof(*item));
     150    if (item == NULL) {
     151      errno = ENOMEM;
     152      fprintf(stderr, "error: %s:%d: %s\n",
    112153              rtems_bsd_rc_conf_name(rc_conf),
    113154              rtems_bsd_rc_conf_line(rc_conf),
    114               argv[0]);
    115       errno = EEXIST;
     155              strerror(errno));
    116156      return -1;
    117157    }
    118     node = rtems_chain_next(node);
    119   }
    120 
    121   item = calloc(1, sizeof(*item));
    122   if (item == NULL) {
    123     errno = ENOMEM;
    124     fprintf(stderr, "error: %s:%d: %s\n",
    125             rtems_bsd_rc_conf_name(rc_conf),
    126             rtems_bsd_rc_conf_line(rc_conf),
    127             strerror(errno));
    128     return -1;
    129   }
    130 
    131   item->argc = argc;
    132 
    133   item->label = strdup(label);
    134   if (item->label == NULL) {
    135     free(item);
    136     errno = ENOMEM;
    137     fprintf(stderr, "error: %s:%d: %s\n",
    138             rtems_bsd_rc_conf_name(rc_conf),
    139             rtems_bsd_rc_conf_line(rc_conf),
    140             strerror(errno));
    141     return -1;
    142   }
    143 
    144   item->argv = calloc(argc + 1, sizeof(char*));
    145   if (item->argv == NULL) {
    146     free((void*) item->label);
    147     free(item);
    148     errno = ENOMEM;
    149     fprintf(stderr, "error: %s:%d: %s\n",
    150             rtems_bsd_rc_conf_name(rc_conf),
    151             rtems_bsd_rc_conf_line(rc_conf),
    152             strerror(errno));
    153     return -1;
    154   }
    155 
    156   for (arg = 0; arg < argc; ++arg) {
    157     item->argv[arg] = strdup(argv[0]);
    158     if (item->argv[arg] == NULL) {
    159       int a;
    160       for (a = 0; a < arg; ++a)
    161         free((void*) item->argv[a]);
    162       free(item->argv);
     158
     159    item->argc = aa->argc;
     160
     161    item->label = strdup(label);
     162    if (item->label == NULL) {
     163      free(item);
     164      errno = ENOMEM;
     165      fprintf(stderr, "error: %s:%d: %s\n",
     166              rtems_bsd_rc_conf_name(rc_conf),
     167              rtems_bsd_rc_conf_line(rc_conf),
     168              strerror(errno));
     169      return -1;
     170    }
     171
     172    item->argv = calloc(aa->argc + 1, sizeof(char*));
     173    if (item->argv == NULL) {
    163174      free((void*) item->label);
    164175      free(item);
     
    170181      return -1;
    171182    }
    172   }
    173 
    174   rtems_chain_append(&create_args_items, &item->node);
     183
     184    for (arg = 0; arg < aa->argc; ++arg) {
     185      item->argv[arg] = strdup(aa->argv[0]);
     186      if (item->argv[arg] == NULL) {
     187        int a;
     188        for (a = 0; a < arg; ++a)
     189          free((void*) item->argv[a]);
     190        free(item->argv);
     191        free((void*) item->label);
     192        free(item);
     193        errno = ENOMEM;
     194        fprintf(stderr, "error: %s:%d: %s\n",
     195                rtems_bsd_rc_conf_name(rc_conf),
     196                rtems_bsd_rc_conf_line(rc_conf),
     197                strerror(errno));
     198        return -1;
     199      }
     200    }
     201
     202    rtems_chain_append(&create_args_items, &item->node);
     203
     204    r = rtems_bsd_rc_conf_find_next(rc_conf, aa);
     205  }
     206
     207  /*
     208   * ignore not found.
     209   */
     210  if (r < 0 && errno == ENOENT)
     211    r = 0;
    175212
    176213  return 0;
     
    186223static int
    187224ifconfig_(rtems_bsd_rc_conf* rc_conf,
     225          const char*        ifname,
    188226          int                argc,
    189227          const char**       argv)
    190228{
    191   const char** args;
    192   int          arg;
    193   int          r;
     229  const char**      args;
     230  int               arg;
     231  int               r;
     232  const char const* ifconfig_show[] = { "ifconfig", ifname, NULL };
    194233
    195234  for (arg = 1; arg < argc; ++arg) {
     
    205244
    206245  args[0] = "ifconfig";
    207   args[1] = argv[0] + strlen("ifconfig_");
     246  args[1] = ifname;
    208247
    209248  for (arg = 1; arg < argc; ++arg)
     
    223262  }
    224263
    225   return 0;
     264  r = rtems_bsd_command_ifconfig(2, (char**) ifconfig_show);
     265
     266  return r;
    226267}
    227268
     
    234275 */
    235276static int
    236 hostname(rtems_bsd_rc_conf* rc_conf,
    237          int                argc,
    238          const char**       argv)
    239 {
    240   if (argc > 2) {
     277hostname(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
     278{
     279  const char**      argv;
     280  int               r;
     281  const char const* default_argv[] = { "hostname", "Amnesiac", NULL };
     282
     283  r = rtems_bsd_rc_conf_find(rc_conf, "hostname", aa);
     284  if (r < 0 && errno != ENOENT)
     285    return -1;
     286
     287  if (r < 0 || (r == 0 && aa->argc != 2)) {
     288    argv = default_argv;
     289  }
     290  else {
     291    argv = aa->argv;
     292  }
     293
     294  fprintf(stdout, "Setting hostname: %s.\n", argv[1]);
     295
     296  return sethostname(argv[1], strlen(argv[1]));
     297}
     298
     299/*
     300 * defaultrouter
     301 *
     302 * eg defaultrouter="1.2.3.4"
     303 *
     304 * See 'man rc.conf(5)' on FreeBSD.
     305 */
     306static int
     307defaultrouter(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
     308{
     309  int r;
     310
     311  r = rtems_bsd_rc_conf_find(rc_conf, "defaultrouter", aa);
     312  if (r < 0 && errno != ENOENT)
     313    return -1;
     314
     315  if (r == 0) {
     316    if (aa->argc > 2) {
     317      errno = EINVAL;
     318      return -1;
     319    }
     320
     321    if (strcasecmp(aa->argv[1], "NO") != 0) {
     322      const char* args[] = { "route", "add", "default", aa->argv[1], NULL };
     323      int         r;
     324
     325      rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 4, args);
     326
     327      r = rtems_bsd_command_route(4, (char**) args);
     328      if (r != EX_OK) {
     329        errno = ECANCELED;
     330        return -1;
     331      }
     332    }
     333  }
     334
     335  return 0;
     336}
     337
     338/*
     339 * defaultroute_delay
     340 *
     341 * eg defaultroute=120
     342 *
     343 * See 'man rc.conf(5)' on FreeBSD.
     344 */
     345static int
     346defaultroute_delay(rtems_bsd_rc_conf* rc_conf,
     347                   int                argc,
     348                   const char**       argv)
     349{
     350  int   value;
     351  char* end = NULL;
     352
     353  if (argc != 2) {
    241354    errno = EINVAL;
    242355    return -1;
    243356  }
    244357
    245   rtems_bsd_rc_conf_print_cmd(rc_conf, "hostname", argc, argv);
    246 
    247   return sethostname(argv[1], strlen(argv[1]));
    248 }
    249 
    250 /*
    251  * defaultrouter
    252  *
    253  * eg defaultrouter="1.2.3.4"
    254  *
    255  * See 'man rc.conf(5)' on FreeBSD.
    256  */
    257 static int
    258 defaultrouter(rtems_bsd_rc_conf* rc_conf,
    259               int                argc,
    260               const char**       argv)
    261 {
    262   if (argc > 2) {
     358  value = strtol(argv[1], &end, 10);
     359
     360  if (end == NULL) {
     361      const char* args[] = {
     362        "defaultrouter_delay", argv[1], NULL
     363    };
     364
     365    rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 2, args);
     366
     367    defaultroute_delay_secs = value;
     368  }
     369  else {
    263370    errno = EINVAL;
    264371    return -1;
    265372  }
    266373
    267   if (strcasecmp(argv[1], "NO") != 0) {
    268     const char* args[] = {
    269       "route", "add", "default", argv[1], NULL
    270     };
    271     int r;
    272 
    273     rtems_bsd_rc_conf_print_cmd(rc_conf, "defaultrouter", 4, args);
    274 
    275     r = rtems_bsd_command_route(4, (char**) args);
    276     if (r != EX_OK) {
    277       errno = ECANCELED;
    278       return -1;
    279     }
    280   }
    281 
    282   return 0;
    283 }
    284 
    285 static void
    286 add_directive(const char* name, rtems_bsd_rc_conf_directive handler)
    287 {
    288   int r;
    289   r = rtems_bsd_rc_conf_directive_add(name, handler);
    290   if (r < 0)
    291     fprintf(stderr, "error: cannot register rc.conf handler: %s\n", name);
     374  return 0;
     375}
     376
     377static int
     378show_interfaces(const char* msg, struct ifaddrs* ifap)
     379{
     380  struct ifaddrs* ifa;
     381
     382  fprintf(stdout, msg);
     383
     384  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     385    if (strcasecmp("lo0", ifa->ifa_name) == 0) {
     386      fprintf(stdout, "%s ", ifa->ifa_name);
     387      break;
     388    }
     389  }
     390
     391  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     392    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
     393      fprintf(stdout, "%s ", ifa->ifa_name);
     394    }
     395  }
     396
     397  fprintf(stdout, "\b.\n");
     398
     399  return 0;
     400}
     401
     402static int
     403setup_lo0(rtems_bsd_rc_conf* rc_conf, struct ifaddrs* ifap)
     404{
     405  struct ifaddrs* ifa;
     406  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     407    if (strcasecmp("lo0", ifa->ifa_name) == 0) {
     408      const char* lo0_argv[] = {
     409        "ifconfig_lo0", "inet", "127.0.0.1", "netmask", "255.0.0.0", NULL
     410      };
     411      show_result("lo0", ifconfig_(rc_conf, "lo0", 5, lo0_argv));
     412      return 0;
     413    }
     414  }
     415  fprintf(stderr, "warning: no loopback interface found\n");
     416  return -1;
     417}
     418
     419static int
     420setup_interfaces(rtems_bsd_rc_conf*           rc_conf,
     421                 rtems_bsd_rc_conf_argc_argv* aa,
     422                 struct ifaddrs*              ifap)
     423{
     424  struct ifaddrs* ifa;
     425  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     426    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
     427      char iface[64];
     428      int  r;
     429      snprintf(iface, sizeof(iface), "ifconfig_%s", ifa->ifa_name);
     430      r = rtems_bsd_rc_conf_find(rc_conf, iface, aa);
     431      if (r == 0) {
     432        show_result(iface, ifconfig_(rc_conf, ifa->ifa_name, aa->argc, aa->argv));
     433      }
     434    }
     435  }
     436  return 0;
     437}
     438
     439static int
     440setup_vlans(rtems_bsd_rc_conf*           rc_conf,
     441            rtems_bsd_rc_conf_argc_argv* aa,
     442            struct ifaddrs*              ifap)
     443{
     444  rtems_bsd_rc_conf_argc_argv* vaa;
     445  struct ifaddrs*              ifa;
     446
     447  vaa = rtems_bsd_rc_conf_argc_argv_create();
     448  if (vaa == NULL)
     449    return -1;
     450
     451  show_result("create_args", load_create_args(rc_conf, aa));
     452
     453  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     454    if (strcasecmp("lo0", ifa->ifa_name) != 0) {
     455      char expr[128];
     456      int  r;
     457      /*
     458       * Look for vlans_'iface'="101 102 103"
     459       */
     460      snprintf(expr, sizeof(expr), "vlans_%s", ifa->ifa_name);
     461      r = rtems_bsd_rc_conf_find(rc_conf, expr, aa);
     462      if (r == 0) {
     463        int arg;
     464        for (arg = 1; arg < aa->argc; ++arg) {
     465          char vlan_name[64];
     466          const char* vlan_create[] = {
     467            "ifconfig", vlan_name, "create", NULL
     468          };
     469          /*
     470           * Create the VLAN name as 'iface'.'vlan'.
     471           */
     472          snprintf(vlan_name, sizeof(vlan_name),
     473                   "%s.%s", ifa->ifa_name, aa->argv[arg]);
     474          rtems_bsd_rc_conf_print_cmd(rc_conf, "vlan", 3, vlan_create);
     475          r = rtems_bsd_command_ifconfig(3, (char**) vlan_create);
     476          if (r == 0) {
     477            /*
     478             * Look for ifconfig_'iface'_'vlan'="..."
     479             */
     480            snprintf(expr, sizeof(expr),
     481                     "ifconfig_%s_%s", ifa->ifa_name, aa->argv[arg]);
     482            r = rtems_bsd_rc_conf_find(rc_conf, expr, vaa);
     483            if (r == 0) {
     484              show_result(vlan_name, ifconfig_(rc_conf, vlan_name,
     485                                               vaa->argc, vaa->argv));
     486            }
     487          }
     488        }
     489      }
     490    }
     491  }
     492
     493  rtems_bsd_rc_conf_argc_argv_destroy(vaa);
     494
     495  return 0;
     496}
     497
     498static int
     499interfaces(rtems_bsd_rc_conf* rc_conf, rtems_bsd_rc_conf_argc_argv* aa)
     500{
     501  struct ifaddrs* ifap;
     502
     503  if (getifaddrs(&ifap) != 0) {
     504    fprintf(stderr, "error: interfaces: getifaddrs: %s\n", strerror(errno));
     505    return -1;
     506  }
     507
     508  show_interfaces("Starting network: ", ifap);
     509  show_result("cloned_interfaces", cloned_interfaces(rc_conf, aa));
     510  show_result("lo0", setup_lo0(rc_conf, ifap));
     511  show_result("ifaces", setup_interfaces(rc_conf, aa, ifap));
     512  show_result("vlans", setup_vlans(rc_conf, aa, ifap));
     513
     514  free(ifap);
     515
     516  return 0;
     517}
     518
     519static int
     520network_service(rtems_bsd_rc_conf* rc_conf)
     521{
     522  rtems_bsd_rc_conf_argc_argv* aa;
     523  int                          r;
     524
     525  aa = rtems_bsd_rc_conf_argc_argv_create();
     526  if (aa == NULL)
     527    return -1;
     528
     529  show_result("hostname",    hostname(rc_conf, aa));
     530
     531  r = interfaces(rc_conf, aa);
     532  if (r < 0) {
     533    rtems_bsd_rc_conf_argc_argv_destroy(aa);
     534    return -1;
     535  }
     536
     537  show_result("defaultrouter", defaultrouter(rc_conf, aa));
     538
     539  rtems_bsd_rc_conf_argc_argv_destroy(aa);
     540
     541  return 0;
    292542}
    293543
     
    295545rc_conf_net_init(void* arg)
    296546{
    297   add_directive("cloned_interfaces", cloned_interfaces);
    298   add_directive("create_args_.*", create_args_);
    299   add_directive("ifconfig_.*", ifconfig_);
    300   add_directive("hostname", hostname);
    301   add_directive("defaultrouter", defaultrouter);
    302 }
     547  int r;
     548  r = rtems_bsd_rc_conf_service_add("network",
     549                                    "after:first;",
     550                                    network_service);
     551  if (r < 0)
     552    fprintf(stderr, "error: network service add failed: %s\n", strerror(errno));
     553}
  • rtemsbsd/rtems/rtems-bsd-rc-conf.c

    rc6713d1 r55c564a  
    4242
    4343#include <machine/rtems-bsd-rc-conf.h>
    44 #include <machine/rtems-bsd-rc-conf-directives.h>
     44#include <machine/rtems-bsd-rc-conf-services.h>
    4545
    4646/*
    47  * By default the networking directives are available.
     47 * By default the networking service is always available.
    4848 */
    4949RTEMS_BSD_RC_CONF_SYSINT(rc_conf_net);
     
    5555
    5656/*
    57  * Directive handler chain.
     57 * Intrenal rc.conf data. This is not visible out side of here.
    5858 */
    5959struct rtems_bsd_rc_conf_ {
    60   const char*  name;       /**< Name of the file. */
    61   const char*  data;       /**< Pre-processed rc.conf data. */
    62   size_t       line_count; /**< Number of lines with text. */
    63   const char** lines;      /**< The lines in the file's text. */
    64   size_t       line;       /**< The line being processed. */
    65   bool         verbose;    /**< Verbose processing. */
     60  const char*  name;          /**< Name of the file. */
     61  const char*  data;          /**< Pre-processed rc.conf data. */
     62  size_t       line_count;    /**< Number of lines with text. */
     63  const char** lines;         /**< The lines in the file's text. */
     64  size_t       line;          /**< The line being processed. */
     65  char*        find_regex;    /**< Find's regular expression. */
     66  int          timeout;       /**< The timeout for processing rc.conf. */
     67  bool         verbose;       /**< Verbose processing. */
     68  int          error_code;    /**< The error code returned to the caller. */
     69  rtems_id     lock;          /**< Threading lock for this data. */
     70  rtems_id     waiter;        /**< The waiting thread, 0 if no one waiting */
    6671};
    6772
    6873/*
    69  * Directive handler chain.
     74 * Services handler chain.
    7075 */
    7176typedef struct {
    72   rtems_chain_node            node;
    73   const char*                 directive;
    74   rtems_bsd_rc_conf_directive handler;
    75 } directive;
     77  rtems_chain_node          node;
     78  const char*               name;
     79  const char*               control;
     80  const char*               before;
     81  const char*               after;
     82  const char*               require;
     83  rtems_bsd_rc_conf_service entry;
     84} service;
    7685
    7786/*
    78  * Control of argc and argv.
     87 * The chain of services.
    7988 */
    80 typedef struct {
    81   char*        command;
    82   int          argc;
    83   const char** argv;
    84 } argc_argv;
    85 
    86 /*
    87  * The chain of directives.
    88  */
    89 static RTEMS_CHAIN_DEFINE_EMPTY(directives);
     89static RTEMS_CHAIN_DEFINE_EMPTY(services);
     90
     91#define ARGC_ARGV_MARKER (0x20010928)
    9092
    9193static int
    92 argc_argv_create(const char* line, argc_argv* aa)
     94argc_argv_valid(rtems_bsd_rc_conf_argc_argv* aa)
     95{
     96  if (aa->marker != ARGC_ARGV_MARKER) {
     97    errno = EACCES;
     98    return -1;
     99  }
     100  return 0;
     101}
     102
     103static void
     104argc_argv_clean(rtems_bsd_rc_conf_argc_argv* aa)
     105{
     106  if (argc_argv_valid(aa) >= 0) {
     107    free(aa->argv);
     108    free(aa->command);
     109    aa->argv = NULL;
     110    aa->command = NULL;
     111  }
     112}
     113
     114static int
     115argc_argv_update(const char* line, rtems_bsd_rc_conf_argc_argv* aa)
    93116{
    94117  char* c;
    95118  int   arg;
    96119  char* brk;
     120
     121  if (argc_argv_valid(aa) < 0)
     122    return -1;
     123
     124  argc_argv_clean(aa);
    97125
    98126  if (strnlen(line, MAX_LINE_SIZE) >= MAX_LINE_SIZE) {
     
    146174}
    147175
    148 static void
    149 argc_argv_destroy(argc_argv* aa)
    150 {
    151   free(aa->argv);
    152   free(aa->command);
    153   aa->argv = NULL;
    154   aa->command = NULL;
     176static int
     177lock_create(rtems_bsd_rc_conf* rc_conf)
     178{
     179  rtems_status_code sc;
     180  sc = rtems_semaphore_create(rtems_build_name('B', 'S', 'D', 'r'),
     181                              1,
     182                              RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE |
     183                              RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING |
     184                              RTEMS_LOCAL,
     185                              0,
     186                              &rc_conf->lock);
     187  if (sc != RTEMS_SUCCESSFUL) {
     188    fprintf(stderr, "error: rc_conf: cannot create lock: %s", rtems_status_text(sc));
     189    errno = EIO;
     190    return -1;
     191  }
     192  return 0;
     193}
     194
     195static int
     196lock_delete(rtems_bsd_rc_conf* rc_conf)
     197{
     198  rtems_semaphore_delete(rc_conf->lock);
     199  return 0;
     200}
     201
     202static int
     203lock(rtems_bsd_rc_conf* rc_conf)
     204{
     205  rtems_status_code sc;
     206  sc = rtems_semaphore_obtain(rc_conf->lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     207  if (sc != RTEMS_SUCCESSFUL) {
     208    fprintf(stderr, "error: rc_conf: locking: %s", rtems_status_text(sc));
     209    errno = EIO;
     210    return -1;
     211  }
     212  return 0;
     213}
     214
     215static int
     216unlock(rtems_bsd_rc_conf* rc_conf)
     217{
     218  rtems_status_code sc;
     219  sc = rtems_semaphore_release(rc_conf->lock);
     220  if (sc != RTEMS_SUCCESSFUL) {
     221    fprintf(stderr, "error: rc_conf: locking: %s", rtems_status_text(sc));
     222    errno = EIO;
     223    return -1;
     224  }
     225  return 0;
    155226}
    156227
     
    159230               const char*        name,
    160231               const char*        text,
     232               int                timeout,
    161233               bool               verbose)
    162234{
     
    168240  const char** lines;
    169241  size_t       line_count;
     242  int          r;
    170243
    171244  memset(rc_conf, 0, sizeof(*rc_conf));
     
    241314  }
    242315
    243   rc_conf->name = name;
     316  rc_conf->name = strdup(name);
    244317  rc_conf->data = copy;
    245318  rc_conf->line_count = line_count;
    246319  rc_conf->lines = lines;
    247320  rc_conf->line = 0;
     321  rc_conf->timeout = timeout;
    248322  rc_conf->verbose = verbose;
     323  if (timeout >= 0)
     324    rc_conf->waiter = rtems_task_self();
     325
     326  /*
     327   * Create the lock.
     328   */
     329  r = lock_create(rc_conf);
     330  if (r < 0) {
     331    free((void*) rc_conf->name);
     332    free((void*) rc_conf->lines);
     333    free((void*) rc_conf->data);
     334    return -1;
     335  }
    249336
    250337  return 0;
     
    254341rc_conf_destroy(rtems_bsd_rc_conf* rc_conf)
    255342{
    256   free((void*) rc_conf->lines);
    257   free((void*) rc_conf->data);
    258   rc_conf->data = NULL;
    259   rc_conf->name = NULL;
    260 }
    261 
    262 
    263 static int
    264 parse_line(rtems_bsd_rc_conf* rc_conf)
    265 {
    266   const char*             line;
    267   rtems_chain_node*       node = rtems_chain_first(&directives);
    268   const rtems_chain_node* tail = rtems_chain_tail(&directives);
    269   argc_argv               aa;
    270   int                     r;
    271 
    272   line = rc_conf->lines[rc_conf->line];
    273 
    274   if (*line == '\0')
    275     return 0;
    276 
    277   r = argc_argv_create(line, &aa);
    278   if (r < 0) {
    279     fprintf(stderr, "error: %s:%lu: creating argc/argv: %s\n",
    280             rc_conf->name, rc_conf->line + 1, strerror(errno));
    281     return r;
    282   }
    283 
    284   while (node != tail) {
    285     directive* dir = (directive*) node;
    286     regex_t    rege;
    287     #define    MAX_MATCHES 1
    288     regmatch_t matches[MAX_MATCHES];
    289 
    290     r = regcomp(&rege, dir->directive, REG_EXTENDED);
     343  if (rc_conf->name != NULL) {
     344    free((void*) rc_conf->name);
     345    free((void*) rc_conf->lines);
     346    free((void*) rc_conf->data);
     347    rc_conf->name = NULL;
     348    rc_conf->lines = NULL;
     349    rc_conf->data = NULL;
     350    lock_delete(rc_conf);
     351  }
     352}
     353
     354rtems_bsd_rc_conf_argc_argv*
     355rtems_bsd_rc_conf_argc_argv_create(void)
     356{
     357  rtems_bsd_rc_conf_argc_argv* aa = calloc(1, sizeof(rtems_bsd_rc_conf_argc_argv));
     358  if (aa != NULL)
     359    aa->marker = ARGC_ARGV_MARKER;
     360  return aa;
     361}
     362
     363void
     364rtems_bsd_rc_conf_argc_argv_destroy(rtems_bsd_rc_conf_argc_argv* aa)
     365{
     366  if (aa->marker == ARGC_ARGV_MARKER) {
     367    argc_argv_clean(aa);
     368    free(aa);
     369  }
     370}
     371
     372int rtems_bsd_rc_conf_find_next(rtems_bsd_rc_conf*           rc_conf,
     373                                rtems_bsd_rc_conf_argc_argv* argc_argv)
     374{
     375
     376  if (argc_argv_valid(argc_argv) < 0)
     377    return -1;
     378
     379  while (rc_conf->line < rc_conf->line_count) {
     380    const char* line;
     381    regex_t     rege;
     382    #define     MAX_MATCHES 1
     383    regmatch_t  matches[MAX_MATCHES];
     384    int         r;
     385
     386    line = rc_conf->lines[rc_conf->line];
     387    ++rc_conf->line;
     388
     389    if (*line == '\0')
     390      continue;
     391
     392    if (argc_argv_update(line, argc_argv) < 0)
     393      return -1;
     394
     395    r = regcomp(&rege, rc_conf->find_regex, REG_EXTENDED);
    291396    if (r != 0) {
    292397      char rerror[128];
     
    294399      fprintf(stderr, "error: %s:%lu: %s\n",
    295400              rc_conf->name, rc_conf->line + 1, rerror);
    296       argc_argv_destroy(&aa);
    297401      return -1;
    298402    }
    299403
    300     r = regexec(&rege, aa.argv[0], MAX_MATCHES, matches, 0);
     404    r = regexec(&rege, argc_argv->argv[0], MAX_MATCHES, matches, 0);
    301405    if (r != 0 && r != REG_NOMATCH) {
    302406      char rerror[128];
     
    305409              rc_conf->name, rc_conf->line + 1, rerror);
    306410      regfree(&rege);
    307       argc_argv_destroy(&aa);
    308411      return -1;
    309412    }
    310413
    311     if (r == 0) {
    312       r = dir->handler(rc_conf, aa.argc, aa.argv);
    313       if (r < 0)
    314         fprintf(stderr, "error: %s:%lu: runtime error: %s: %s\n",
    315                 rc_conf->name, rc_conf->line + 1, aa.argv[0], strerror(errno));
    316       regfree(&rege);
    317       argc_argv_destroy(&aa);
    318       return r;
    319     }
    320 
    321414    regfree(&rege);
    322415
     416    /*
     417     * Match found.
     418     */
     419    if (r == 0)
     420      return 0;
     421
     422    regfree(&rege);
     423  }
     424
     425  errno = ENOENT;
     426
     427  return -1;
     428}
     429
     430int rtems_bsd_rc_conf_find(rtems_bsd_rc_conf*           rc_conf,
     431                           const char*                  expression,
     432                           rtems_bsd_rc_conf_argc_argv* argc_argv)
     433{
     434  if (argc_argv_valid(argc_argv) < 0)
     435    return -1;
     436  free(rc_conf->find_regex);
     437  rc_conf->find_regex = strdup(expression);
     438  rc_conf->line = 0;
     439  if (rc_conf->find_regex == NULL) {
     440    errno = ENOMEM;
     441    return -1;
     442  }
     443  return rtems_bsd_rc_conf_find_next(rc_conf, argc_argv);
     444}
     445
     446int
     447rtems_bsd_rc_conf_service_add(const char*               name,
     448                              const char*               control,
     449                              rtems_bsd_rc_conf_service entry)
     450{
     451  service* srv;
     452  char*    ctl = NULL;
     453  char*    s;
     454  char*    c;
     455
     456  srv = malloc(sizeof(*srv));
     457  if (srv == NULL) {
     458    errno = ENOMEM;
     459    return -1;
     460  }
     461
     462  memset(srv, 0, sizeof(*srv));
     463
     464  srv->name = strdup(name);
     465  if (control != NULL) {
     466    ctl = strdup(control);
     467    srv->control = ctl;
     468  }
     469  srv->entry = entry;
     470
     471  if (srv->name == NULL || (control != NULL && ctl == NULL)) {
     472    fprintf(stderr, "error: rc.conf: add service: no memory\n");
     473    free((void*) srv->control);
     474    free((void*) srv->name);
     475    free(srv);
     476    errno = ENOMEM;
     477    return -1;
     478  }
     479
     480  if (control != NULL) {
     481    s = c = ctl;
     482
     483    while (*c != '\0') {
     484      if (*c == ';') {
     485        *c = '\0';
     486
     487        if (strncasecmp("before:", s, sizeof("before:") - 1) == 0) {
     488          if (srv->before == NULL) {
     489            srv->before = s + sizeof("before:") - 1;
     490            s = NULL;
     491          }
     492          else {
     493            fprintf(stderr, "error: rc.conf: add service: repeated 'before'\n");
     494            c = NULL;
     495          }
     496        }
     497        else if (strncasecmp("after:", s, sizeof("after:") - 1) == 0) {
     498          if (srv->after == NULL) {
     499            srv->after = s + sizeof("after:") - 1;
     500            s = NULL;
     501          }
     502          else {
     503            fprintf(stderr, "error: rc.conf: add service: repeated 'after'\n");
     504            c = NULL;
     505          }
     506        }
     507        else if (strncasecmp("require:", s, sizeof("require:") - 1) == 0) {
     508          if (srv->require == NULL) {
     509            srv->require = s + sizeof("require:") - 1;
     510            s = NULL;
     511          }
     512          else {
     513            fprintf(stderr, "error: rc.conf: add service: repeated 'require'\n");
     514            c = NULL;
     515          }
     516        }
     517        else {
     518          fprintf(stderr, "error: rc.conf: add service: unknown keyword: %s\n", s);
     519          c = NULL;
     520        }
     521
     522        if (c == NULL) {
     523          free((void*) srv->control);
     524          free((void*) srv->name);
     525          free(srv);
     526          errno = EINVAL;
     527          return -1;
     528        }
     529      }
     530      else if (s == NULL) {
     531        s = c;
     532      }
     533
     534      ++c;
     535    }
     536
     537    if (s != NULL) {
     538      fprintf(stderr, "error: rc.conf: add service: no ';' found\n");
     539      free((void*) srv->control);
     540      free((void*) srv->name);
     541      free(srv);
     542      errno = EINVAL;
     543      return -1;
     544    }
     545
     546    /*
     547     * Place on the services list. The node is removed before being inserted. If
     548     * there are competing positions the last position is used. As a result
     549     * handle 'after' before 'before'.
     550     */
     551    rtems_chain_prepend(&services, &srv->node);
     552  }
     553  else {
     554    /*
     555     * No control string, add the end.
     556     */
     557    rtems_chain_append(&services, &srv->node);
     558  }
     559
     560  /*
     561   * After.
     562   */
     563  if (srv->after != NULL) {
     564    const char* cc = srv->after;
     565    while (*cc != '\0') {
     566      const char* cs = cc;
     567      size_t      l;
     568      while (*cc != ',' && *cc != '\0')
     569        ++cc;
     570      l = cc - cs;
     571      if (strncasecmp(cs, "last", l) == 0) {
     572        fprintf(stderr,
     573                "error: rc.conf: add service: 'last' in 'after': %s\n",
     574                control);
     575        rtems_chain_extract(&srv->node);
     576        free((void*) srv->control);
     577        free((void*) srv->name);
     578        free(srv);
     579        errno = EINVAL;
     580        return -1;
     581      }
     582      else if (strncasecmp(cs, "first", l) == 0) {
     583        /* already prepended */
     584      }
     585      else {
     586        rtems_chain_node* node = rtems_chain_first(&services);
     587        while (!rtems_chain_is_tail(&services, node)) {
     588          service* ss = (service*) node;
     589          if (ss != srv &&
     590              strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
     591            rtems_chain_extract(&srv->node);
     592            rtems_chain_insert(&ss->node, &srv->node);
     593            break;
     594          }
     595          node = rtems_chain_next(node);
     596        }
     597      }
     598    }
     599  }
     600
     601  /*
     602   * Before.
     603   */
     604  if (srv->before != NULL) {
     605    const char* cc = srv->before;
     606    while (*cc != '\0') {
     607      const char* cs = cc;
     608      size_t      l;
     609      while (*cc != ',' && *cc != '\0')
     610        ++cc;
     611      l = cc - cs;
     612      if (strncasecmp(cs, "first", l) == 0) {
     613        fprintf(stderr, "error: rc.conf: add service: 'first' in 'before'\n");
     614        rtems_chain_extract(&srv->node);
     615        free((void*) srv->control);
     616        free((void*) srv->name);
     617        free(srv);
     618        errno = EINVAL;
     619        return -1;
     620      }
     621      else if (strncasecmp(cs, "last", l) == 0) {
     622        rtems_chain_extract(&srv->node);
     623        rtems_chain_append(&services, &srv->node);
     624      }
     625      else {
     626        rtems_chain_node* node = rtems_chain_first(&services);
     627        while (!rtems_chain_is_tail(&services, node)) {
     628          service* ss = (service*) node;
     629          if (strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
     630            rtems_chain_extract(&srv->node);
     631            if (rtems_chain_is_first(node))
     632              rtems_chain_prepend(&services, &srv->node);
     633            else {
     634              service* sp = (service*) rtems_chain_previous(node);
     635              rtems_chain_insert(&sp->node, &srv->node);
     636            }
     637            break;
     638          }
     639          node = rtems_chain_next(node);
     640        }
     641      }
     642    }
     643  }
     644
     645  return 0;
     646}
     647
     648int
     649rtems_bsd_rc_conf_service_remove(const char* name)
     650{
     651  rtems_chain_node*       node = rtems_chain_first(&services);
     652  const rtems_chain_node* tail = rtems_chain_tail(&services);
     653
     654  while (node != tail) {
     655    service* srv = (service*) node;
     656
     657    if (strcasecmp(name, srv->name) == 0) {
     658      rtems_chain_extract(&srv->node);
     659      free((void*) srv->control);
     660      free((void*) srv->name);
     661      free(srv);
     662      return 0;
     663    }
     664
    323665    node = rtems_chain_next(node);
    324666  }
    325667
    326   errno = ENOSYS;
    327 
    328   fprintf(stderr, "error: %s:%lu: %s: configuration name is not supported\n",
    329           rc_conf->name, rc_conf->line + 1, aa.argv[0]);
    330 
    331   argc_argv_destroy(&aa);
    332 
     668  errno = ENOENT;
    333669  return -1;
    334670}
    335671
     672static rtems_task rc_conf_worker(rtems_task_argument task_argument)
     673{
     674  rtems_bsd_rc_conf* rc_conf = (rtems_bsd_rc_conf*) task_argument;
     675  rtems_chain_node* node = rtems_chain_first(&services);
     676  int               r = 0;
     677  int               error;
     678
     679  if (rc_conf->verbose)
     680    printf("rc.conf: running\n");
     681
     682  while (!rtems_chain_is_tail(&services, node)) {
     683    service* srv = (service*) node;
     684    int      rr;
     685    if (rc_conf->verbose)
     686      printf("BSD service: %s\n", srv->name);
     687    rr = srv->entry(rc_conf);
     688    if (rr < 0) {
     689      fprintf(stderr, "error: bsd service: %s: %s\n", srv->name, strerror(errno));
     690      if (r == 0) {
     691        r = rr;
     692        error = errno;
     693      }
     694    }
     695    node = rtems_chain_next(node);
     696  }
     697
     698  if (rc_conf->verbose)
     699    printf("rc.conf: services done\n");
     700
     701  lock(rc_conf);
     702
     703  if (r < 0)
     704    rc_conf->error_code = error;
     705
     706  /*
     707   * If there is a waiter signal else clean up because the waiter has gone.
     708   */
     709  if (rc_conf->waiter != 0) {
     710    rtems_event_send(rc_conf->waiter, RTEMS_EVENT_1);
     711    unlock(rc_conf);
     712  }
     713  else {
     714    unlock(rc_conf);
     715    rc_conf_destroy(rc_conf);
     716  }
     717
     718  if (rc_conf->verbose)
     719    printf("rc.conf: finished\n");
     720
     721  rtems_task_delete(RTEMS_SELF);
     722}
     723
    336724int
    337 rtems_bsd_rc_conf_directive_add(const char*                 dir_regex,
    338                                 rtems_bsd_rc_conf_directive handler)
    339 {
    340   directive* dir;
    341 
    342   dir = malloc(sizeof(*dir));
    343   if (dir == NULL) {
    344     errno = ENOMEM;
    345     return -1;
    346   }
    347 
    348   memset(dir, 0, sizeof(*dir));
    349 
    350   dir->directive = strdup(dir_regex);
    351   if (dir->directive == NULL) {
    352     free(dir);
    353     errno = ENOMEM;
    354     return -1;
    355   }
    356 
    357   dir->handler = handler;
    358 
    359   rtems_chain_append(&directives, &dir->node);
    360 
    361   return 0;
    362 }
    363 
    364 int
    365 rtems_bsd_run_rc_conf_script(const char* name, const char* text, bool verbose)
    366 {
    367   rtems_bsd_rc_conf rc_conf;
    368   int               r;
     725rtems_bsd_run_rc_conf_script(const char* name,
     726                             const char* text,
     727                             int         timeout,
     728                             bool        verbose)
     729{
     730  rtems_bsd_rc_conf   rc_conf;
     731  rtems_task_priority priority;
     732  rtems_id            worker;
     733  rtems_status_code   sc;
     734  int                 r = 0;
    369735
    370736  if (verbose)
    371     printf("rc.conf: processing: %s size:%lu\n", name, strlen(text));
    372 
    373   r = rc_conf_create(&rc_conf, name, text, verbose);
     737    printf("rc.conf: start: %s size:%lu, timeout: %i\n",
     738           name, strlen(text), timeout);
     739
     740  r = rc_conf_create(&rc_conf, name, text, timeout, verbose);
    374741  if (r < 0) {
    375742    fprintf(stderr, "error: %s: parse error: %s\n",
     
    378745  }
    379746
    380   while (rc_conf.line < rc_conf.line_count) {
    381     r = parse_line(&rc_conf);
    382     if (r < 0)
    383       break;
    384     ++rc_conf.line;
    385   }
    386 
    387   rc_conf_destroy(&rc_conf);
     747  sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
     748  if (sc != RTEMS_SUCCESSFUL) {
     749    fprintf(stderr, "error: %s: get priority: %s\n",
     750            name, rtems_status_text(sc));
     751    errno = EIO;
     752    return -1;
     753  }
     754
     755  sc = rtems_task_create(rtems_build_name('B', 'S', 'D', 'r' ),
     756                         priority,
     757                         8 * 1024,
     758                         RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
     759                         RTEMS_LOCAL | RTEMS_FLOATING_POINT,
     760                         &worker);
     761  if (sc != RTEMS_SUCCESSFUL) {
     762    fprintf (stderr, "error: worker create: %s", rtems_status_text(sc));
     763    errno = EIO;
     764    return -1;
     765  }
     766
     767  sc = rtems_task_start(worker,
     768                        rc_conf_worker,
     769                        (rtems_task_argument) &rc_conf);
     770  if (sc != RTEMS_SUCCESSFUL) {
     771    fprintf (stderr, "error: worker start: %s", rtems_status_text(sc));
     772    errno = EIO;
     773    return - 1;
     774  }
     775
     776  if (timeout >= 0) {
     777    rtems_event_set out = 0;
     778    rtems_interval  ticks;
     779
     780    if (timeout == 0)
     781      ticks = RTEMS_NO_TIMEOUT;
     782    else
     783      ticks = RTEMS_MICROSECONDS_TO_TICKS(timeout * 1000000UL);
     784
     785    sc = rtems_event_receive(RTEMS_EVENT_1,
     786                             RTEMS_WAIT | RTEMS_EVENT_ANY,
     787                             ticks,
     788                             &out);
     789    if (sc != RTEMS_SUCCESSFUL) {
     790      if (sc != RTEMS_TIMEOUT) {
     791        fprintf (stderr, "error: worker event in: %s", rtems_status_text(sc));
     792        errno = EIO;
     793      }
     794      else {
     795        lock(&rc_conf);
     796        rc_conf.waiter = 0;
     797        unlock(&rc_conf);
     798        errno = ETIMEDOUT;
     799      }
     800      r = -1;
     801    }
     802    else {
     803      lock(&rc_conf);
     804      errno = rc_conf.error_code;
     805      if (errno != 0)
     806        r = -1;
     807      unlock(&rc_conf);
     808      rc_conf_destroy(&rc_conf);
     809    }
     810  }
    388811
    389812  return r;
     
    391814
    392815int
    393 rtems_bsd_run_rc_conf(const char* name, bool verbose)
     816rtems_bsd_run_rc_conf(const char* name, int timeout, bool verbose)
    394817{
    395818  struct stat sb;
     
    425848  fclose(file);
    426849
    427   r = rtems_bsd_run_rc_conf_script(name, rc_conf, verbose);
     850  r = rtems_bsd_run_rc_conf_script(name, rc_conf, timeout, verbose);
    428851
    429852  free(rc_conf);
     
    433856
    434857int
    435 rtems_bsd_run_etc_rc_conf(bool verbose)
    436 {
    437   return rtems_bsd_run_rc_conf("/etc/rc.conf", verbose);
     858rtems_bsd_run_etc_rc_conf(int timeout, bool verbose)
     859{
     860  return rtems_bsd_run_rc_conf("/etc/rc.conf", timeout, verbose);
    438861}
    439862
     
    451874
    452875bool
    453  rtems_bsd_rc_conf_verbose(rtems_bsd_rc_conf* rc_conf)
     876rtems_bsd_rc_conf_verbose(rtems_bsd_rc_conf* rc_conf)
    454877{
    455878  return rc_conf->verbose;
     
    463886  if (rc_conf->verbose) {
    464887    int arg;
    465     printf("rc.conf: %s:%lu: %s:", rc_conf->name, rc_conf->line + 1, name);
     888    printf("rc.conf: %s: %s:", rc_conf->name, name);
    466889    for (arg = 0; arg < argc; ++arg)
    467890      printf(" %s", argv[arg]);
  • testsuite/rcconf01/test_main.c

    rc6713d1 r55c564a  
    2727
    2828#include <assert.h>
     29#include <ctype.h>
    2930#include <errno.h>
    3031#include <string.h>
     
    3334#include <sys/stat.h>
    3435#include <sysexits.h>
     36#include <unistd.h>
    3537
    3638#include <machine/rtems-bsd-rc-conf.h>
     39#include <machine/rtems-bsd-rc-conf-services.h>
    3740
    3841#define TEST_NAME "LIBBSD RC.CONF 1"
     
    5356static bool test_regex_results[NUM_OF_TEST_REGEX_];
    5457static int  test_regex_last_num;
     58static int  test_service_last_num;
    5559
    5660static const char* rc_conf_not_found = \
     
    5963
    6064static int
    61 test_regex_(rtems_bsd_rc_conf* rc_conf, int argc, const char** argv)
    62 {
    63   int num;
    64   int arg;
    65 
    66   rtems_bsd_rc_conf_print_cmd(rc_conf, "test_regex_", argc, argv);
    67 
    68   assert(strncasecmp(argv[0], "test_regex_", strlen("test_regex_")) == 0);
    69   num = atoi(argv[0] + strlen("test_regex_"));
    70   assert(num == (test_regex_last_num + 1));
    71   assert((num - 1) < NUM_OF_TEST_REGEX_);
    72   for (arg = 0; arg < argc; ++arg) {
    73     const char* a = argv[arg];
    74     size_t      l = strlen(a);
    75     if (l > 0) {
    76       assert(!isspace(a[0]));
    77       assert(!isspace(a[l - 1]));
    78       assert(a[0] != '"');
    79       assert(a[l - 1] != '"');
     65test_service(rtems_bsd_rc_conf* rc_conf)
     66{
     67  rtems_bsd_rc_conf_argc_argv* aa;
     68  int                          r;
     69
     70  test_service_last_num = 1;
     71
     72  assert((aa = rtems_bsd_rc_conf_argc_argv_create()) != NULL);
     73  r = rtems_bsd_rc_conf_find(rc_conf, "test_regex_.*", aa);
     74  assert(r == 0 || (r < 0 && errno == ENOENT));
     75  if (r < 0 && errno == ENOENT)
     76    return -1;
     77
     78  while (r == 0) {
     79    int num;
     80    int arg;
     81    rtems_bsd_rc_conf_print_cmd(rc_conf, "test_service", aa->argc, aa->argv);
     82    assert(strncasecmp(aa->argv[0], "test_regex_", strlen("test_regex_")) == 0);
     83    num = atoi(aa->argv[0] + strlen("test_regex_"));
     84    assert(num == (test_regex_last_num + 1));
     85    assert((num - 1) < NUM_OF_TEST_REGEX_);
     86    for (arg = 0; arg < aa->argc; ++arg) {
     87      const char* a = aa->argv[arg];
     88      size_t      l = strlen(a);
     89      if (l > 0) {
     90        assert(!isspace(a[0]));
     91        assert(!isspace(a[l - 1]));
     92        assert(a[0] != '"');
     93        assert(a[l - 1] != '"');
     94      }
    8095    }
     96    test_regex_results[num - 1] = true;
     97    ++test_regex_last_num;
     98    r = rtems_bsd_rc_conf_find_next(rc_conf, aa);
     99    assert(r == 0 || (r < 0 && errno == ENOENT));
    81100  }
    82   test_regex_results[num - 1] = true;
    83   ++test_regex_last_num;
    84 
    85   return 0;
     101  rtems_bsd_rc_conf_argc_argv_destroy(aa);
     102  puts("test_service done");
     103  return 0;
     104}
     105
     106static int
     107test_service_2(rtems_bsd_rc_conf* rc_conf)
     108{
     109  puts("test_service_2");
     110  assert(test_service_last_num == 1);
     111  test_service_last_num = 2;
     112  return 0;
     113}
     114
     115static int
     116test_service_3(rtems_bsd_rc_conf* rc_conf)
     117{
     118  puts("test_service_3");
     119  assert(test_service_last_num == 2);
     120  test_service_last_num = 3;
     121  return 0;
     122}
     123
     124static int
     125test_service_4(rtems_bsd_rc_conf* rc_conf)
     126{
     127  puts("test_service_4");
     128  assert(test_service_last_num == 3);
     129  test_service_last_num = 4;
     130  return 0;
     131}
     132
     133static int
     134test_service_5(rtems_bsd_rc_conf* rc_conf)
     135{
     136  puts("test_service_5");
     137  assert(test_service_last_num == 4);
     138  test_service_last_num = 5;
     139  return 0;
     140}
     141
     142static int
     143test_service_bad(rtems_bsd_rc_conf* rc_conf)
     144{
     145  puts("test_service_bad");
     146  return -1;
    86147}
    87148
     
    106167
    107168static void
    108 test_etc_rc_conf(void)
     169test_regex_reset(void)
    109170{
    110171  memset(&test_regex_results[0], 0, sizeof(test_regex_results));
    111172  test_regex_last_num = 0;
     173  test_service_last_num = 0;
     174 }
     175
     176static void
     177test_etc_rc_conf(void)
     178{
     179  puts("test_etc_rc_conf");
    112180  make_rc_conf("/etc/rc.conf");
    113   assert(rtems_bsd_run_etc_rc_conf(true) == 0);
     181  test_regex_reset();
     182  assert(rtems_bsd_run_etc_rc_conf(0, true) == 0);
    114183  test_regex_check();
    115184}
     
    118187test_rc_conf(void)
    119188{
    120   memset(&test_regex_results[0], 0, sizeof(test_regex_results));
    121   test_regex_last_num = 0;
     189  puts("test_rc_conf");
    122190  make_rc_conf("/my_rc.conf");
    123   assert(rtems_bsd_run_rc_conf("/my_rc.conf", true) == 0);
     191  test_regex_reset();
     192  assert(rtems_bsd_run_rc_conf("/my_rc.conf", 0, true) == 0);
    124193  test_regex_check();
    125194}
     
    128197test_rc_conf_script(void)
    129198{
    130   memset(&test_regex_results[0], 0, sizeof(test_regex_results));
    131   test_regex_last_num = 0;
    132   assert(rtems_bsd_run_rc_conf_script("internal", rc_conf_regex, true) == 0);
     199  puts("test_rc_conf_conf");
     200  test_regex_reset();
     201  assert(rtems_bsd_run_rc_conf_script("internal", rc_conf_regex, 0, true) == 0);
    133202  test_regex_check();
    134203}
     
    137206test_rc_conf_script_not_found(void)
    138207{
    139   assert(rtems_bsd_run_rc_conf_script("internal", rc_conf_not_found, true) < 0);
     208  puts("test_rc_conf_conf_not_found");
     209  test_regex_reset();
     210  assert(rtems_bsd_run_rc_conf_script("internal", rc_conf_not_found, 0, true) < 0);
     211  assert(test_regex_last_num == 0);
    140212}
    141213
     
    147219  assert(stat("/etc", &sb) == 0);
    148220  assert(S_ISDIR(sb.st_mode));
    149   assert(rtems_bsd_rc_conf_directive_add("test_regex_.*", test_regex_) == 0);
     221  assert(rtems_bsd_rc_conf_service_add("test_service_2",
     222                                       "before:last;",
     223                                       test_service_2) == 0);
     224  assert(rtems_bsd_rc_conf_service_add("test_service_5",
     225                                       "after:test_service_2;",
     226                                       test_service_5) == 0);
     227  assert(rtems_bsd_rc_conf_service_add("test_service_4",
     228                                       "before:test_service_5;",
     229                                       test_service_4) == 0);
     230  assert(rtems_bsd_rc_conf_service_add("test_service_3",
     231                                       "before:test_service_4;after:test_service_2;",
     232                                       test_service_3) == 0);
     233  assert(rtems_bsd_rc_conf_service_add("test_service_bad",
     234                                       "before:first;",
     235                                       test_service_bad) < 0);
     236  assert(rtems_bsd_rc_conf_service_add("test_service_bad",
     237                                       "after:last;",
     238                                       test_service_bad) < 0);
     239  assert(rtems_bsd_rc_conf_service_add("test_service_bad",
     240                                       "after:xxxx,xxxx",
     241                                       test_service_bad) < 0);
     242  assert(rtems_bsd_rc_conf_service_add("test_service_bad",
     243                                       "yyyy:xxxx;",
     244                                       test_service_bad) < 0);
     245  assert(rtems_bsd_rc_conf_service_add("test_service",
     246                                       "after:first;",
     247                                       test_service) == 0);
    150248}
    151249
Note: See TracChangeset for help on using the changeset viewer.