source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-rc-conf.c @ c2ec5f1

5-freebsd-12freebsd-9.3
Last change on this file since c2ec5f1 was c2ec5f1, checked in by Chris Johns <chrisj@…>, on Jun 28, 2016 at 3:31:11 AM

Print the service when starting.

  • Property mode set to 100644
File size: 21.4 KB
Line 
1/*
2 * Copyright (c) 2016 Chris Johns <chrisj@rtems.org>.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/*
27 * Parse the /etc/rc.conf format file and execute the configuration options
28 * we want to support.
29 */
30
31
32#include <ctype.h>
33#include <errno.h>
34#include <stddef.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <sys/stat.h>
38#include <regex.h>
39
40#include <rtems.h>
41#include <rtems/chain.h>
42
43#include <machine/rtems-bsd-rc-conf.h>
44#include <machine/rtems-bsd-rc-conf-services.h>
45
46/*
47 * By default the networking service is always available.
48 */
49RTEMS_BSD_RC_CONF_SYSINT(rc_conf_net);
50
51/*
52 * Max line length.
53 */
54#define MAX_LINE_SIZE (512)
55
56/*
57 * Intrenal rc.conf data. This is not visible out side of here.
58 */
59struct 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  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 */
71};
72
73/*
74 * Services handler chain.
75 */
76typedef struct {
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;
85
86/*
87 * The chain of services.
88 */
89static RTEMS_CHAIN_DEFINE_EMPTY(services);
90
91#define ARGC_ARGV_MARKER (0x20010928)
92
93static int
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)
116{
117  char* c;
118  int   arg;
119  char* brk;
120
121  if (argc_argv_valid(aa) < 0)
122    return -1;
123
124  argc_argv_clean(aa);
125
126  if (strnlen(line, MAX_LINE_SIZE) >= MAX_LINE_SIZE) {
127    errno = EFBIG;
128    return -1;
129  }
130
131  aa->command = strdup(line);
132  if (aa->command == NULL) {
133    errno = ENOMEM;
134    return -1;
135  }
136
137  aa->argc = 0;
138  aa->argv = NULL;
139
140  /*
141   * Yes, the man page says do not use strtok. This is a local oopy, and the
142   * re-entrant version is being used.
143   */
144  c = aa->command;
145  while (true) {
146    c = strtok_r(c, " \t=\"", &brk);
147    if (c == NULL)
148      break;
149    ++aa->argc;
150    c = NULL;
151  }
152
153  /*
154   * Plus 1 for the trailing NULL present in argv lists.
155   */
156  aa->argv = calloc(aa->argc + 1, sizeof(char*));
157  if (aa->argv == NULL) {
158    free(aa->command);
159    errno = ENOMEM;
160    return -1;
161  }
162
163  aa->argv[0] = aa->command;
164  c = aa->command;
165
166  for (arg = 1; arg < aa->argc; ++arg) {
167    c += strlen(c) + 1;
168    while (*c != '\0' && (*c == '"' || isspace(*c)))
169      ++c;
170    aa->argv[arg] = c;
171  }
172
173  return 0;
174}
175
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;
226}
227
228static int
229rc_conf_create(rtems_bsd_rc_conf* rc_conf,
230               const char*        name,
231               const char*        text,
232               int                timeout,
233               bool               verbose)
234{
235  size_t       length;
236  char*        line;
237  char*        end;
238  char*        copy;
239  char*        marker;
240  const char** lines;
241  size_t       line_count;
242  int          r;
243
244  memset(rc_conf, 0, sizeof(*rc_conf));
245
246  /*
247   * Range check, this makes the rest safer in respect to buffer overflows.
248   */
249  length = strnlen(text, RTEMS_BSD_RC_CONF_MAX_SIZE);
250  if (length == RTEMS_BSD_RC_CONF_MAX_SIZE) {
251    errno = E2BIG;
252    return -1;
253  }
254
255  copy = strdup(text);
256  if (copy == NULL) {
257    errno = ENOMEM;
258    return -1;
259  }
260
261  end = copy + length;
262
263  /*
264   * Break the text up into lines.
265   */
266  line_count = 0;
267  for (line = copy; line != end; ++line) {
268    if (*line == '\n') {
269      line_count++;
270      *line = '\0';
271    }
272  }
273
274  lines = malloc(sizeof(char*) * line_count);
275  if (lines == NULL) {
276    free(copy);
277    errno = ENOMEM;
278    return -1;
279  }
280
281  memset(lines, 0, sizeof(char*) * line_count);
282
283  /*
284   * Extract all the lines.
285   */
286  line_count = 0;
287  for (marker = line = copy; line != end; ++line) {
288    if (*line == '\0' && line != end) {
289      /*
290       * Look for a comment.
291       */
292      char* comment = strchr(marker, '#');
293      if (comment != NULL)
294        *comment = '\0';
295      /*
296       * Remove leading whitespace.
297       */
298      length = strlen(marker);
299      while (*marker != '\0' && isspace(*marker))
300        memmove(marker, marker + 1, length--);
301      /*
302       * Remove trailing whitespace.
303       */
304      length = strlen(marker) - 1;
305      while (length > 0 && isspace(marker[length]))
306        marker[length--] = '\0';
307      /*
308       * Set the line.
309       */
310      lines[line_count] = marker;
311      ++line_count;
312      marker = line + 1;
313    }
314  }
315
316  rc_conf->name = strdup(name);
317  rc_conf->data = copy;
318  rc_conf->line_count = line_count;
319  rc_conf->lines = lines;
320  rc_conf->line = 0;
321  rc_conf->timeout = timeout;
322  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  }
336
337  return 0;
338}
339
340static void
341rc_conf_destroy(rtems_bsd_rc_conf* rc_conf)
342{
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);
396    if (r != 0) {
397      char rerror[128];
398      regerror(r, &rege, rerror, sizeof(rerror));
399      fprintf(stderr, "error: %s:%lu: %s\n",
400              rc_conf->name, rc_conf->line + 1, rerror);
401      return -1;
402    }
403
404    r = regexec(&rege, argc_argv->argv[0], MAX_MATCHES, matches, 0);
405    if (r != 0 && r != REG_NOMATCH) {
406      char rerror[128];
407      regerror(r, &rege, rerror, sizeof(rerror));
408      fprintf(stderr, "error: %s:%lu: %s\n",
409              rc_conf->name, rc_conf->line + 1, rerror);
410      regfree(&rege);
411      return -1;
412    }
413
414    regfree(&rege);
415
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
665    node = rtems_chain_next(node);
666  }
667
668  errno = ENOENT;
669  return -1;
670}
671
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 (strcmp("network", srv->name) != 0)
686      printf("Starting %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
724int
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;
735
736  if (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);
741  if (r < 0) {
742    fprintf(stderr, "error: %s: parse error: %s\n",
743            name, strerror(errno));
744    return -1;
745  }
746
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  }
811
812  return r;
813}
814
815int
816rtems_bsd_run_rc_conf(const char* name, int timeout, bool verbose)
817{
818  struct stat sb;
819  int         r;
820  char*       rc_conf;
821  FILE*       file;
822
823  r = stat(name, &sb);
824  if (r < 0)
825    return r;
826
827  rc_conf = malloc(sb.st_size);
828  if (rc_conf == NULL) {
829    errno = ENOMEM;
830    return -1;
831  }
832
833  if (verbose)
834    printf("rc.conf: loading: %s\n", name);
835
836  file = fopen(name, "r");
837  if (file == NULL) {
838    free(rc_conf);
839    return -1;
840  }
841
842  if (fread(rc_conf, 1, sb.st_size, file) != sb.st_size) {
843    fclose(file);
844    free(rc_conf);
845    return -1;
846  }
847
848  fclose(file);
849
850  r = rtems_bsd_run_rc_conf_script(name, rc_conf, timeout, verbose);
851
852  free(rc_conf);
853
854  return r;
855}
856
857int
858rtems_bsd_run_etc_rc_conf(int timeout, bool verbose)
859{
860  return rtems_bsd_run_rc_conf("/etc/rc.conf", timeout, verbose);
861}
862
863const char*
864rtems_bsd_rc_conf_name(rtems_bsd_rc_conf* rc_conf)
865{
866  return rc_conf->name;
867}
868
869int
870rtems_bsd_rc_conf_line(rtems_bsd_rc_conf* rc_conf)
871{
872  return rc_conf->line + 1;
873}
874
875bool
876rtems_bsd_rc_conf_verbose(rtems_bsd_rc_conf* rc_conf)
877{
878  return rc_conf->verbose;
879}
880
881void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf,
882                                 const char*        name,
883                                 int                argc,
884                                 const char**       argv)
885{
886  if (rc_conf->verbose) {
887    int arg;
888    printf("rc.conf: %s: %s:", rc_conf->name, name);
889    for (arg = 0; arg < argc; ++arg)
890      printf(" %s", argv[arg]);
891    printf("\n");
892  }
893}
Note: See TracBrowser for help on using the repository browser.