Annotation of embedaddon/bird/sysdep/unix/main.c, revision 1.1.1.2

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");
1.1.1.2 ! misho      90: 
        !            91:   if (setgroups(0, NULL) < 0)
        !            92:     die("setgroups: %m");
1.1       misho      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)
1.1.1.2 ! misho     218:        die("%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
1.1       misho     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)
1.1.1.2 ! misho     235:        log(L_ERR "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
1.1       misho     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)
1.1.1.2 ! misho     256:        cli_msg(8002, "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
1.1       misho     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>