/** * Parse command line options to initialize global options * * @param[in] argc number of command line arguments * @param[in] argv arguments provided by the command line */ static void parse_cmdline(int argc, char *argv[]) { /* long options */ static const struct option long_opt[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, #ifdef DEBUG {"debug", no_argument, 0, 'd'}, #endif /* DEBUG */ {NULL, 0, NULL, 0} }; /* short options */ #ifdef HAVE_LIBPCAP static const char *short_opt = "b:c:dhp:w:v"; #else static const char *short_opt = "b:c:dhp:v"; #endif /* HAVE_LIBPCAP */ /* variables from getopt() */ extern char *optarg; /* the option argument */ extern int optind; /* index of the next element */ int ch = 0; /* getopt_long() return value */ /* parse command line */ while ((ch = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) { switch (ch) { case 'b': rpc_bind_addr = strdup(optarg); if (sscanf(optarg, "%s", rpc_bind_addr) != 1) { errx("failed to parse bind address"); usage(EXIT_FAILURE); } break; case 'c': if (sscanf(optarg, "%i", &cpu) != 1) { errx("failed to parse CPU number"); usage(EXIT_FAILURE); } break; case 'd': log_type = LOGTYPE_STDERR; increase_debuglevel(); break; case 'h': usage(EXIT_SUCCESS); break; case 'p': if (sscanf(optarg, "%u", &port) != 1) { errx("failed to parse port number"); usage(EXIT_FAILURE); } break; #ifdef HAVE_LIBPCAP case 'w': dump_dir = optarg; break; #endif /* HAVE_LIBPCAP */ case 'v': fprintf(stderr, "%s version: %s\n", progname, FLOWGRIND_VERSION); exit(EXIT_SUCCESS); /* unknown option or missing option-argument */ case '?': usage(EXIT_FAILURE); break; } } /* Do we have remaning command line arguments? */ if (optind < argc) { char *args = NULL; while (optind < argc) asprintf_append(&args, "%s ", argv[optind++]); errx("invalid arguments: %s", args); free(args); usage(EXIT_FAILURE); } // TODO more sanity checks... (e.g. if port is in valid range) }
static void parse_option(int argc, char ** argv) { int ch, rc; int argcorig = argc; #ifdef HAVE_GETOPT_LONG /* getopt_long isn't portable, it's GNU extension */ struct option lo[] = { {"help", 0, 0, 'h' }, {"version", 0, 0, 'v'}, {"debug", 0, 0, 'd'}, {0, 0, 0, 0} }; while ((ch = getopt_long(argc, argv, "dDhp:vVw:W:", lo, 0)) != -1) { #else while ((ch = getopt(argc, argv, "dDhp:vVw:W:")) != -1) { #endif switch (ch) { case 'h': usage(); break; case 'd': case 'D': log_type = LOGTYPE_STDERR; increase_debuglevel(); break; case 'p': rc = sscanf(optarg, "%u", &port); if (rc != 1) { fprintf(stderr, "failed to " "parse port number.\n"); usage(); } break; case 'v': case 'V': fprintf(stderr, "flowgrindd version: %s\n", FLOWGRIND_VERSION); exit(0); case 'w': case 'W': #ifdef HAVE_LIBPCAP dump_filename_prefix_server = optarg; break; #endif default: usage(); } } argc = argcorig; argc -= optind; if (argc != 0) usage(); } int main(int argc, char ** argv) { struct sigaction sa; xmlrpc_env env; /* update progname from argv[0] */ if (argc > 0) { /* Strip path */ char *tok = strrchr(argv[0], '/'); if (tok) tok++; else tok = argv[0]; if (*tok) { strncpy(progname, tok, sizeof(progname)); progname[sizeof(progname) - 1] = 0; } } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { error(ERR_FATAL, "Could not ignore SIGPIPE: %s", strerror(errno)); /* NOTREACHED */ } sa.sa_handler = sighandler; sa.sa_flags = 0; sigemptyset (&sa.sa_mask); sigaction (SIGHUP, &sa, NULL); sigaction (SIGALRM, &sa, NULL); sigaction (SIGCHLD, &sa, NULL); parse_option(argc, argv); logging_init(); #ifdef HAVE_LIBPCAP fg_pcap_init(); #endif if (log_type == LOGTYPE_SYSLOG) { /* Need to call daemon() before creating the thread because * it internally calls fork() which does not copy threads. */ if (daemon(0, 0) == -1) { error(ERR_FATAL, "daemon() failed: %s", strerror(errno)); } logging_log(LOG_NOTICE, "flowgrindd daemonized"); } create_daemon_thread(); xmlrpc_env_init(&env); run_rpc_server(&env, port); fprintf(stderr, "Control should never reach end of main()\n"); return 0; }