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