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

55-freebsd-126-freebsd-12
Last change on this file since eae664e was 43c65f5, checked in by Chris Johns <chrisj@…>, on 04/26/17 at 07:39:38

rc_conf: Do not use a local variable for the rc_conf context.

If a network error occurs or there is no waiter on rc_conf
processing the worker thread is left holding a local stack
struct ater the call has returned. Allocate on the heap.

  • Property mode set to 100644
File size: 22.5 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\n", 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\n", 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  rtems_bsd_rc_conf* _rc_conf;
239  size_t             length;
240  char*              line;
241  char*              end;
242  char*              copy;
243  char*              marker;
244  const char**       lines;
245  size_t             line_count;
246  int                r;
247
248  *rc_conf = NULL;
249
250  _rc_conf = malloc(sizeof(rtems_bsd_rc_conf));
251  if (_rc_conf == NULL) {
252    errno = ENOMEM;
253    return -1;
254  }
255
256  memset(_rc_conf, 0, sizeof(rtems_bsd_rc_conf));
257
258  /*
259   * Range check, this makes the rest safer in respect to buffer overflows.
260   */
261  length = strnlen(text, RTEMS_BSD_RC_CONF_MAX_SIZE);
262  if (length == RTEMS_BSD_RC_CONF_MAX_SIZE) {
263    errno = E2BIG;
264    return -1;
265  }
266
267  copy = strdup(text);
268  if (copy == NULL) {
269    errno = ENOMEM;
270    return -1;
271  }
272
273  end = copy + length;
274
275  /*
276   * Break the text up into lines.
277   */
278  line_count = 0;
279  for (line = copy; line != end; ++line) {
280    if (*line == '\n') {
281      line_count++;
282      *line = '\0';
283    }
284  }
285
286  lines = malloc(sizeof(char*) * line_count);
287  if (lines == NULL) {
288    free(copy);
289    errno = ENOMEM;
290    return -1;
291  }
292
293  memset(lines, 0, sizeof(char*) * line_count);
294
295  /*
296   * Extract all the lines.
297   */
298  line_count = 0;
299  for (marker = line = copy; line != end; ++line) {
300    if (*line == '\0' && line != end) {
301      /*
302       * Look for a comment.
303       */
304      char* comment = strchr(marker, '#');
305      if (comment != NULL)
306        *comment = '\0';
307      /*
308       * Remove leading whitespace.
309       */
310      length = strlen(marker);
311      while (*marker != '\0' && isspace(*marker))
312        memmove(marker, marker + 1, length--);
313      /*
314       * Remove trailing whitespace.
315       */
316      length = strlen(marker) - 1;
317      while (length > 0 && isspace(marker[length]))
318        marker[length--] = '\0';
319      /*
320       * Set the line.
321       */
322      lines[line_count] = marker;
323      ++line_count;
324      marker = line + 1;
325    }
326  }
327
328  _rc_conf->name = strdup(name);
329  _rc_conf->data = copy;
330  _rc_conf->line_count = line_count;
331  _rc_conf->lines = lines;
332  _rc_conf->line = 0;
333  _rc_conf->timeout = timeout;
334  _rc_conf->verbose = verbose;
335  if (timeout >= 0)
336    _rc_conf->waiter = rtems_task_self();
337
338  /*
339   * Create the lock.
340   */
341  r = lock_create(_rc_conf);
342  if (r < 0) {
343    free((void*) _rc_conf->name);
344    free((void*) _rc_conf->lines);
345    free((void*) _rc_conf->data);
346    return -1;
347  }
348
349  *rc_conf = _rc_conf;
350
351  return 0;
352}
353
354static void
355rc_conf_destroy(rtems_bsd_rc_conf* rc_conf)
356{
357  if (rc_conf != NULL && rc_conf->name != NULL) {
358    free((void*) rc_conf->name);
359    free((void*) rc_conf->lines);
360    free((void*) rc_conf->data);
361    rc_conf->name = NULL;
362    rc_conf->lines = NULL;
363    rc_conf->data = NULL;
364    lock_delete(rc_conf);
365    free((void*) rc_conf);
366  }
367}
368
369rtems_bsd_rc_conf_argc_argv*
370rtems_bsd_rc_conf_argc_argv_create(void)
371{
372  rtems_bsd_rc_conf_argc_argv* aa = calloc(1, sizeof(rtems_bsd_rc_conf_argc_argv));
373  if (aa != NULL)
374    aa->marker = ARGC_ARGV_MARKER;
375  return aa;
376}
377
378void
379rtems_bsd_rc_conf_argc_argv_destroy(rtems_bsd_rc_conf_argc_argv* aa)
380{
381  if (aa->marker == ARGC_ARGV_MARKER) {
382    argc_argv_clean(aa);
383    free(aa);
384  }
385}
386
387int rtems_bsd_rc_conf_find_next(rtems_bsd_rc_conf*           rc_conf,
388                                rtems_bsd_rc_conf_argc_argv* argc_argv)
389{
390
391  if (argc_argv_valid(argc_argv) < 0)
392    return -1;
393
394  while (rc_conf->line < rc_conf->line_count) {
395    const char* line;
396    regex_t     rege;
397    #define     MAX_MATCHES 1
398    regmatch_t  matches[MAX_MATCHES];
399    int         r;
400
401    line = rc_conf->lines[rc_conf->line];
402    ++rc_conf->line;
403
404    if (*line == '\0')
405      continue;
406
407    if (argc_argv_update(line, argc_argv) < 0)
408      return -1;
409
410    r = regcomp(&rege, rc_conf->find_regex, REG_EXTENDED);
411    if (r != 0) {
412      char rerror[128];
413      regerror(r, &rege, rerror, sizeof(rerror));
414      fprintf(stderr, "error: %s:%lu: %s\n",
415              rc_conf->name, rc_conf->line + 1, rerror);
416      return -1;
417    }
418
419    r = regexec(&rege, argc_argv->argv[0], MAX_MATCHES, matches, 0);
420    if (r != 0 && r != REG_NOMATCH) {
421      char rerror[128];
422      regerror(r, &rege, rerror, sizeof(rerror));
423      fprintf(stderr, "error: %s:%lu: %s\n",
424              rc_conf->name, rc_conf->line + 1, rerror);
425      regfree(&rege);
426      return -1;
427    }
428
429    regfree(&rege);
430
431    /*
432     * Match found.
433     */
434    if (r == 0)
435      return 0;
436  }
437
438  argc_argv_clean(argc_argv);
439
440  errno = ENOENT;
441
442  return -1;
443}
444
445int rtems_bsd_rc_conf_find(rtems_bsd_rc_conf*           rc_conf,
446                           const char*                  expression,
447                           rtems_bsd_rc_conf_argc_argv* argc_argv)
448{
449  if (argc_argv_valid(argc_argv) < 0)
450    return -1;
451  rc_conf->line = 0;
452  free(rc_conf->find_regex);
453  rc_conf->find_regex = strdup(expression);
454  if (rc_conf->find_regex == NULL) {
455    errno = ENOMEM;
456    return -1;
457  }
458  return rtems_bsd_rc_conf_find_next(rc_conf, argc_argv);
459}
460
461int
462rtems_bsd_rc_conf_service_add(const char*               name,
463                              const char*               control,
464                              rtems_bsd_rc_conf_service entry)
465{
466  service* srv;
467  char*    ctl = NULL;
468  char*    s;
469  char*    c;
470
471  srv = malloc(sizeof(*srv));
472  if (srv == NULL) {
473    errno = ENOMEM;
474    return -1;
475  }
476
477  memset(srv, 0, sizeof(*srv));
478
479  srv->name = strdup(name);
480  if (control != NULL) {
481    ctl = strdup(control);
482    srv->control = ctl;
483  }
484  srv->entry = entry;
485
486  if (srv->name == NULL || (control != NULL && ctl == NULL)) {
487    fprintf(stderr, "error: rc.conf: add service: no memory\n");
488    free((void*) srv->control);
489    free((void*) srv->name);
490    free(srv);
491    errno = ENOMEM;
492    return -1;
493  }
494
495  if (control != NULL) {
496    s = c = ctl;
497
498    while (*c != '\0') {
499      if (*c == ';') {
500        *c = '\0';
501
502        if (strncasecmp("before:", s, sizeof("before:") - 1) == 0) {
503          if (srv->before == NULL) {
504            srv->before = s + sizeof("before:") - 1;
505            s = NULL;
506          }
507          else {
508            fprintf(stderr, "error: rc.conf: add service: repeated 'before'\n");
509            c = NULL;
510          }
511        }
512        else if (strncasecmp("after:", s, sizeof("after:") - 1) == 0) {
513          if (srv->after == NULL) {
514            srv->after = s + sizeof("after:") - 1;
515            s = NULL;
516          }
517          else {
518            fprintf(stderr, "error: rc.conf: add service: repeated 'after'\n");
519            c = NULL;
520          }
521        }
522        else if (strncasecmp("require:", s, sizeof("require:") - 1) == 0) {
523          if (srv->require == NULL) {
524            srv->require = s + sizeof("require:") - 1;
525            s = NULL;
526          }
527          else {
528            fprintf(stderr, "error: rc.conf: add service: repeated 'require'\n");
529            c = NULL;
530          }
531        }
532        else {
533          fprintf(stderr, "error: rc.conf: add service: unknown keyword: %s\n", s);
534          c = NULL;
535        }
536
537        if (c == NULL) {
538          free((void*) srv->control);
539          free((void*) srv->name);
540          free(srv);
541          errno = EINVAL;
542          return -1;
543        }
544      }
545      else if (s == NULL) {
546        s = c;
547      }
548
549      ++c;
550    }
551
552    if (s != NULL) {
553      fprintf(stderr, "error: rc.conf: add service: no ';' found\n");
554      free((void*) srv->control);
555      free((void*) srv->name);
556      free(srv);
557      errno = EINVAL;
558      return -1;
559    }
560
561    /*
562     * Place on the services list. The node is removed before being inserted. If
563     * there are competing positions the last position is used. As a result
564     * handle 'after' before 'before'.
565     */
566    rtems_chain_prepend(&services, &srv->node);
567  }
568  else {
569    /*
570     * No control string, add the end.
571     */
572    rtems_chain_append(&services, &srv->node);
573  }
574
575  /*
576   * After.
577   */
578  if (srv->after != NULL) {
579    const char* cc = srv->after;
580    while (*cc != '\0') {
581      const char* cs = cc;
582      size_t      l;
583      while (*cc != ',' && *cc != '\0')
584        ++cc;
585      l = cc - cs;
586      if (strncasecmp(cs, "last", l) == 0) {
587        fprintf(stderr,
588                "error: rc.conf: add service: 'last' in 'after': %s\n",
589                control);
590        rtems_chain_extract(&srv->node);
591        free((void*) srv->control);
592        free((void*) srv->name);
593        free(srv);
594        errno = EINVAL;
595        return -1;
596      }
597      else if (strncasecmp(cs, "first", l) == 0) {
598        /* already prepended */
599      }
600      else {
601        rtems_chain_node* node = rtems_chain_first(&services);
602        while (!rtems_chain_is_tail(&services, node)) {
603          service* ss = (service*) node;
604          if (ss != srv &&
605              strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
606            rtems_chain_extract(&srv->node);
607            rtems_chain_insert(&ss->node, &srv->node);
608            break;
609          }
610          node = rtems_chain_next(node);
611        }
612      }
613    }
614  }
615
616  /*
617   * Before.
618   */
619  if (srv->before != NULL) {
620    const char* cc = srv->before;
621    while (*cc != '\0') {
622      const char* cs = cc;
623      size_t      l;
624      while (*cc != ',' && *cc != '\0')
625        ++cc;
626      l = cc - cs;
627      if (strncasecmp(cs, "first", l) == 0) {
628        fprintf(stderr, "error: rc.conf: add service: 'first' in 'before'\n");
629        rtems_chain_extract(&srv->node);
630        free((void*) srv->control);
631        free((void*) srv->name);
632        free(srv);
633        errno = EINVAL;
634        return -1;
635      }
636      else if (strncasecmp(cs, "last", l) == 0) {
637        rtems_chain_extract(&srv->node);
638        rtems_chain_append(&services, &srv->node);
639      }
640      else {
641        rtems_chain_node* node = rtems_chain_first(&services);
642        while (!rtems_chain_is_tail(&services, node)) {
643          service* ss = (service*) node;
644          if (strlen(ss->name) == l && strncasecmp(ss->name, cs, l) == 0) {
645            rtems_chain_extract(&srv->node);
646            if (rtems_chain_is_first(node))
647              rtems_chain_prepend(&services, &srv->node);
648            else {
649              service* sp = (service*) rtems_chain_previous(node);
650              rtems_chain_insert(&sp->node, &srv->node);
651            }
652            break;
653          }
654          node = rtems_chain_next(node);
655        }
656      }
657    }
658  }
659
660  return 0;
661}
662
663int
664rtems_bsd_rc_conf_service_remove(const char* name)
665{
666  rtems_chain_node*       node = rtems_chain_first(&services);
667  const rtems_chain_node* tail = rtems_chain_tail(&services);
668
669  while (node != tail) {
670    service* srv = (service*) node;
671
672    if (strcasecmp(name, srv->name) == 0) {
673      rtems_chain_extract(&srv->node);
674      free((void*) srv->control);
675      free((void*) srv->name);
676      free(srv);
677      return 0;
678    }
679
680    node = rtems_chain_next(node);
681  }
682
683  errno = ENOENT;
684  return -1;
685}
686
687static void
688rc_conf_syslog(rtems_bsd_rc_conf* rc_conf)
689{
690  rtems_bsd_rc_conf_argc_argv* aa;
691  int                          r = 0;
692  aa = rtems_bsd_rc_conf_argc_argv_create();
693  if (aa != NULL) {
694    r = rtems_bsd_rc_conf_find(rc_conf, "syslog_priority", aa);
695    if (r == 0) {
696      if (aa->argc == 2) {
697        r = rtems_bsd_setlogpriority(aa->argv[1]);
698        if (r < 0)
699          fprintf(stderr,
700                  "error: syslog: invalid priority: %s\n", aa->argv[1]);
701      }
702      else {
703        fprintf(stderr, "error: syslog: invalid priority\n");
704      }
705    }
706    rtems_bsd_rc_conf_argc_argv_destroy(aa);
707  }
708}
709
710static rtems_task
711rc_conf_worker(rtems_task_argument task_argument)
712{
713  rtems_bsd_rc_conf* rc_conf = (rtems_bsd_rc_conf*) task_argument;
714  rtems_chain_node*  node = rtems_chain_first(&services);
715  int                r = 0;
716  int                error;
717
718  /*
719   * Check for a syslog priority before any services are run.
720   */
721  rc_conf_syslog(rc_conf);
722
723  if (rc_conf->verbose)
724    printf("rc.conf: running\n");
725
726  while (!rtems_chain_is_tail(&services, node)) {
727    service* srv = (service*) node;
728    int      rr;
729    if (strcmp("network", srv->name) != 0)
730      printf("Starting %s.\n", srv->name);
731    rr = srv->entry(rc_conf);
732    if (rr < 0) {
733      fprintf(stderr,
734              "error: bsd service: %s: %s\n", srv->name, strerror(errno));
735      if (r == 0) {
736        r = rr;
737        error = errno;
738      }
739    }
740    node = rtems_chain_next(node);
741  }
742
743  if (rc_conf->verbose)
744    printf("rc.conf: services done\n");
745
746  lock(rc_conf);
747
748  if (r < 0)
749    rc_conf->error_code = error;
750
751  /*
752   * If there is a waiter signal else clean up because the waiter has gone.
753   */
754  if (rc_conf->waiter != 0) {
755    rtems_event_send(rc_conf->waiter, RTEMS_EVENT_1);
756    unlock(rc_conf);
757  }
758  else {
759    unlock(rc_conf);
760    rc_conf_destroy(rc_conf);
761  }
762
763  if (rc_conf->verbose)
764    printf("rc.conf: finished\n");
765
766  rtems_task_delete(RTEMS_SELF);
767}
768
769int
770rtems_bsd_run_rc_conf_script(const char* name,
771                             const char* text,
772                             int         timeout,
773                             bool        verbose)
774{
775  rtems_bsd_rc_conf*  rc_conf;
776  rtems_task_priority priority;
777  rtems_id            worker;
778  rtems_status_code   sc;
779  int                 r = 0;
780
781  if (verbose)
782    printf("rc.conf: start: %s size:%lu, timeout: %i\n",
783           name, strlen(text), timeout);
784
785  r = rc_conf_create(&rc_conf, name, text, timeout, verbose);
786  if (r < 0) {
787    fprintf(stderr, "error: %s: parse error: %s\n",
788            name, strerror(errno));
789    return -1;
790  }
791
792  sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
793  if (sc != RTEMS_SUCCESSFUL) {
794    fprintf(stderr, "error: %s: get priority: %s\n",
795            name, rtems_status_text(sc));
796    errno = EIO;
797    return -1;
798  }
799
800  sc = rtems_task_create(rtems_build_name('B', 'S', 'D', 'r' ),
801                         priority,
802                         32 * 1024,
803                         RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
804                         RTEMS_LOCAL | RTEMS_FLOATING_POINT,
805                         &worker);
806  if (sc != RTEMS_SUCCESSFUL) {
807    fprintf (stderr, "error: worker create: %s", rtems_status_text(sc));
808    errno = EIO;
809    return -1;
810  }
811
812  sc = rtems_task_start(worker,
813                        rc_conf_worker,
814                        (rtems_task_argument) rc_conf);
815  if (sc != RTEMS_SUCCESSFUL) {
816    fprintf (stderr, "error: worker start: %s", rtems_status_text(sc));
817    errno = EIO;
818    return - 1;
819  }
820
821  if (timeout >= 0) {
822    rtems_event_set out = 0;
823    rtems_interval  ticks;
824
825    if (timeout == 0)
826      ticks = RTEMS_NO_TIMEOUT;
827    else
828      ticks = RTEMS_MICROSECONDS_TO_TICKS(timeout * 1000000UL);
829
830    sc = rtems_event_receive(RTEMS_EVENT_1,
831                             RTEMS_WAIT | RTEMS_EVENT_ANY,
832                             ticks,
833                             &out);
834    if (sc != RTEMS_SUCCESSFUL) {
835      if (sc != RTEMS_TIMEOUT) {
836        fprintf (stderr, "error: worker event in: %s", rtems_status_text(sc));
837        errno = EIO;
838      }
839      else {
840        lock(rc_conf);
841        rc_conf->waiter = 0;
842        unlock(rc_conf);
843        errno = ETIMEDOUT;
844      }
845      r = -1;
846    }
847    else {
848      lock(rc_conf);
849      errno = rc_conf->error_code;
850      if (errno != 0)
851        r = -1;
852      unlock(rc_conf);
853      rc_conf_destroy(rc_conf);
854    }
855  }
856
857  return r;
858}
859
860int
861rtems_bsd_run_rc_conf(const char* name, int timeout, bool verbose)
862{
863  struct stat sb;
864  int         r;
865  char*       rc_conf;
866  FILE*       file;
867
868  r = stat(name, &sb);
869  if (r < 0)
870    return r;
871
872  rc_conf = malloc(sb.st_size);
873  if (rc_conf == NULL) {
874    errno = ENOMEM;
875    return -1;
876  }
877
878  if (verbose)
879    printf("rc.conf: loading: %s\n", name);
880
881  file = fopen(name, "r");
882  if (file == NULL) {
883    free(rc_conf);
884    return -1;
885  }
886
887  if (fread(rc_conf, 1, sb.st_size, file) != sb.st_size) {
888    fclose(file);
889    free(rc_conf);
890    return -1;
891  }
892
893  fclose(file);
894
895  r = rtems_bsd_run_rc_conf_script(name, rc_conf, timeout, verbose);
896
897  free(rc_conf);
898
899  return r;
900}
901
902int
903rtems_bsd_run_etc_rc_conf(int timeout, bool verbose)
904{
905  return rtems_bsd_run_rc_conf("/etc/rc.conf", timeout, verbose);
906}
907
908const char*
909rtems_bsd_rc_conf_name(rtems_bsd_rc_conf* rc_conf)
910{
911  return rc_conf->name;
912}
913
914int
915rtems_bsd_rc_conf_line(rtems_bsd_rc_conf* rc_conf)
916{
917  return rc_conf->line + 1;
918}
919
920bool
921rtems_bsd_rc_conf_verbose(rtems_bsd_rc_conf* rc_conf)
922{
923  return rc_conf->verbose;
924}
925
926void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf,
927                                 const char*        name,
928                                 int                argc,
929                                 const char**       argv)
930{
931  if (rc_conf->verbose) {
932    int arg;
933    printf("rc.conf: %s: %s:", rc_conf->name, name);
934    for (arg = 0; arg < argc; ++arg)
935      printf(" %s", argv[arg]);
936    printf("\n");
937  }
938}
Note: See TracBrowser for help on using the repository browser.