+ signal(SIGHUP, hup);
+ signal(SIGINT, hup);
+ signal(SIGUSR1, do_nothing); // Used in internal signalling.
+ signal(SIGPIPE, SIG_IGN);
+
+ // Parse options.
+ int state_fd = -1;
+ bool test_config = false;
+ for ( ;; ) {
+ static const option long_options[] = {
+ { "state", required_argument, 0, 's' },
+ { "test-config", no_argument, 0, 't' },
+ { 0, 0, 0, 0 }
+ };
+ int option_index = 0;
+ int c = getopt_long(argc, argv, "s:t", long_options, &option_index);
+
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 's':
+ state_fd = atoi(optarg);
+ break;
+ case 't':
+ test_config = true;
+ break;
+ default:
+ fprintf(stderr, "Unknown option '%s'\n", argv[option_index]);
+ exit(1);
+ }
+ }
+
+ string config_filename = "cubemap.config";
+ if (optind < argc) {
+ config_filename = argv[optind++];
+ }
+
+ // Canonicalize argv[0] and config_filename.
+ char argv0_canon[PATH_MAX];
+ char config_filename_canon[PATH_MAX];
+
+ if (realpath("/proc/self/exe", argv0_canon) == NULL) {
+ log_perror(argv[0]);
+ exit(1);
+ }
+ if (realpath(config_filename.c_str(), config_filename_canon) == NULL) {
+ log_perror(config_filename.c_str());
+ exit(1);
+ }
+
+ // Now parse the configuration file.
+ Config config;
+ if (!parse_config(config_filename_canon, &config)) {
+ exit(1);
+ }
+ if (test_config) {
+ exit(0);
+ }
+
+ // Ideally we'd like to daemonize only when we've started up all threads etc.,
+ // but daemon() forks, which is not good in multithreaded software, so we'll
+ // have to do it here.
+ if (config.daemonize) {
+ if (daemon(0, 0) == -1) {
+ log_perror("daemon");
+ exit(1);
+ }
+ }