Example #1
0
/* On USR signals, dump debug information */
static void _sig_usr(int sig) {
  mem_report(sig == SIGUSR1 ? 0 : "signal");
  signal(sig, _sig_usr);
}
Example #2
0
	~Dummy() {
		mem_report();
	}
Example #3
0
/* We need this */
int main(int argc, char *argv[]) {
  int optc, show_help, show_version, show_usage;
  char *local_file, *cmd_listen_port, *cmd_pid_file;
  int inetd_mode, no_daemon;

  /* Set up some globals */
  progname = argv[0];
  listen_port = x_strdup(DEFAULT_LISTEN_PORT);
  pid_file = (DEFAULT_PID_FILE ? x_strdup(DEFAULT_PID_FILE) : 0);

#ifndef DEBUG
  no_daemon = 0;
#else /* DEBUG */
  no_daemon = 1;
#endif /* DEBUG */
  local_file = cmd_listen_port = cmd_pid_file = 0;
  show_help = show_version = show_usage = inetd_mode = 0;
  while ((optc = getopt_long(argc, argv, GETOPTIONS, long_opts, NULL)) != -1) {
    switch (optc) {
      case 'h':
        show_help = 1;
        break;
      case 'v':
        show_version = 1;
        break;
      case 'D':
#ifndef DEBUG
        no_daemon = 1;
#else /* DEBUG */
        no_daemon = 0;
#endif /* DEBUG */
        break;
      case 'I':
        inetd_mode = 1;
        break;
      case 'P':
        free(cmd_listen_port);
        cmd_listen_port = x_strdup(optarg);
        break;
      case 'p':
        free(cmd_pid_file);
        cmd_pid_file = x_strdup(optarg);
        break;
      case 'f':
        free(local_file);
        local_file = x_strdup(optarg);
        break;
      default:
        show_usage = 1;
        break;
    }
  }

  if (show_usage || (optind < argc)) {
    _print_usage();
    return 1;
  }

  if (show_version) {
    _print_version();
    if (!show_help)
      return 0;
  }

  if (show_help) {
    _print_help();
    return 0;
  }

  /* If no -f was specified use the home directory */
  if (!local_file && !inetd_mode) {
    struct stat statinfo;
    struct passwd *pw;

    pw = getpwuid(geteuid());
    if (pw && pw->pw_dir) {
      local_file = x_sprintf("%s/%s", pw->pw_dir, USER_CONFIG_FILENAME);
      debug("Local config file: %s", local_file);
      if (!stat(local_file, &statinfo) && (statinfo.st_mode & 0077)) {
        fprintf(stderr, "%s: Permissions of %s must be 0700 or "
                        "more restrictive\n", progname, local_file);
        free(local_file);
        return 2;
      }
      if (cfg_read(local_file, &listen_port, &pid_file, &g)) {
        /* If the local one didn't exist, set to 0 so we open
           global one */
        free(local_file);
        local_file = 0;
      } else {
        config_file = x_strdup(local_file);
      }
    }
  } else if (local_file) {
    if (cfg_read(local_file, &listen_port, &pid_file, &g)) {
      /* This is fatal! */
      fprintf(stderr, "%s: Couldn't read configuration from %s: %s\n",
              progname, local_file, strerror(errno));
      free(local_file);
      return 2;
    } else {
      config_file = x_strdup(local_file);
    }
  }

  /* Read global config file if local one not found */
  if (!local_file) {
    char *global_file;

    /* Not fatal if it doesn't exist */
    global_file = x_sprintf("%s/%s", SYSCONFDIR, GLOBAL_CONFIG_FILENAME);
    debug("Global config file: %s", global_file);
    cfg_read(global_file, &listen_port, &pid_file, &g);
    config_file = x_strdup(global_file);
    free(global_file);
  } else {
    free(local_file);
  }

  /* Check we got some connection classes */
  if (!connclasses) {
    fprintf(stderr, "%s: No connection classes have been defined.\n", progname);
    return 2;
  }

  /* -P overrides config file */
  if (cmd_listen_port) {
    free(listen_port);
    listen_port = cmd_listen_port;
  }

  /* -p overrides pid file */
  if (cmd_pid_file) {
    free(pid_file);
    pid_file = cmd_pid_file;
  }

  /* Set signal handlers */
  signal(SIGTERM, _sig_term);
  signal(SIGINT, _sig_term);
  signal(SIGHUP, _sig_hup);
  signal(SIGCHLD, _sig_child);
#ifdef DEBUG_MEMORY
  signal(SIGUSR1, _sig_usr);
  signal(SIGUSR2, _sig_usr);
#endif /* DEBUG_MEMORY */

  /* Broken Pipe?  This means that someone disconnected while we were
     sending stuff.  Naughty! */
  signal(SIGPIPE, SIG_IGN);

  if (!inetd_mode) {
    debug("Ordinary console dodge-monkey mode");

    /* Make listening socket before we fork */
    if (ircnet_listen(listen_port)) {
      fprintf(stderr, "%s: Unable to establish listen port\n", progname);
      return 3;
    }

    /* go daemon here */
    if (!no_daemon) {
      switch (go_daemon()) {
        case -1:
          return -1;
        case 0:
          break;
        default:
          return 0;
      }
    }

  } else {
    /* running under inetd means we are backgrounded right *now* */
    in_background = 1;

    debug("Inetd SuperTed mode!");

    /* Hook STDIN into a new proxy */
    ircnet_hooksocket(STDIN_FILENO);
  }
 
  /* Open a connection to syslog if we're in the background */
  if (in_background)
    openlog(PACKAGE, LOG_PID, LOG_USER);

  if (pid_file) {
    FILE *pidfile;

    pidfile = fopen(pid_file, "w");
    if (pidfile) {
      fchmod(fileno(pidfile), 0600);
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    } else {
      syscall_fail("fopen", pid_file, 0);
    }
  }
  
  /* Main loop! */
  while (!stop_poll) {
    int ns, nt, status;
    pid_t pid;

    ircnet_expunge_proxies();
    dccnet_expunge_proxies();
    ns = net_poll();
    nt = timer_poll();

    /* Reap any children */
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
      debug("Reaped process %d, exit status %d", pid, status);
      
      /* Handle any DNS children */
      dns_endrequest(pid, status);
    }

    /* Reload the configuration file? */
    if (reload_config) {
      _reload_config();
      reload_config = 0;
    }

    if (!ns && !nt)
      break;
  }

  if (pid_file) {
    unlink(pid_file);
  }

  /* Free up stuff */
  ircnet_flush();
  dccnet_flush();
  dns_flush();
  timer_flush();

  /* Do a lingering close on all sockets */
  net_closeall();
  net_flush();

  /* Close down and free up memory */
  if (!inetd_mode && !no_daemon)
    closelog();
  free(listen_port);
  free(pid_file);
  free(config_file);

#ifdef DEBUG_MEMORY
  mem_report("termination");
#endif /* DEBUG_MEMORY */

  return 0;
}