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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since dc5b267 was 573b1982, checked in by Chris Johns <chrisj@…>, on 06/29/16 at 23:19:52

Add DHCP support to rc.conf.

  • Property mode set to 100644
File size: 22.2 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 <syslog.h>
41
42#include <rtems.h>
43#include <rtems/chain.h>
44
45#include <machine/rtems-bsd-rc-conf.h>
46#include <machine/rtems-bsd-rc-conf-services.h>
47
48/*
49 * By default the networking service is always available.
50 */
51RTEMS_BSD_RC_CONF_SYSINT(rc_conf_net);
52
53/*
54 * Max line length.
55 */
56#define MAX_LINE_SIZE (512)
57
58/*
59 * Intrenal rc.conf data. This is not visible out side of here.
60 */
61struct rtems_bsd_rc_conf_ {
62  const char*  name;          /**< Name of the file. */
63  const char*  data;          /**< Pre-processed rc.conf data. */
64  size_t       line_count;    /**< Number of lines with text. */
65  const char** lines;         /**< The lines in the file's text. */
66  size_t       line;          /**< The line being processed. */
67  char*        find_regex;    /**< Find's regular expression. */
68  int          timeout;       /**< The timeout for processing rc.conf. */
69  bool         verbose;       /**< Verbose processing. */
70  int          error_code;    /**< The error code returned to the caller. */
71  rtems_id     lock;          /**< Threading lock for this data. */
72  rtems_id     waiter;        /**< The waiting thread, 0 if no one waiting */
73};
74
75/*
76 * Services handler chain.
77 */
78typedef struct {
79  rtems_chain_node          node;
80  const char*               name;
81  const char*               control;
82  const char*               before;
83  const char*               after;
84  const char*               require;
85  rtems_bsd_rc_conf_service entry;
86} service;
87
88/*
89 * The chain of services.
90 */
91static RTEMS_CHAIN_DEFINE_EMPTY(services);
92
93#define ARGC_ARGV_MARKER (0x20010928)
94
95static int
96argc_argv_valid(rtems_bsd_rc_conf_argc_argv* aa)
97{
98  if (aa->marker != ARGC_ARGV_MARKER) {
99    errno = EACCES;
100    return -1;
101  }
102  return 0;
103}
104
105static void
106argc_argv_clean(rtems_bsd_rc_conf_argc_argv* aa)
107{
108  if (argc_argv_valid(aa) >= 0) {
109    free(aa->argv);
110    free(aa->command);
111    aa->argv = NULL;
112    aa->command = NULL;
113    aa->argc = 0;
114  }
115}
116
117static int
118argc_argv_update(const char* line, rtems_bsd_rc_conf_argc_argv* aa)
119{
120  char* c;
121  int   arg;
122  char* brk;
123
124  if (argc_argv_valid(aa) < 0)
125    return -1;
126
127  argc_argv_clean(aa);
128
129  if (strnlen(line, MAX_LINE_SIZE) >= MAX_LINE_SIZE) {
130    errno = EFBIG;
131    return -1;
132  }
133
134  aa->command = strdup(line);
135  if (aa->command == NULL) {
136    errno = ENOMEM;
137    return -1;
138  }
139
140  aa->argc = 0;
141  aa->argv = NULL;
142
143  /*
144   * Yes, the man page says do not use strtok. This is a local oopy, and the
145   * re-entrant version is being used.
146   */
147  c = aa->command;
148  while (true) {
149    c = strtok_r(c, " \t=\"", &brk);
150    if (c == NULL)
151      break;
152    ++aa->argc;
153    c = NULL;
154  }
155
156  /*
157   * Plus 1 for the trailing NULL present in argv lists.
158   */
159  aa->argv = calloc(aa->argc + 1, sizeof(char*));
160  if (aa->argv == NULL) {
161    free(aa->command);
162    errno = ENOMEM;
163    return -1;
164  }
165
166  aa->argv[0] = aa->command;
167  c = aa->command;
168
169  for (arg = 1; arg < aa->argc; ++arg) {
170    c += strlen(c) + 1;
171    while (*c != '\0' && (*c == '"' || isspace(*c)))
172      ++c;
173    aa->argv[arg] = c;
174  }
175
176  return 0;
177}
178
179static int
180lock_create(rtems_bsd_rc_conf* rc_conf)
181{
182  rtems_status_code sc;
183  sc = rtems_semaphore_create(rtems_build_name('B', 'S', 'D', 'r'),
184                              1,
185                              RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE |
186                              RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING |
187                              RTEMS_LOCAL,
188                              0,
189                              &rc_conf->lock);
190  if (sc != RTEMS_SUCCESSFUL) {
191    fprintf(stderr, "error: rc_conf: cannot create lock: %s", rtems_status_text(sc));
192    errno = EIO;
193    return -1;
194  }
195  return 0;
196}
197
198static int
199lock_delete(rtems_bsd_rc_conf* rc_conf)
200{
201  rtems_semaphore_delete(rc_conf->lock);
202  return 0;
203}
204
205static int
206lock(rtems_bsd_rc_conf* rc_conf)
207{
208  rtems_status_code sc;
209  sc = rtems_semaphore_obtain(rc_conf->lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
210  if (sc != RTEMS_SUCCESSFUL) {
211    fprintf(stderr, "error: rc_conf: locking: %s", rtems_status_text(sc));
212    errno = EIO;
213    return -1;
214  }
215  return 0;
216}
217
218static int
219unlock(rtems_bsd_rc_conf* rc_conf)
220{
221  rtems_status_code sc;
222  sc = rtems_semaphore_release(rc_conf->lock);
223  if (sc != RTEMS_SUCCESSFUL) {
224    fprintf(stderr, "error: rc_conf: locking: %s", rtems_status_text(sc));
225    errno = EIO;
226    return -1;
227  }
228  return 0;
229}
230
231static int
232rc_conf_create(rtems_bsd_rc_conf* rc_conf,
233               const char*        name,
234               const char*        text,
235               int                timeout,
236               bool               verbose)
237{
238  size_t       length;
239  char*        line;
240  char*        end;
241  char*        copy;
242  char*        marker;
243  const char** lines;
244  size_t       line_count;
245  int          r;
246
247  memset(rc_conf, 0, sizeof(*rc_conf));
248
249  /*
250   * Range check, this makes the rest safer in respect to buffer overflows.
251   */
252  length = strnlen(text, RTEMS_BSD_RC_CONF_MAX_SIZE);
253  if (length == RTEMS_BSD_RC_CONF_MAX_SIZE) {
254    errno = E2BIG;
255    return -1;
256  }
257
258  copy = strdup(text);
259  if (copy == NULL) {
260    errno = ENOMEM;
261    return -1;
262  }
263
264  end = copy + length;
265
266  /*
267   * Break the text up into lines.
268   */
269  line_count = 0;
270  for (line = copy; line != end; ++line) {
271    if (*line == '\n') {
272      line_count++;
273      *line = '\0';
274    }
275  }
276
277  lines = malloc(sizeof(char*) * line_count);
278  if (lines == NULL) {
279    free(copy);
280    errno = ENOMEM;
281    return -1;
282  }
283
284  memset(lines, 0, sizeof(char*) * line_count);
285
286  /*
287   * Extract all the lines.
288   */
289  line_count = 0;
290  for (marker = line = copy; line != end; ++line) {
291    if (*line == '\0' && line != end) {
292      /*
293       * Look for a comment.
294       */
295      char* comment = strchr(marker, '#');
296      if (comment != NULL)
297        *comment = '\0';
298      /*
299       * Remove leading whitespace.
300       */
301      length = strlen(marker);
302      while (*marker != '\0' && isspace(*marker))
303        memmove(marker, marker + 1, length--);
304      /*
305       * Remove trailing whitespace.
306       */
307      length = strlen(marker) - 1;
308      while (length > 0 && isspace(marker[length]))
309        marker[length--] = '\0';
310      /*
311       * Set the line.
312       */
313      lines[line_count] = marker;
314      ++line_count;
315      marker = line + 1;
316    }
317  }
318
319  rc_conf->name = strdup(name);
320  rc_conf->data = copy;
321  rc_conf->line_count = line_count;
322  rc_conf->lines = lines;
323  rc_conf->line = 0;
324  rc_conf->timeout = timeout;
325  rc_conf->verbose = verbose;
326  if (timeout >= 0)
327    rc_conf->waiter = rtems_task_self();
328
329  /*
330   * Create the lock.
331   */
332  r = lock_create(rc_conf);
333  if (r < 0) {
334    free((void*) rc_conf->name);
335    free((void*) rc_conf->lines);
336    free((void*) rc_conf->data);
337    return -1;
338  }
339
340  return 0;
341}
342
343static void
344rc_conf_destroy(rtems_bsd_rc_conf* rc_conf)
345{
346  if (rc_conf->name != NULL) {
347    free((void*) rc_conf->name);
348    free((void*) rc_conf->lines);
349    free((void*) rc_conf->data);
350    rc_conf->name = NULL;
351    rc_conf->lines = NULL;
352    rc_conf->data = NULL;
353    lock_delete(rc_conf);
354  }
355}
356
357rtems_bsd_rc_conf_argc_argv*
358rtems_bsd_rc_conf_argc_argv_create(void)
359{
360  rtems_bsd_rc_conf_argc_argv* aa = calloc(1, sizeof(rtems_bsd_rc_conf_argc_argv));
361  if (aa != NULL)
362    aa->marker = ARGC_ARGV_MARKER;
363  return aa;
364}
365
366void
367rtems_bsd_rc_conf_argc_argv_destroy(rtems_bsd_rc_conf_argc_argv* aa)
368{
369  if (aa->marker == ARGC_ARGV_MARKER) {
370    argc_argv_clean(aa);
371    free(aa);
372  }
373}
374
375int rtems_bsd_rc_conf_find_next(rtems_bsd_rc_conf*           rc_conf,
376                                rtems_bsd_rc_conf_argc_argv* argc_argv)
377{
378
379  if (argc_argv_valid(argc_argv) < 0)
380    return -1;
381
382  while (rc_conf->line < rc_conf->line_count) {
383    const char* line;
384    regex_t     rege;
385    #define     MAX_MATCHES 1
386    regmatch_t  matches[MAX_MATCHES];
387    int         r;
388
389    line = rc_conf->lines[rc_conf->line];
390    ++rc_conf->line;
391
392    if (*line == '\0')
393      continue;
394
395    if (argc_argv_update(line, argc_argv) < 0)
396      return -1;
397
398    r = regcomp(&rege, rc_conf->find_regex, REG_EXTENDED);
399    if (r != 0) {
400      char rerror[128];
401      regerror(r, &rege, rerror, sizeof(rerror));
402      fprintf(stderr, "error: %s:%lu: %s\n",
403              rc_conf->name, rc_conf->line + 1, rerror);
404      return -1;
405    }
406
407    r = regexec(&rege, argc_argv->argv[0], MAX_MATCHES, matches, 0);
408    if (r != 0 && r != REG_NOMATCH) {
409      char rerror[128];
410      regerror(r, &rege, rerror, sizeof(rerror));
411      fprintf(stderr, "error: %s:%lu: %s\n",
412              rc_conf->name, rc_conf->line + 1, rerror);
413      regfree(&rege);
414      return -1;
415    }
416
417    regfree(&rege);
418
419    /*
420     * Match found.
421     */
422    if (r == 0)
423      return 0;
424
425    regfree(&rege);
426  }
427
428  argc_argv_clean(argc_argv);
429
430  errno = ENOENT;
431
432  return -1;
433}
434
435int rtems_bsd_rc_conf_find(rtems_bsd_rc_conf*           rc_conf,
436                           const char*                  expression,
437                           rtems_bsd_rc_conf_argc_argv* argc_argv)
438{
439  if (argc_argv_valid(argc_argv) < 0)
440    return -1;
441  free(rc_conf->find_regex);
442  rc_conf->find_regex = strdup(expression);
443  rc_conf->line = 0;
444  if (rc_conf->find_regex == NULL) {
445    errno = ENOMEM;
446    return -1;
447  }
448  return rtems_bsd_rc_conf_find_next(rc_conf, argc_argv);
449}
450
451int
452rtems_bsd_rc_conf_service_add(const char*               name,
453                              const char*               control,
454                              rtems_bsd_rc_conf_service entry)
455{
456  service* srv;
457  char*    ctl = NULL;
458  char*    s;
459  char*    c;
460
461  srv = malloc(sizeof(*srv));
462  if (srv == NULL) {
463    errno = ENOMEM;
464    return -1;
465  }
466
467  memset(srv, 0, sizeof(*srv));
468
469  srv->name = strdup(name);
470  if (control != NULL) {
471    ctl = strdup(control);
472    srv->control = ctl;
473  }
474  srv->entry = entry;
475
476  if (srv->name == NULL || (control != NULL && ctl == NULL)) {
477    fprintf(stderr, "error: rc.conf: add service: no memory\n");
478    free((void*) srv->control);
479    free((void*) srv->name);
480    free(srv);
481    errno = ENOMEM;
482    return -1;
483  }
484
485  if (control != NULL) {
486    s = c = ctl;
487
488    while (*c != '\0') {
489      if (*c == ';') {
490        *c = '\0';
491
492        if (strncasecmp("before:", s, sizeof("before:") - 1) == 0) {
493          if (srv->before == NULL) {
494            srv->before = s + sizeof("before:") - 1;
495            s = NULL;
496          }
497          else {
498            fprintf(stderr, "error: rc.conf: add service: repeated 'before'\n");
499            c = NULL;
500          }
501        }
502        else if (strncasecmp("after:", s, sizeof("after:") - 1) == 0) {
503          if (srv->after == NULL) {
504            srv->after = s + sizeof("after:") - 1;
505            s = NULL;
506          }
507          else {
508            fprintf(stderr, "error: rc.conf: add service: repeated 'after'\n");
509            c = NULL;
510          }
511        }
512        else if (strncasecmp("require:", s, sizeof("require:") - 1) == 0) {
513          if (srv->require == NULL) {
514            srv->require = s + sizeof("require:") - 1;
515            s = NULL;
516          }
517          else {
518            fprintf(stderr, "error: rc.conf: add service: repeated 'require'\n");
519            c = NULL;
520          }
521        }
522        else {
523          fprintf(stderr, "error: rc.conf: add service: unknown keyword: %s\n", s);
524          c = NULL;
525        }
526
527        if (c == NULL) {
528          free((void*) srv->control);
529          free((void*) srv->name);
530          free(srv);
531          errno = EINVAL;
532          return -1;
533        }
534      }
535      else if (s == NULL) {
536        s = c;
537      }
538
539      ++c;
540    }
541
542    if (s != NULL) {
543      fprintf(stderr, "error: rc.conf: add service: no ';' found\n");
544      free((void*) srv->control);
545      free((void*) srv->name);
546      free(srv);
547      errno = EINVAL;
548      return -1;
549    }
550
551    /*
552     * Place on the services list. The node is removed before being inserted. If
553     * there are competing positions the last position is used. As a result
554     * handle 'after' before 'before'.
555     */
556    rtems_chain_prepend(&services, &srv->node);
557  }
558  else {
559    /*
560     * No control string, add the end.
561     */
562    rtems_chain_append(&services, &srv->node);
563  }
564
565  /*
566   * After.
567   */
568  if (srv->after != NULL) {
569    const char* cc = srv->after;
570    while (*cc != '\0') {
571      const char* cs = cc;
572      size_t      l;
573      while (*cc != ',' && *cc != '\0')
574        ++cc;
575      l = cc - cs;
576      if (strncasecmp(cs, "last", l) == 0) {
577        fprintf(stderr,
578                "error: rc.conf: add service: 'last' in 'after': %s\n",
579                control);
580        rtems_chain_extract(&srv->node);
581        free((void*) srv->control);
582        free((void*) srv->name);
583        free(srv);
584        errno = EINVAL;
585        return -1;
586      }
587      else if (strncasecmp(cs, "first", l) == 0) {
588        /* already prepended */
589      }
590      else {
591        rtems_chain_node* node = rtems_chain_first(&services);
592        while (!rtems_chain_is_tail(&services, node)) {
593          service* ss = (service*) node;
594          if (ss != srv &&
595              strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
596            rtems_chain_extract(&srv->node);
597            rtems_chain_insert(&ss->node, &srv->node);
598            break;
599          }
600          node = rtems_chain_next(node);
601        }
602      }
603    }
604  }
605
606  /*
607   * Before.
608   */
609  if (srv->before != NULL) {
610    const char* cc = srv->before;
611    while (*cc != '\0') {
612      const char* cs = cc;
613      size_t      l;
614      while (*cc != ',' && *cc != '\0')
615        ++cc;
616      l = cc - cs;
617      if (strncasecmp(cs, "first", l) == 0) {
618        fprintf(stderr, "error: rc.conf: add service: 'first' in 'before'\n");
619        rtems_chain_extract(&srv->node);
620        free((void*) srv->control);
621        free((void*) srv->name);
622        free(srv);
623        errno = EINVAL;
624        return -1;
625      }
626      else if (strncasecmp(cs, "last", l) == 0) {
627        rtems_chain_extract(&srv->node);
628        rtems_chain_append(&services, &srv->node);
629      }
630      else {
631        rtems_chain_node* node = rtems_chain_first(&services);
632        while (!rtems_chain_is_tail(&services, node)) {
633          service* ss = (service*) node;
634          if (strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
635            rtems_chain_extract(&srv->node);
636            if (rtems_chain_is_first(node))
637              rtems_chain_prepend(&services, &srv->node);
638            else {
639              service* sp = (service*) rtems_chain_previous(node);
640              rtems_chain_insert(&sp->node, &srv->node);
641            }
642            break;
643          }
644          node = rtems_chain_next(node);
645        }
646      }
647    }
648  }
649
650  return 0;
651}
652
653int
654rtems_bsd_rc_conf_service_remove(const char* name)
655{
656  rtems_chain_node*       node = rtems_chain_first(&services);
657  const rtems_chain_node* tail = rtems_chain_tail(&services);
658
659  while (node != tail) {
660    service* srv = (service*) node;
661
662    if (strcasecmp(name, srv->name) == 0) {
663      rtems_chain_extract(&srv->node);
664      free((void*) srv->control);
665      free((void*) srv->name);
666      free(srv);
667      return 0;
668    }
669
670    node = rtems_chain_next(node);
671  }
672
673  errno = ENOENT;
674  return -1;
675}
676
677static void
678rc_conf_syslog(rtems_bsd_rc_conf* rc_conf)
679{
680  rtems_bsd_rc_conf_argc_argv* aa;
681  int                          r = 0;
682  aa = rtems_bsd_rc_conf_argc_argv_create();
683  if (aa != NULL) {
684    r = rtems_bsd_rc_conf_find(rc_conf, "syslog_priority", aa);
685    if (r == 0) {
686      if (aa->argc == 2) {
687        r = rtems_bsd_setlogpriority(aa->argv[1]);
688        if (r < 0)
689          fprintf(stderr,
690                  "error: syslog: invalid priority: %s\n", aa->argv[1]);
691      }
692      else {
693        fprintf(stderr, "error: syslog: invalid priority\n");
694      }
695    }
696    rtems_bsd_rc_conf_argc_argv_destroy(aa);
697  }
698}
699
700static rtems_task
701rc_conf_worker(rtems_task_argument task_argument)
702{
703  rtems_bsd_rc_conf* rc_conf = (rtems_bsd_rc_conf*) task_argument;
704  rtems_chain_node*  node = rtems_chain_first(&services);
705  int                r = 0;
706  int                error;
707
708  /*
709   * Check for a syslog priority before any services are run.
710   */
711  rc_conf_syslog(rc_conf);
712
713  if (rc_conf->verbose)
714    printf("rc.conf: running\n");
715
716  while (!rtems_chain_is_tail(&services, node)) {
717    service* srv = (service*) node;
718    int      rr;
719    if (strcmp("network", srv->name) != 0)
720      printf("Starting %s.\n", srv->name);
721    rr = srv->entry(rc_conf);
722    if (rr < 0) {
723      fprintf(stderr,
724              "error: bsd service: %s: %s\n", srv->name, strerror(errno));
725      if (r == 0) {
726        r = rr;
727        error = errno;
728      }
729    }
730    node = rtems_chain_next(node);
731  }
732
733  if (rc_conf->verbose)
734    printf("rc.conf: services done\n");
735
736  lock(rc_conf);
737
738  if (r < 0)
739    rc_conf->error_code = error;
740
741  /*
742   * If there is a waiter signal else clean up because the waiter has gone.
743   */
744  if (rc_conf->waiter != 0) {
745    rtems_event_send(rc_conf->waiter, RTEMS_EVENT_1);
746    unlock(rc_conf);
747  }
748  else {
749    unlock(rc_conf);
750    rc_conf_destroy(rc_conf);
751  }
752
753  if (rc_conf->verbose)
754    printf("rc.conf: finished\n");
755
756  rtems_task_delete(RTEMS_SELF);
757}
758
759int
760rtems_bsd_run_rc_conf_script(const char* name,
761                             const char* text,
762                             int         timeout,
763                             bool        verbose)
764{
765  rtems_bsd_rc_conf   rc_conf;
766  rtems_task_priority priority;
767  rtems_id            worker;
768  rtems_status_code   sc;
769  int                 r = 0;
770
771  if (verbose)
772    printf("rc.conf: start: %s size:%lu, timeout: %i\n",
773           name, strlen(text), timeout);
774
775  r = rc_conf_create(&rc_conf, name, text, timeout, verbose);
776  if (r < 0) {
777    fprintf(stderr, "error: %s: parse error: %s\n",
778            name, strerror(errno));
779    return -1;
780  }
781
782  sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
783  if (sc != RTEMS_SUCCESSFUL) {
784    fprintf(stderr, "error: %s: get priority: %s\n",
785            name, rtems_status_text(sc));
786    errno = EIO;
787    return -1;
788  }
789
790  sc = rtems_task_create(rtems_build_name('B', 'S', 'D', 'r' ),
791                         priority,
792                         8 * 1024,
793                         RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
794                         RTEMS_LOCAL | RTEMS_FLOATING_POINT,
795                         &worker);
796  if (sc != RTEMS_SUCCESSFUL) {
797    fprintf (stderr, "error: worker create: %s", rtems_status_text(sc));
798    errno = EIO;
799    return -1;
800  }
801
802  sc = rtems_task_start(worker,
803                        rc_conf_worker,
804                        (rtems_task_argument) &rc_conf);
805  if (sc != RTEMS_SUCCESSFUL) {
806    fprintf (stderr, "error: worker start: %s", rtems_status_text(sc));
807    errno = EIO;
808    return - 1;
809  }
810
811  if (timeout >= 0) {
812    rtems_event_set out = 0;
813    rtems_interval  ticks;
814
815    if (timeout == 0)
816      ticks = RTEMS_NO_TIMEOUT;
817    else
818      ticks = RTEMS_MICROSECONDS_TO_TICKS(timeout * 1000000UL);
819
820    sc = rtems_event_receive(RTEMS_EVENT_1,
821                             RTEMS_WAIT | RTEMS_EVENT_ANY,
822                             ticks,
823                             &out);
824    if (sc != RTEMS_SUCCESSFUL) {
825      if (sc != RTEMS_TIMEOUT) {
826        fprintf (stderr, "error: worker event in: %s", rtems_status_text(sc));
827        errno = EIO;
828      }
829      else {
830        lock(&rc_conf);
831        rc_conf.waiter = 0;
832        unlock(&rc_conf);
833        errno = ETIMEDOUT;
834      }
835      r = -1;
836    }
837    else {
838      lock(&rc_conf);
839      errno = rc_conf.error_code;
840      if (errno != 0)
841        r = -1;
842      unlock(&rc_conf);
843      rc_conf_destroy(&rc_conf);
844    }
845  }
846
847  return r;
848}
849
850int
851rtems_bsd_run_rc_conf(const char* name, int timeout, bool verbose)
852{
853  struct stat sb;
854  int         r;
855  char*       rc_conf;
856  FILE*       file;
857
858  r = stat(name, &sb);
859  if (r < 0)
860    return r;
861
862  rc_conf = malloc(sb.st_size);
863  if (rc_conf == NULL) {
864    errno = ENOMEM;
865    return -1;
866  }
867
868  if (verbose)
869    printf("rc.conf: loading: %s\n", name);
870
871  file = fopen(name, "r");
872  if (file == NULL) {
873    free(rc_conf);
874    return -1;
875  }
876
877  if (fread(rc_conf, 1, sb.st_size, file) != sb.st_size) {
878    fclose(file);
879    free(rc_conf);
880    return -1;
881  }
882
883  fclose(file);
884
885  r = rtems_bsd_run_rc_conf_script(name, rc_conf, timeout, verbose);
886
887  free(rc_conf);
888
889  return r;
890}
891
892int
893rtems_bsd_run_etc_rc_conf(int timeout, bool verbose)
894{
895  return rtems_bsd_run_rc_conf("/etc/rc.conf", timeout, verbose);
896}
897
898const char*
899rtems_bsd_rc_conf_name(rtems_bsd_rc_conf* rc_conf)
900{
901  return rc_conf->name;
902}
903
904int
905rtems_bsd_rc_conf_line(rtems_bsd_rc_conf* rc_conf)
906{
907  return rc_conf->line + 1;
908}
909
910bool
911rtems_bsd_rc_conf_verbose(rtems_bsd_rc_conf* rc_conf)
912{
913  return rc_conf->verbose;
914}
915
916void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf,
917                                 const char*        name,
918                                 int                argc,
919                                 const char**       argv)
920{
921  if (rc_conf->verbose) {
922    int arg;
923    printf("rc.conf: %s: %s:", rc_conf->name, name);
924    for (arg = 0; arg < argc; ++arg)
925      printf(" %s", argv[arg]);
926    printf("\n");
927  }
928}
Note: See TracBrowser for help on using the repository browser.