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