Annotation of embedaddon/bird/sysdep/unix/main.c, revision 1.1.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>