File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / sysdep / unix / main.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 19:50:23 2021 UTC (4 years ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, HEAD
bird 1.6.8

    1: /*
    2:  *	BIRD Internet Routing Daemon -- Unix Entry Point
    3:  *
    4:  *	(c) 1998--2000 Martin Mares <mj@ucw.cz>
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  */
    8: 
    9: #undef LOCAL_DEBUG
   10: 
   11: #ifndef _GNU_SOURCE
   12: #define _GNU_SOURCE
   13: #endif
   14: 
   15: #include <stdio.h>
   16: #include <stdlib.h>
   17: #include <fcntl.h>
   18: #include <unistd.h>
   19: #include <signal.h>
   20: #include <pwd.h>
   21: #include <grp.h>
   22: #include <sys/stat.h>
   23: #include <libgen.h>
   24: 
   25: #include "nest/bird.h"
   26: #include "lib/lists.h"
   27: #include "lib/resource.h"
   28: #include "lib/socket.h"
   29: #include "lib/event.h"
   30: #include "lib/string.h"
   31: #include "nest/route.h"
   32: #include "nest/protocol.h"
   33: #include "nest/iface.h"
   34: #include "nest/cli.h"
   35: #include "nest/locks.h"
   36: #include "conf/conf.h"
   37: #include "filter/filter.h"
   38: 
   39: #include "unix.h"
   40: #include "krt.h"
   41: 
   42: /*
   43:  *	Debugging
   44:  */
   45: 
   46: #ifdef DEBUGGING
   47: static int debug_flag = 1;
   48: #else
   49: static int debug_flag = 0;
   50: #endif
   51: 
   52: void
   53: async_dump(void)
   54: {
   55:   debug("INTERNAL STATE DUMP\n\n");
   56: 
   57:   rdump(&root_pool);
   58:   sk_dump_all();
   59:   tm_dump_all();
   60:   if_dump_all();
   61:   neigh_dump_all();
   62:   rta_dump_all();
   63:   rt_dump_all();
   64:   protos_dump_all();
   65: 
   66:   debug("\n");
   67: }
   68: 
   69: /*
   70:  *	Dropping privileges
   71:  */
   72: 
   73: #ifdef CONFIG_RESTRICTED_PRIVILEGES
   74: #include "lib/syspriv.h"
   75: #else
   76: 
   77: static inline void
   78: drop_uid(uid_t uid UNUSED)
   79: {
   80:   die("Cannot change user on this platform");
   81: }
   82: 
   83: #endif
   84: 
   85: static inline void
   86: drop_gid(gid_t gid)
   87: {
   88:   if (setgid(gid) < 0)
   89:     die("setgid: %m");
   90: 
   91:   if (setgroups(0, NULL) < 0)
   92:     die("setgroups: %m");
   93: }
   94: 
   95: /*
   96:  *	Reading the Configuration
   97:  */
   98: 
   99: #ifdef PATH_IPROUTE_DIR
  100: 
  101: static inline void
  102: add_num_const(char *name, int val)
  103: {
  104:   struct symbol *s = cf_get_symbol(name);
  105:   s->class = SYM_CONSTANT | T_INT;
  106:   s->def = cfg_allocz(sizeof(struct f_val));
  107:   SYM_TYPE(s) = T_INT;
  108:   SYM_VAL(s).i = val;
  109: }
  110: 
  111: /* the code of read_iproute_table() is based on
  112:    rtnl_tab_initialize() from iproute2 package */
  113: static void
  114: read_iproute_table(char *file, char *prefix, int max)
  115: {
  116:   char buf[512], namebuf[512];
  117:   char *name;
  118:   int val;
  119:   FILE *fp;
  120: 
  121:   strcpy(namebuf, prefix);
  122:   name = namebuf + strlen(prefix);
  123: 
  124:   fp = fopen(file, "r");
  125:   if (!fp)
  126:     return;
  127: 
  128:   while (fgets(buf, sizeof(buf), fp))
  129:   {
  130:     char *p = buf;
  131: 
  132:     while (*p == ' ' || *p == '\t')
  133:       p++;
  134: 
  135:     if (*p == '#' || *p == '\n' || *p == 0)
  136:       continue;
  137:    
  138:     if (sscanf(p, "0x%x %s\n", &val, name) != 2 &&
  139: 	sscanf(p, "0x%x %s #", &val, name) != 2 &&
  140: 	sscanf(p, "%d %s\n", &val, name) != 2 &&
  141: 	sscanf(p, "%d %s #", &val, name) != 2)
  142:       continue;
  143: 
  144:     if (val < 0 || val > max)
  145:       continue;
  146: 
  147:     for(p = name; *p; p++)
  148:       if ((*p < 'a' || *p > 'z') && (*p < '0' || *p > '9') && (*p != '_'))
  149: 	*p = '_';
  150: 
  151:     add_num_const(namebuf, val);
  152:   }
  153: 
  154:   fclose(fp);
  155: }
  156: 
  157: #endif // PATH_IPROUTE_DIR
  158: 
  159: 
  160: static char *config_name = PATH_CONFIG_FILE;
  161: 
  162: static int
  163: cf_read(byte *dest, uint len, int fd)
  164: {
  165:   int l = read(fd, dest, len);
  166:   if (l < 0)
  167:     cf_error("Read error");
  168:   return l;
  169: }
  170: 
  171: void
  172: sysdep_preconfig(struct config *c)
  173: {
  174:   init_list(&c->logfiles);
  175: 
  176:   c->latency_limit = UNIX_DEFAULT_LATENCY_LIMIT;
  177:   c->watchdog_warning = UNIX_DEFAULT_WATCHDOG_WARNING;
  178: 
  179: #ifdef PATH_IPROUTE_DIR
  180:   read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256);
  181:   read_iproute_table(PATH_IPROUTE_DIR "/rt_realms", "ipr_", 256);
  182:   read_iproute_table(PATH_IPROUTE_DIR "/rt_scopes", "ips_", 256);
  183:   read_iproute_table(PATH_IPROUTE_DIR "/rt_tables", "ipt_", 256);
  184: #endif
  185: }
  186: 
  187: int
  188: sysdep_commit(struct config *new, struct config *old UNUSED)
  189: {
  190:   log_switch(debug_flag, &new->logfiles, new->syslog_name);
  191:   return 0;
  192: }
  193: 
  194: static int
  195: unix_read_config(struct config **cp, char *name)
  196: {
  197:   struct config *conf = config_alloc(name);
  198:   int ret;
  199: 
  200:   *cp = conf;
  201:   conf->file_fd = open(name, O_RDONLY);
  202:   if (conf->file_fd < 0)
  203:     return 0;
  204:   cf_read_hook = cf_read;
  205:   ret = config_parse(conf);
  206:   close(conf->file_fd);
  207:   return ret;
  208: }
  209: 
  210: static struct config *
  211: read_config(void)
  212: {
  213:   struct config *conf;
  214: 
  215:   if (!unix_read_config(&conf, config_name))
  216:     {
  217:       if (conf->err_msg)
  218: 	die("%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  219:       else
  220: 	die("Unable to open configuration file %s: %m", config_name);
  221:     }
  222: 
  223:   return conf;
  224: }
  225: 
  226: void
  227: async_config(void)
  228: {
  229:   struct config *conf;
  230: 
  231:   log(L_INFO "Reconfiguration requested by SIGHUP");
  232:   if (!unix_read_config(&conf, config_name))
  233:     {
  234:       if (conf->err_msg)
  235: 	log(L_ERR "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  236:       else
  237: 	log(L_ERR "Unable to open configuration file %s: %m", config_name);
  238:       config_free(conf);
  239:     }
  240:   else
  241:     config_commit(conf, RECONFIG_HARD, 0);
  242: }
  243: 
  244: static struct config *
  245: cmd_read_config(char *name)
  246: {
  247:   struct config *conf;
  248: 
  249:   if (!name)
  250:     name = config_name;
  251: 
  252:   cli_msg(-2, "Reading configuration from %s", name);
  253:   if (!unix_read_config(&conf, name))
  254:     {
  255:       if (conf->err_msg)
  256: 	cli_msg(8002, "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  257:       else
  258: 	cli_msg(8002, "%s: %m", name);
  259:       config_free(conf);
  260:       conf = NULL;
  261:     }
  262: 
  263:   return conf;
  264: }
  265: 
  266: void
  267: cmd_check_config(char *name)
  268: {
  269:   struct config *conf = cmd_read_config(name);
  270:   if (!conf)
  271:     return;
  272: 
  273:   cli_msg(20, "Configuration OK");
  274:   config_free(conf);
  275: }
  276: 
  277: static void
  278: cmd_reconfig_msg(int r)
  279: {
  280:   switch (r)
  281:     {
  282:     case CONF_DONE:	cli_msg( 3, "Reconfigured"); break;
  283:     case CONF_PROGRESS: cli_msg( 4, "Reconfiguration in progress"); break;
  284:     case CONF_QUEUED:	cli_msg( 5, "Reconfiguration already in progress, queueing new config"); break;
  285:     case CONF_UNQUEUED:	cli_msg(17, "Reconfiguration already in progress, removing queued config"); break;
  286:     case CONF_CONFIRM:	cli_msg(18, "Reconfiguration confirmed"); break;
  287:     case CONF_SHUTDOWN:	cli_msg( 6, "Reconfiguration ignored, shutting down"); break;
  288:     case CONF_NOTHING:	cli_msg(19, "Nothing to do"); break;
  289:     default:		break;
  290:     }
  291: }
  292: 
  293: /* Hack for scheduled undo notification */
  294: cli *cmd_reconfig_stored_cli;
  295: 
  296: void
  297: cmd_reconfig_undo_notify(void)
  298: {
  299:   if (cmd_reconfig_stored_cli)
  300:     {
  301:       cli *c = cmd_reconfig_stored_cli;
  302:       cli_printf(c, CLI_ASYNC_CODE, "Config timeout expired, starting undo");
  303:       cli_write_trigger(c);
  304:     }
  305: }
  306: 
  307: void
  308: cmd_reconfig(char *name, int type, int timeout)
  309: {
  310:   if (cli_access_restricted())
  311:     return;
  312: 
  313:   struct config *conf = cmd_read_config(name);
  314:   if (!conf)
  315:     return;
  316: 
  317:   int r = config_commit(conf, type, timeout);
  318: 
  319:   if ((r >= 0) && (timeout > 0))
  320:     {
  321:       cmd_reconfig_stored_cli = this_cli;
  322:       cli_msg(-22, "Undo scheduled in %d s", timeout);
  323:     }
  324: 
  325:   cmd_reconfig_msg(r);
  326: }
  327: 
  328: void
  329: cmd_reconfig_confirm(void)
  330: {
  331:   if (cli_access_restricted())
  332:     return;
  333: 
  334:   int r = config_confirm();
  335:   cmd_reconfig_msg(r);
  336: }
  337: 
  338: void
  339: cmd_reconfig_undo(void)
  340: {
  341:   if (cli_access_restricted())
  342:     return;
  343: 
  344:   cli_msg(-21, "Undo requested");
  345: 
  346:   int r = config_undo();
  347:   cmd_reconfig_msg(r);
  348: }
  349: 
  350: /*
  351:  *	Command-Line Interface
  352:  */
  353: 
  354: static sock *cli_sk;
  355: static char *path_control_socket = PATH_CONTROL_SOCKET;
  356: 
  357: 
  358: static void
  359: cli_write(cli *c)
  360: {
  361:   sock *s = c->priv;
  362: 
  363:   while (c->tx_pos)
  364:     {
  365:       struct cli_out *o = c->tx_pos;
  366: 
  367:       int len = o->wpos - o->outpos;
  368:       s->tbuf = o->outpos;
  369:       o->outpos = o->wpos;
  370: 
  371:       if (sk_send(s, len) <= 0)
  372: 	return;
  373: 
  374:       c->tx_pos = o->next;
  375:     }
  376: 
  377:   /* Everything is written */
  378:   s->tbuf = NULL;
  379:   cli_written(c);
  380: }
  381: 
  382: void
  383: cli_write_trigger(cli *c)
  384: {
  385:   sock *s = c->priv;
  386: 
  387:   if (s->tbuf == NULL)
  388:     cli_write(c);
  389: }
  390: 
  391: static void
  392: cli_tx(sock *s)
  393: {
  394:   cli_write(s->data);
  395: }
  396: 
  397: int
  398: cli_get_command(cli *c)
  399: {
  400:   sock *s = c->priv;
  401:   byte *t = c->rx_aux ? : s->rbuf;
  402:   byte *tend = s->rpos;
  403:   byte *d = c->rx_pos;
  404:   byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2;
  405: 
  406:   while (t < tend)
  407:     {
  408:       if (*t == '\r')
  409: 	t++;
  410:       else if (*t == '\n')
  411: 	{
  412: 	  t++;
  413: 	  c->rx_pos = c->rx_buf;
  414: 	  c->rx_aux = t;
  415: 	  *d = 0;
  416: 	  return (d < dend) ? 1 : -1;
  417: 	}
  418:       else if (d < dend)
  419: 	*d++ = *t++;
  420:     }
  421:   c->rx_aux = s->rpos = s->rbuf;
  422:   c->rx_pos = d;
  423:   return 0;
  424: }
  425: 
  426: static int
  427: cli_rx(sock *s, uint size UNUSED)
  428: {
  429:   cli_kick(s->data);
  430:   return 0;
  431: }
  432: 
  433: static void
  434: cli_err(sock *s, int err)
  435: {
  436:   if (config->cli_debug)
  437:     {
  438:       if (err)
  439: 	log(L_INFO "CLI connection dropped: %s", strerror(err));
  440:       else
  441: 	log(L_INFO "CLI connection closed");
  442:     }
  443:   cli_free(s->data);
  444: }
  445: 
  446: static int
  447: cli_connect(sock *s, uint size UNUSED)
  448: {
  449:   cli *c;
  450: 
  451:   if (config->cli_debug)
  452:     log(L_INFO "CLI connect");
  453:   s->rx_hook = cli_rx;
  454:   s->tx_hook = cli_tx;
  455:   s->err_hook = cli_err;
  456:   s->data = c = cli_new(s);
  457:   s->pool = c->pool;		/* We need to have all the socket buffers allocated in the cli pool */
  458:   s->fast_rx = 1;
  459:   c->rx_pos = c->rx_buf;
  460:   c->rx_aux = NULL;
  461:   rmove(s, c->pool);
  462:   return 1;
  463: }
  464: 
  465: static void
  466: cli_init_unix(uid_t use_uid, gid_t use_gid)
  467: {
  468:   sock *s;
  469: 
  470:   cli_init();
  471:   s = cli_sk = sk_new(cli_pool);
  472:   s->type = SK_UNIX_PASSIVE;
  473:   s->rx_hook = cli_connect;
  474:   s->rbsize = 1024;
  475:   s->fast_rx = 1;
  476: 
  477:   /* Return value intentionally ignored */
  478:   unlink(path_control_socket);
  479: 
  480:   if (sk_open_unix(s, path_control_socket) < 0)
  481:     die("Cannot create control socket %s: %m", path_control_socket);
  482: 
  483:   if (use_uid || use_gid)
  484:     if (chown(path_control_socket, use_uid, use_gid) < 0)
  485:       die("chown: %m");
  486: 
  487:   if (chmod(path_control_socket, 0660) < 0)
  488:     die("chmod: %m");
  489: }
  490: 
  491: /*
  492:  *	PID file
  493:  */
  494: 
  495: static char *pid_file;
  496: static int pid_fd;
  497: 
  498: static inline void
  499: open_pid_file(void)
  500: {
  501:   if (!pid_file)
  502:     return;
  503: 
  504:   pid_fd = open(pid_file, O_WRONLY|O_CREAT, 0664);
  505:   if (pid_fd < 0)
  506:     die("Cannot create PID file %s: %m", pid_file);
  507: }
  508: 
  509: static inline void
  510: write_pid_file(void)
  511: {
  512:   int pl, rv;
  513:   char ps[24];
  514: 
  515:   if (!pid_file)
  516:     return;
  517: 
  518:   /* We don't use PID file for uniqueness, so no need for locking */
  519: 
  520:   pl = bsnprintf(ps, sizeof(ps), "%ld\n", (long) getpid());
  521:   if (pl < 0)
  522:     bug("PID buffer too small");
  523: 
  524:   rv = ftruncate(pid_fd, 0);
  525:   if (rv < 0)
  526:     die("fruncate: %m");
  527:     
  528:   rv = write(pid_fd, ps, pl);
  529:   if(rv < 0)
  530:     die("write: %m");
  531: 
  532:   close(pid_fd);
  533: }
  534: 
  535: static inline void
  536: unlink_pid_file(void)
  537: {
  538:   if (pid_file)
  539:     unlink(pid_file);
  540: }
  541: 
  542: 
  543: /*
  544:  *	Shutdown
  545:  */
  546: 
  547: void
  548: cmd_shutdown(void)
  549: {
  550:   if (cli_access_restricted())
  551:     return;
  552: 
  553:   cli_msg(7, "Shutdown requested");
  554:   order_shutdown();
  555: }
  556: 
  557: void
  558: async_shutdown(void)
  559: {
  560:   DBG("Shutting down...\n");
  561:   order_shutdown();
  562: }
  563: 
  564: void
  565: sysdep_shutdown_done(void)
  566: {
  567:   unlink_pid_file();
  568:   unlink(path_control_socket);
  569:   log_msg(L_FATAL "Shutdown completed");
  570:   exit(0);
  571: }
  572: 
  573: /*
  574:  *	Signals
  575:  */
  576: 
  577: static void
  578: handle_sighup(int sig UNUSED)
  579: {
  580:   DBG("Caught SIGHUP...\n");
  581:   async_config_flag = 1;
  582: }
  583: 
  584: static void
  585: handle_sigusr(int sig UNUSED)
  586: {
  587:   DBG("Caught SIGUSR...\n");
  588:   async_dump_flag = 1;
  589: }
  590: 
  591: static void
  592: handle_sigterm(int sig UNUSED)
  593: {
  594:   DBG("Caught SIGTERM...\n");
  595:   async_shutdown_flag = 1;
  596: }
  597: 
  598: void watchdog_sigalrm(int sig UNUSED);
  599: 
  600: static void
  601: signal_init(void)
  602: {
  603:   struct sigaction sa;
  604: 
  605:   bzero(&sa, sizeof(sa));
  606:   sa.sa_handler = handle_sigusr;
  607:   sa.sa_flags = SA_RESTART;
  608:   sigaction(SIGUSR1, &sa, NULL);
  609:   sa.sa_handler = handle_sighup;
  610:   sa.sa_flags = SA_RESTART;
  611:   sigaction(SIGHUP, &sa, NULL);
  612:   sa.sa_handler = handle_sigterm;
  613:   sa.sa_flags = SA_RESTART;
  614:   sigaction(SIGTERM, &sa, NULL);
  615:   sa.sa_handler = watchdog_sigalrm;
  616:   sa.sa_flags = 0;
  617:   sigaction(SIGALRM, &sa, NULL);
  618:   signal(SIGPIPE, SIG_IGN);
  619: }
  620: 
  621: /*
  622:  *	Parsing of command-line arguments
  623:  */
  624: 
  625: static char *opt_list = "c:dD:ps:P:u:g:flRh";
  626: static int parse_and_exit;
  627: char *bird_name;
  628: static char *use_user;
  629: static char *use_group;
  630: static int run_in_foreground = 0;
  631: 
  632: static void
  633: display_usage(void)
  634: {
  635:   fprintf(stderr, "Usage: %s [--version] [--help] [-c <config-file>] [OPTIONS]\n", bird_name);
  636: }
  637: 
  638: static void
  639: display_help(void)
  640: {
  641:   display_usage();
  642: 
  643:   fprintf(stderr,
  644:     "\n"
  645:     "Options: \n"
  646:     "  -c <config-file>     Use given configuration file instead\n"
  647:     "                       of prefix/etc/bird.conf\n"
  648:     "  -d                   Enable debug messages and run bird in foreground\n"
  649:     "  -D <debug-file>      Log debug messages to given file instead of stderr\n"
  650:     "  -f                   Run bird in foreground\n"
  651:     "  -g <group>           Use given group ID\n"
  652:     "  -h, --help           Display this information\n"
  653:     "  -l                   Look for a configuration file and a communication socket\n"
  654:     "                       file in the current working directory\n"
  655:     "  -p                   Test configuration file and exit without start\n"
  656:     "  -P <pid-file>        Create a PID file with given filename\n"
  657:     "  -R                   Apply graceful restart recovery after start\n"
  658:     "  -s <control-socket>  Use given filename for a control socket\n"
  659:     "  -u <user>            Drop privileges and use given user ID\n"
  660:     "  --version            Display version of BIRD\n");
  661: 
  662:   exit(0);
  663: }
  664: 
  665: static void
  666: display_version(void)
  667: {
  668:   fprintf(stderr, "BIRD version " BIRD_VERSION "\n");
  669:   exit(0);
  670: }
  671: 
  672: static inline char *
  673: get_bird_name(char *s, char *def)
  674: {
  675:   char *t;
  676:   if (!s)
  677:     return def;
  678:   t = strrchr(s, '/');
  679:   if (!t)
  680:     return s;
  681:   if (!t[1])
  682:     return def;
  683:   return t+1;
  684: }
  685: 
  686: static inline uid_t
  687: get_uid(const char *s)
  688: {
  689:   struct passwd *pw;
  690:   char *endptr;
  691:   long int rv;
  692: 
  693:   if (!s)
  694:     return 0;
  695: 
  696:   errno = 0;
  697:   rv = strtol(s, &endptr, 10);
  698: 
  699:   if (!errno && !*endptr)
  700:     return rv;
  701: 
  702:   pw = getpwnam(s);
  703:   if (!pw)
  704:     die("Cannot find user '%s'", s);
  705: 
  706:   return pw->pw_uid;
  707: }
  708: 
  709: static inline gid_t
  710: get_gid(const char *s)
  711: {
  712:   struct group *gr;
  713:   char *endptr;
  714:   long int rv;
  715: 
  716:   if (!s)
  717:     return 0;
  718: 
  719:   errno = 0;
  720:   rv = strtol(s, &endptr, 10);
  721: 
  722:   if (!errno && !*endptr)
  723:     return rv;
  724: 
  725:   gr = getgrnam(s);
  726:   if (!gr)
  727:     die("Cannot find group '%s'", s);
  728: 
  729:   return gr->gr_gid;
  730: }
  731: 
  732: static void
  733: parse_args(int argc, char **argv)
  734: {
  735:   int config_changed = 0;
  736:   int socket_changed = 0;
  737:   int c;
  738: 
  739:   bird_name = get_bird_name(argv[0], "bird");
  740:   if (argc == 2)
  741:     {
  742:       if (!strcmp(argv[1], "--version"))
  743: 	display_version();
  744:       if (!strcmp(argv[1], "--help"))
  745: 	display_help();
  746:     }
  747:   while ((c = getopt(argc, argv, opt_list)) >= 0)
  748:     switch (c)
  749:       {
  750:       case 'c':
  751: 	config_name = optarg;
  752: 	config_changed = 1;
  753: 	break;
  754:       case 'd':
  755: 	debug_flag |= 1;
  756: 	break;
  757:       case 'D':
  758: 	log_init_debug(optarg);
  759: 	debug_flag |= 2;
  760: 	break;
  761:       case 'p':
  762: 	parse_and_exit = 1;
  763: 	break;
  764:       case 's':
  765: 	path_control_socket = optarg;
  766: 	socket_changed = 1;
  767: 	break;
  768:       case 'P':
  769: 	pid_file = optarg;
  770: 	break;
  771:       case 'u':
  772: 	use_user = optarg;
  773: 	break;
  774:       case 'g':
  775: 	use_group = optarg;
  776: 	break;
  777:       case 'f':
  778: 	run_in_foreground = 1;
  779: 	break;
  780:       case 'l':
  781: 	if (!config_changed)
  782: 	  config_name = xbasename(config_name);
  783: 	if (!socket_changed)
  784: 	  path_control_socket = xbasename(path_control_socket);
  785: 	break;
  786:       case 'R':
  787: 	graceful_restart_recovery();
  788: 	break;
  789:       case 'h':
  790: 	display_help();
  791: 	break;
  792:       default:
  793: 	fputc('\n', stderr);
  794: 	display_usage();
  795: 	exit(1);
  796:       }
  797:   if (optind < argc)
  798:    {
  799:      display_usage();
  800:      exit(1);
  801:    }
  802: }
  803: 
  804: /*
  805:  *	Hic Est main()
  806:  */
  807: 
  808: int
  809: main(int argc, char **argv)
  810: {
  811: #ifdef HAVE_LIBDMALLOC
  812:   if (!getenv("DMALLOC_OPTIONS"))
  813:     dmalloc_debug(0x2f03d00);
  814: #endif
  815: 
  816:   parse_args(argc, argv);
  817:   if (debug_flag == 1)
  818:     log_init_debug("");
  819:   log_switch(debug_flag, NULL, NULL);
  820: 
  821:   resource_init();
  822:   olock_init();
  823:   io_init();
  824:   rt_init();
  825:   if_init();
  826:   roa_init();
  827:   config_init();
  828: 
  829:   uid_t use_uid = get_uid(use_user);
  830:   gid_t use_gid = get_gid(use_group);
  831: 
  832:   if (!parse_and_exit)
  833:   {
  834:     test_old_bird(path_control_socket);
  835:     cli_init_unix(use_uid, use_gid);
  836:   }
  837: 
  838:   if (use_gid)
  839:     drop_gid(use_gid);
  840: 
  841:   if (use_uid)
  842:     drop_uid(use_uid);
  843: 
  844:   if (!parse_and_exit)
  845:     open_pid_file();
  846: 
  847:   protos_build();
  848:   proto_build(&proto_unix_kernel);
  849:   proto_build(&proto_unix_iface);
  850: 
  851:   struct config *conf = read_config();
  852: 
  853:   if (parse_and_exit)
  854:     exit(0);
  855: 
  856:   if (!(debug_flag||run_in_foreground))
  857:     {
  858:       pid_t pid = fork();
  859:       if (pid < 0)
  860: 	die("fork: %m");
  861:       if (pid)
  862: 	return 0;
  863:       setsid();
  864:       close(0);
  865:       if (open("/dev/null", O_RDWR) < 0)
  866: 	die("Cannot open /dev/null: %m");
  867:       dup2(0, 1);
  868:       dup2(0, 2);
  869:     }
  870: 
  871:   main_thread_init();
  872: 
  873:   write_pid_file();
  874: 
  875:   signal_init();
  876: 
  877:   config_commit(conf, RECONFIG_HARD, 0);
  878: 
  879:   graceful_restart_init();
  880: 
  881: #ifdef LOCAL_DEBUG
  882:   async_dump_flag = 1;
  883: #endif
  884: 
  885:   log(L_INFO "Started");
  886:   DBG("Entering I/O loop.\n");
  887: 
  888:   io_loop();
  889:   bug("I/O loop died");
  890: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>